1use std::cell::Cell;
9use std::collections::hash_map::Entry;
10use std::slice;
11
12use rustc_abi::{Align, ExternAbi, Size};
13use rustc_ast::{AttrStyle, MetaItemKind, ast};
14use rustc_attr_parsing::{AttributeParser, Late};
15use rustc_data_structures::fx::FxHashMap;
16use rustc_data_structures::thin_vec::ThinVec;
17use rustc_data_structures::unord::UnordMap;
18use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey};
19use rustc_feature::{
20 ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
21 BuiltinAttribute,
22};
23use rustc_hir::attrs::{
24 AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr,
25 MirDialect, MirPhase, ReprAttr, SanitizerSet,
26};
27use rustc_hir::def::DefKind;
28use rustc_hir::def_id::LocalModDefId;
29use rustc_hir::intravisit::{self, Visitor};
30use rustc_hir::{
31 self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, HirId, Item, ItemKind,
32 MethodKind, PartialConstStability, Safety, Stability, StabilityLevel, Target, TraitItem,
33 find_attr,
34};
35use rustc_macros::LintDiagnostic;
36use rustc_middle::hir::nested_filter;
37use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
38use rustc_middle::query::Providers;
39use rustc_middle::traits::ObligationCause;
40use rustc_middle::ty::error::{ExpectedFound, TypeError};
41use rustc_middle::ty::{self, TyCtxt, TypingMode};
42use rustc_middle::{bug, span_bug};
43use rustc_session::config::CrateType;
44use rustc_session::lint;
45use rustc_session::lint::builtin::{
46 CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MISPLACED_DIAGNOSTIC_ATTRIBUTES,
47 UNUSED_ATTRIBUTES,
48};
49use rustc_session::parse::feature_err;
50use rustc_span::edition::Edition;
51use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, sym};
52use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
53use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs};
54use rustc_trait_selection::traits::ObligationCtxt;
55use tracing::debug;
56
57use crate::{errors, fluent_generated as fluent};
58
59#[derive(const _: () =
{
impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for
DiagnosticOnUnimplementedOnlyForTraits {
#[track_caller]
fn decorate_lint<'__b>(self,
diag: &'__b mut rustc_errors::Diag<'__a, ()>) {
match self {
DiagnosticOnUnimplementedOnlyForTraits => {
diag.primary_message(crate::fluent_generated::passes_diagnostic_diagnostic_on_unimplemented_only_for_traits);
;
diag
}
};
}
}
};LintDiagnostic)]
60#[diag(passes_diagnostic_diagnostic_on_unimplemented_only_for_traits)]
61struct DiagnosticOnUnimplementedOnlyForTraits;
62
63#[derive(const _: () =
{
impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for
DiagnosticOnConstOnlyForTraitImpls {
#[track_caller]
fn decorate_lint<'__b>(self,
diag: &'__b mut rustc_errors::Diag<'__a, ()>) {
match self {
DiagnosticOnConstOnlyForTraitImpls { item_span: __binding_0
} => {
diag.primary_message(crate::fluent_generated::passes_diagnostic_diagnostic_on_const_only_for_trait_impls);
;
diag.span_label(__binding_0,
crate::fluent_generated::_subdiag::label);
diag
}
};
}
}
};LintDiagnostic)]
64#[diag(passes_diagnostic_diagnostic_on_const_only_for_trait_impls)]
65struct DiagnosticOnConstOnlyForTraitImpls {
66 #[label]
67 item_span: Span,
68}
69
70fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target {
71 match impl_item.kind {
72 hir::ImplItemKind::Const(..) => Target::AssocConst,
73 hir::ImplItemKind::Fn(..) => {
74 let parent_def_id = tcx.hir_get_parent_item(impl_item.hir_id()).def_id;
75 let containing_item = tcx.hir_expect_item(parent_def_id);
76 let containing_impl_is_for_trait = match &containing_item.kind {
77 hir::ItemKind::Impl(impl_) => impl_.of_trait.is_some(),
78 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("parent of an ImplItem must be an Impl"))bug!("parent of an ImplItem must be an Impl"),
79 };
80 if containing_impl_is_for_trait {
81 Target::Method(MethodKind::Trait { body: true })
82 } else {
83 Target::Method(MethodKind::Inherent)
84 }
85 }
86 hir::ImplItemKind::Type(..) => Target::AssocTy,
87 }
88}
89
90#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for ItemLike<'tcx> {
#[inline]
fn clone(&self) -> ItemLike<'tcx> {
let _: ::core::clone::AssertParamIsClone<&'tcx Item<'tcx>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for ItemLike<'tcx> { }Copy)]
91enum ItemLike<'tcx> {
92 Item(&'tcx Item<'tcx>),
93 ForeignItem,
94}
95
96#[derive(#[automatically_derived]
impl ::core::marker::Copy for ProcMacroKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for ProcMacroKind {
#[inline]
fn clone(&self) -> ProcMacroKind { *self }
}Clone)]
97pub(crate) enum ProcMacroKind {
98 FunctionLike,
99 Derive,
100 Attribute,
101}
102
103impl IntoDiagArg for ProcMacroKind {
104 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
105 match self {
106 ProcMacroKind::Attribute => "attribute proc macro",
107 ProcMacroKind::Derive => "derive proc macro",
108 ProcMacroKind::FunctionLike => "function-like proc macro",
109 }
110 .into_diag_arg(&mut None)
111 }
112}
113
114struct CheckAttrVisitor<'tcx> {
115 tcx: TyCtxt<'tcx>,
116
117 abort: Cell<bool>,
119}
120
121impl<'tcx> CheckAttrVisitor<'tcx> {
122 fn dcx(&self) -> DiagCtxtHandle<'tcx> {
123 self.tcx.dcx()
124 }
125
126 fn check_attributes(
128 &self,
129 hir_id: HirId,
130 span: Span,
131 target: Target,
132 item: Option<ItemLike<'_>>,
133 ) {
134 let mut seen = FxHashMap::default();
135 let attrs = self.tcx.hir_attrs(hir_id);
136 for attr in attrs {
137 let mut style = None;
138 match attr {
139 Attribute::Parsed(AttributeKind::ProcMacro(_)) => {
140 self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
141 }
142 Attribute::Parsed(AttributeKind::ProcMacroAttribute(_)) => {
143 self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
144 }
145 Attribute::Parsed(AttributeKind::ProcMacroDerive { .. }) => {
146 self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
147 }
148 Attribute::Parsed(
149 AttributeKind::Stability {
150 span: attr_span,
151 stability: Stability { level, feature },
152 }
153 | AttributeKind::ConstStability {
154 span: attr_span,
155 stability: PartialConstStability { level, feature, .. },
156 },
157 ) => self.check_stability(*attr_span, span, level, *feature),
158 Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => {
160 self.check_inline(hir_id, *attr_span, kind, target)
161 }
162 Attribute::Parsed(AttributeKind::LoopMatch(attr_span)) => {
163 self.check_loop_match(hir_id, *attr_span, target)
164 }
165 Attribute::Parsed(AttributeKind::ConstContinue(attr_span)) => {
166 self.check_const_continue(hir_id, *attr_span, target)
167 }
168 Attribute::Parsed(AttributeKind::AllowInternalUnsafe(attr_span) | AttributeKind::AllowInternalUnstable(.., attr_span)) => {
169 self.check_macro_only_attr(*attr_span, span, target, attrs)
170 }
171 Attribute::Parsed(AttributeKind::AllowConstFnUnstable(_, first_span)) => {
172 self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target)
173 }
174 Attribute::Parsed(AttributeKind::Deprecation {span: attr_span, .. }) => {
175 self.check_deprecated(hir_id, *attr_span, target)
176 }
177 Attribute::Parsed(AttributeKind::TargetFeature{ attr_span, ..}) => {
178 self.check_target_feature(hir_id, *attr_span, target, attrs)
179 }
180 Attribute::Parsed(AttributeKind::RustcObjectLifetimeDefault) => {
181 self.check_object_lifetime_default(hir_id);
182 }
183 &Attribute::Parsed(AttributeKind::PubTransparent(attr_span)) => {
184 self.check_rustc_pub_transparent(attr_span, span, attrs)
185 }
186 Attribute::Parsed(AttributeKind::Align { align, span: attr_span }) => {
187 self.check_align(*align, *attr_span)
188 }
189 Attribute::Parsed(AttributeKind::Naked(..)) => {
190 self.check_naked(hir_id, target)
191 }
192 Attribute::Parsed(AttributeKind::TrackCaller(attr_span)) => {
193 self.check_track_caller(hir_id, *attr_span, attrs, target)
194 }
195 Attribute::Parsed(AttributeKind::NonExhaustive(attr_span)) => {
196 self.check_non_exhaustive(*attr_span, span, target, item)
197 }
198 &Attribute::Parsed(AttributeKind::FfiPure(attr_span)) => {
199 self.check_ffi_pure(attr_span, attrs)
200 }
201 Attribute::Parsed(AttributeKind::MayDangle(attr_span)) => {
202 self.check_may_dangle(hir_id, *attr_span)
203 }
204 &Attribute::Parsed(AttributeKind::CustomMir(dialect, phase, attr_span)) => {
205 self.check_custom_mir(dialect, phase, attr_span)
206 }
207 &Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, rtsan: _, span: attr_span}) => {
208 self.check_sanitize(attr_span, on_set | off_set, span, target);
209 },
210 Attribute::Parsed(AttributeKind::Link(_, attr_span)) => {
211 self.check_link(hir_id, *attr_span, span, target)
212 },
213 Attribute::Parsed(AttributeKind::MacroExport { span, .. }) => {
214 self.check_macro_export(hir_id, *span, target)
215 },
216 Attribute::Parsed(AttributeKind::RustcLegacyConstGenerics{attr_span, fn_indexes}) => {
217 self.check_rustc_legacy_const_generics(item, *attr_span, fn_indexes)
218 },
219 Attribute::Parsed(AttributeKind::Doc(attr)) => self.check_doc_attrs(attr, hir_id, target),
220 Attribute::Parsed(AttributeKind::EiiImpls(impls)) => {
221 self.check_eii_impl(impls, target)
222 },
223 Attribute::Parsed(AttributeKind::RustcMustImplementOneOf { attr_span, fn_names }) => {
224 self.check_rustc_must_implement_one_of(*attr_span, fn_names, hir_id,target)
225 },
226 Attribute::Parsed(AttributeKind::DoNotRecommend{attr_span}) => {self.check_do_not_recommend(*attr_span, hir_id, target, item)},
227 Attribute::Parsed(
228 AttributeKind::EiiDeclaration { .. }
229 | AttributeKind::EiiForeignItem
230 | AttributeKind::BodyStability { .. }
231 | AttributeKind::ConstStabilityIndirect
232 | AttributeKind::MacroTransparency(_)
233 | AttributeKind::CollapseDebugInfo(..)
234 | AttributeKind::CfgTrace(..)
235 | AttributeKind::Pointee(..)
236 | AttributeKind::Dummy
237 | AttributeKind::RustcBuiltinMacro { .. }
238 | AttributeKind::Ignore { .. }
239 | AttributeKind::InstructionSet(..)
240 | AttributeKind::Path(..)
241 | AttributeKind::NoImplicitPrelude(..)
242 | AttributeKind::AutomaticallyDerived(..)
243 | AttributeKind::Marker(..)
244 | AttributeKind::SkipDuringMethodDispatch { .. }
245 | AttributeKind::Coinductive(..)
246 | AttributeKind::DenyExplicitImpl(..)
247 | AttributeKind::DoNotImplementViaObject(..)
248 | AttributeKind::SpecializationTrait(..)
249 | AttributeKind::UnsafeSpecializationMarker(..)
250 | AttributeKind::ParenSugar(..)
251 | AttributeKind::AllowIncoherentImpl(..)
252 | AttributeKind::Confusables { .. }
253 | AttributeKind::TypeConst{..}
254 | AttributeKind::DocComment {..}
256 | AttributeKind::Repr { .. }
258 | AttributeKind::Cold(..)
259 | AttributeKind::ExportName { .. }
260 | AttributeKind::Fundamental
261 | AttributeKind::Optimize(..)
262 | AttributeKind::LinkSection { .. }
263 | AttributeKind::MacroUse { .. }
264 | AttributeKind::MacroEscape( .. )
265 | AttributeKind::NoLink
266 | AttributeKind::RustcNoImplicitAutorefs
267 | AttributeKind::RustcLayoutScalarValidRangeStart(..)
268 | AttributeKind::RustcLayoutScalarValidRangeEnd(..)
269 | AttributeKind::RustcLintDiagnostics
270 | AttributeKind::RustcLintOptDenyFieldAccess { .. }
271 | AttributeKind::RustcLintOptTy
272 | AttributeKind::RustcLintQueryInstability
273 | AttributeKind::RustcLintUntrackedQueryInformation
274 | AttributeKind::RustcNeverReturnsNullPointer
275 | AttributeKind::RustcScalableVector { .. }
276 | AttributeKind::RustcSimdMonomorphizeLaneLimit(..)
277 | AttributeKind::RustcShouldNotBeCalledOnConstItems(..)
278 | AttributeKind::ExportStable
279 | AttributeKind::FfiConst(..)
280 | AttributeKind::UnstableFeatureBound(..)
281 | AttributeKind::AsPtr(..)
282 | AttributeKind::LinkName { .. }
283 | AttributeKind::LinkOrdinal { .. }
284 | AttributeKind::NoMangle(..)
285 | AttributeKind::Used { .. }
286 | AttributeKind::PassByValue (..)
287 | AttributeKind::StdInternalSymbol (..)
288 | AttributeKind::Coverage (..)
289 | AttributeKind::ShouldPanic { .. }
290 | AttributeKind::Coroutine(..)
291 | AttributeKind::Linkage(..)
292 | AttributeKind::MustUse { .. }
293 | AttributeKind::CrateName { .. }
294 | AttributeKind::RecursionLimit { .. }
295 | AttributeKind::MoveSizeLimit { .. }
296 | AttributeKind::TypeLengthLimit { .. }
297 | AttributeKind::PatternComplexityLimit { .. }
298 | AttributeKind::NoCore { .. }
299 | AttributeKind::NoStd { .. }
300 | AttributeKind::ObjcClass { .. }
301 | AttributeKind::ObjcSelector { .. }
302 | AttributeKind::RustcCoherenceIsCore(..)
303 | AttributeKind::DebuggerVisualizer(..)
304 | AttributeKind::RustcMain
305 | AttributeKind::RustcPassIndirectlyInNonRusticAbis(..)
306 | AttributeKind::PinV2(..)
307 | AttributeKind::WindowsSubsystem(..)
308 | AttributeKind::CfgAttrTrace
309 | AttributeKind::ThreadLocal
310 | AttributeKind::CfiEncoding { .. }
311 | AttributeKind::RustcHasIncoherentInherentImpls
312 | AttributeKind::MustNotSupend { .. }
313 | AttributeKind::RustcDumpUserArgs
314 | AttributeKind::RustcDumpItemBounds
315 | AttributeKind::RustcDumpPredicates
316 | AttributeKind::RustcDumpDefParents
317 | AttributeKind::RustcDumpVtable(..)
318 ) => { }
319 Attribute::Unparsed(attr_item) => {
320 style = Some(attr_item.style);
321 match attr.path().as_slice() {
322 [sym::diagnostic, sym::on_unimplemented, ..] => {
323 self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
324 }
325 [sym::diagnostic, sym::on_const, ..] => {
326 self.check_diagnostic_on_const(attr.span(), hir_id, target, item)
327 }
328 [sym::rustc_clean, ..]
329 | [sym::rustc_dirty, ..]
330 | [sym::rustc_if_this_changed, ..]
331 | [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr),
332 [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
333 self.check_autodiff(hir_id, attr, span, target)
334 }
335 [
336 sym::allow
338 | sym::expect
339 | sym::warn
340 | sym::deny
341 | sym::forbid
342 | sym::patchable_function_entry | sym::deprecated_safe | sym::prelude_import
347 | sym::panic_handler
348 | sym::lang
349 | sym::needs_allocator
350 | sym::default_lib_allocator
351 | sym::rustc_diagnostic_item
352 | sym::rustc_no_mir_inline
353 | sym::rustc_insignificant_dtor
354 | sym::rustc_nonnull_optimization_guaranteed
355 | sym::rustc_intrinsic
356 | sym::rustc_inherit_overflow_checks
357 | sym::rustc_intrinsic_const_stable_indirect
358 | sym::rustc_trivial_field_reads
359 | sym::rustc_on_unimplemented
360 | sym::rustc_do_not_const_check
361 | sym::rustc_reservation_impl
362 | sym::rustc_doc_primitive
363 | sym::rustc_allocator
364 | sym::rustc_deallocator
365 | sym::rustc_reallocator
366 | sym::rustc_conversion_suggestion
367 | sym::rustc_allocator_zeroed
368 | sym::rustc_allocator_zeroed_variant
369 | sym::rustc_deprecated_safe_2024
370 | sym::rustc_test_marker
371 | sym::rustc_abi
372 | sym::rustc_layout
373 | sym::rustc_proc_macro_decls
374 | sym::rustc_never_type_options
375 | sym::rustc_autodiff
376 | sym::rustc_capture_analysis
377 | sym::rustc_regions
378 | sym::rustc_strict_coherence
379 | sym::rustc_variance
380 | sym::rustc_variance_of_opaques
381 | sym::rustc_hidden_type_of_opaques
382 | sym::rustc_mir
383 | sym::rustc_effective_visibility
384 | sym::rustc_outlives
385 | sym::rustc_symbol_name
386 | sym::rustc_evaluate_where_clauses
387 | sym::rustc_delayed_bug_from_inside_query
388 | sym::rustc_def_path
389 | sym::rustc_partition_reused
390 | sym::rustc_partition_codegened
391 | sym::rustc_expected_cgu_reuse
392 | sym::rustc_nounwind,
393 ..
394 ] => {}
395 [name, rest@..] => {
396 match BUILTIN_ATTRIBUTE_MAP.get(name) {
397 Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) => {}
399 Some(_) => {
400 if rest.len() > 0 && AttributeParser::<Late>::is_parsed_attribute(slice::from_ref(name)) {
401 continue
405 }
406
407 ::rustc_middle::util::bug::span_bug_fmt(attr.span(),
format_args!("builtin attribute {0:?} not handled by `CheckAttrVisitor`",
name))span_bug!(
408 attr.span(),
409 "builtin attribute {name:?} not handled by `CheckAttrVisitor`"
410 )
411 }
412 None => (),
413 }
414 }
415 [] => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
416 }
417 }
418 }
419
420 if hir_id != CRATE_HIR_ID {
421 match attr {
422 Attribute::Parsed(_) => { }
423 Attribute::Unparsed(attr) => {
424 if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) =
427 attr.path
428 .segments
429 .first()
430 .and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name))
431 {
432 match attr.style {
433 ast::AttrStyle::Outer => {
434 let attr_span = attr.span;
435 let bang_position = self
436 .tcx
437 .sess
438 .source_map()
439 .span_until_char(attr_span, '[')
440 .shrink_to_hi();
441
442 self.tcx.emit_node_span_lint(
443 UNUSED_ATTRIBUTES,
444 hir_id,
445 attr.span,
446 errors::OuterCrateLevelAttr {
447 suggestion: errors::OuterCrateLevelAttrSuggestion {
448 bang_position,
449 },
450 },
451 )
452 }
453 ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
454 UNUSED_ATTRIBUTES,
455 hir_id,
456 attr.span,
457 errors::InnerCrateLevelAttr,
458 ),
459 }
460 }
461 }
462 }
463 }
464
465 if let Attribute::Unparsed(unparsed_attr) = attr
466 && let Some(BuiltinAttribute { duplicates, .. }) =
467 attr.name().and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name))
468 {
469 check_duplicates(
470 self.tcx,
471 unparsed_attr.span,
472 attr,
473 hir_id,
474 *duplicates,
475 &mut seen,
476 );
477 }
478
479 self.check_unused_attribute(hir_id, attr, style)
480 }
481
482 self.check_repr(attrs, span, target, item, hir_id);
483 self.check_rustc_force_inline(hir_id, attrs, target);
484 self.check_mix_no_mangle_export(hir_id, attrs);
485 }
486
487 fn check_rustc_must_implement_one_of(
488 &self,
489 attr_span: Span,
490 list: &ThinVec<Ident>,
491 hir_id: HirId,
492 target: Target,
493 ) {
494 if !#[allow(non_exhaustive_omitted_patterns)] match target {
Target::Trait => true,
_ => false,
}matches!(target, Target::Trait) {
497 return;
498 }
499
500 let def_id = hir_id.owner.def_id;
501
502 let items = self.tcx.associated_items(def_id);
503 for ident in list {
506 let item = items
507 .filter_by_name_unhygienic(ident.name)
508 .find(|item| item.ident(self.tcx) == *ident);
509
510 match item {
511 Some(item) if #[allow(non_exhaustive_omitted_patterns)] match item.kind {
ty::AssocKind::Fn { .. } => true,
_ => false,
}matches!(item.kind, ty::AssocKind::Fn { .. }) => {
512 if !item.defaultness(self.tcx).has_value() {
513 self.tcx.dcx().emit_err(errors::FunctionNotHaveDefaultImplementation {
514 span: self.tcx.def_span(item.def_id),
515 note_span: attr_span,
516 });
517 }
518 }
519 Some(item) => {
520 self.dcx().emit_err(errors::MustImplementNotFunction {
521 span: self.tcx.def_span(item.def_id),
522 span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
523 note: errors::MustImplementNotFunctionNote {},
524 });
525 }
526 None => {
527 self.dcx().emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
528 }
529 }
530 }
531 let mut set: UnordMap<Symbol, Span> = Default::default();
534
535 for ident in &*list {
536 if let Some(dup) = set.insert(ident.name, ident.span) {
537 self.tcx
538 .dcx()
539 .emit_err(errors::FunctionNamesDuplicated { spans: <[_]>::into_vec(::alloc::boxed::box_new([dup, ident.span]))vec![dup, ident.span] });
540 }
541 }
542 }
543
544 fn check_eii_impl(&self, impls: &[EiiImpl], target: Target) {
545 for EiiImpl { span, inner_span, resolution, impl_marked_unsafe, is_default: _ } in impls {
546 match target {
547 Target::Fn => {}
548 _ => {
549 self.dcx().emit_err(errors::EiiImplNotFunction { span: *span });
550 }
551 }
552
553 if let EiiImplResolution::Macro(eii_macro) = resolution
554 && {
{
'done:
{
for i in self.tcx.get_all_attrs(*eii_macro) {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::EiiDeclaration(EiiDecl {
impl_unsafe, .. })) if *impl_unsafe => {
break 'done Some(());
}
_ => {}
}
}
None
}
}.is_some()
}find_attr!(self.tcx.get_all_attrs(*eii_macro), AttributeKind::EiiDeclaration(EiiDecl { impl_unsafe, .. }) if *impl_unsafe)
555 && !impl_marked_unsafe
556 {
557 self.dcx().emit_err(errors::EiiImplRequiresUnsafe {
558 span: *span,
559 name: self.tcx.item_name(*eii_macro),
560 suggestion: errors::EiiImplRequiresUnsafeSuggestion {
561 left: inner_span.shrink_to_lo(),
562 right: inner_span.shrink_to_hi(),
563 },
564 });
565 }
566 }
567 }
568
569 fn check_do_not_recommend(
571 &self,
572 attr_span: Span,
573 hir_id: HirId,
574 target: Target,
575 item: Option<ItemLike<'_>>,
576 ) {
577 if !#[allow(non_exhaustive_omitted_patterns)] match target {
Target::Impl { .. } => true,
_ => false,
}matches!(target, Target::Impl { .. })
578 || #[allow(non_exhaustive_omitted_patterns)] match item {
Some(ItemLike::Item(hir::Item { kind: hir::ItemKind::Impl(_impl), .. }))
if _impl.of_trait.is_none() => true,
_ => false,
}matches!(
579 item,
580 Some(ItemLike::Item(hir::Item { kind: hir::ItemKind::Impl(_impl),.. }))
581 if _impl.of_trait.is_none()
582 )
583 {
584 self.tcx.emit_node_span_lint(
585 MISPLACED_DIAGNOSTIC_ATTRIBUTES,
586 hir_id,
587 attr_span,
588 errors::IncorrectDoNotRecommendLocation,
589 );
590 }
591 }
592
593 fn check_diagnostic_on_unimplemented(&self, attr_span: Span, hir_id: HirId, target: Target) {
595 if !#[allow(non_exhaustive_omitted_patterns)] match target {
Target::Trait => true,
_ => false,
}matches!(target, Target::Trait) {
596 self.tcx.emit_node_span_lint(
597 MISPLACED_DIAGNOSTIC_ATTRIBUTES,
598 hir_id,
599 attr_span,
600 DiagnosticOnUnimplementedOnlyForTraits,
601 );
602 }
603 }
604
605 fn check_diagnostic_on_const(
607 &self,
608 attr_span: Span,
609 hir_id: HirId,
610 target: Target,
611 item: Option<ItemLike<'_>>,
612 ) {
613 if target == (Target::Impl { of_trait: true }) {
614 match item.unwrap() {
615 ItemLike::Item(it) => match it.expect_impl().constness {
616 Constness::Const => {}
617 Constness::NotConst => return,
618 },
619 ItemLike::ForeignItem => {}
620 }
621 }
622 let item_span = self.tcx.hir_span(hir_id);
623 self.tcx.emit_node_span_lint(
624 MISPLACED_DIAGNOSTIC_ATTRIBUTES,
625 hir_id,
626 attr_span,
627 DiagnosticOnConstOnlyForTraitImpls { item_span },
628 );
629 }
630
631 fn check_inline(&self, hir_id: HirId, attr_span: Span, kind: &InlineAttr, target: Target) {
633 match target {
634 Target::Fn
635 | Target::Closure
636 | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {
637 if let Some(did) = hir_id.as_owner()
639 && self.tcx.def_kind(did).has_codegen_attrs()
640 && kind != &InlineAttr::Never
641 {
642 let attrs = self.tcx.codegen_fn_attrs(did);
643 if attrs.contains_extern_indicator() {
645 self.tcx.emit_node_span_lint(
646 UNUSED_ATTRIBUTES,
647 hir_id,
648 attr_span,
649 errors::InlineIgnoredForExported {},
650 );
651 }
652 }
653 }
654 _ => {}
655 }
656 }
657
658 fn check_sanitize(
661 &self,
662 attr_span: Span,
663 set: SanitizerSet,
664 target_span: Span,
665 target: Target,
666 ) {
667 let mut not_fn_impl_mod = None;
668 let mut no_body = None;
669
670 match target {
671 Target::Fn
672 | Target::Closure
673 | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
674 | Target::Impl { .. }
675 | Target::Mod => return,
676 Target::Static
677 if set & !(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
680 == SanitizerSet::empty() =>
681 {
682 return;
683 }
684
685 Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
688 no_body = Some(target_span);
689 }
690
691 _ => {
692 not_fn_impl_mod = Some(target_span);
693 }
694 }
695
696 self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
697 attr_span,
698 not_fn_impl_mod,
699 no_body,
700 help: (),
701 });
702 }
703
704 fn check_naked(&self, hir_id: HirId, target: Target) {
706 match target {
707 Target::Fn
708 | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {
709 let fn_sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
710 let abi = fn_sig.header.abi;
711 if abi.is_rustic_abi() && !self.tcx.features().naked_functions_rustic_abi() {
712 feature_err(
713 &self.tcx.sess,
714 sym::naked_functions_rustic_abi,
715 fn_sig.span,
716 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`#[naked]` is currently unstable on `extern \"{0}\"` functions",
abi.as_str()))
})format!(
717 "`#[naked]` is currently unstable on `extern \"{}\"` functions",
718 abi.as_str()
719 ),
720 )
721 .emit();
722 }
723 }
724 _ => {}
725 }
726 }
727
728 fn check_object_lifetime_default(&self, hir_id: HirId) {
730 let tcx = self.tcx;
731 if let Some(owner_id) = hir_id.as_owner()
732 && let Some(generics) = tcx.hir_get_generics(owner_id.def_id)
733 {
734 for p in generics.params {
735 let hir::GenericParamKind::Type { .. } = p.kind else { continue };
736 let default = tcx.object_lifetime_default(p.def_id);
737 let repr = match default {
738 ObjectLifetimeDefault::Empty => "BaseDefault".to_owned(),
739 ObjectLifetimeDefault::Static => "'static".to_owned(),
740 ObjectLifetimeDefault::Param(def_id) => tcx.item_name(def_id).to_string(),
741 ObjectLifetimeDefault::Ambiguous => "Ambiguous".to_owned(),
742 };
743 tcx.dcx().emit_err(errors::ObjectLifetimeErr { span: p.span, repr });
744 }
745 }
746 }
747
748 fn check_track_caller(
750 &self,
751 hir_id: HirId,
752 attr_span: Span,
753 attrs: &[Attribute],
754 target: Target,
755 ) {
756 match target {
757 Target::Fn => {
758 if let Some((lang_item, _)) = hir::lang_items::extract(attrs)
761 && let Some(item) = hir::LangItem::from_name(lang_item)
762 && item.is_weak()
763 {
764 let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
765
766 self.dcx().emit_err(errors::LangItemWithTrackCaller {
767 attr_span,
768 name: lang_item,
769 sig_span: sig.span,
770 });
771 }
772
773 if let Some(impls) = {
'done:
{
for i in attrs {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::EiiImpls(impls))
=> {
break 'done Some(impls);
}
_ => {}
}
}
None
}
}find_attr!(attrs, AttributeKind::EiiImpls(impls) => impls) {
774 let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
775 for i in impls {
776 let name = match i.resolution {
777 EiiImplResolution::Macro(def_id) => self.tcx.item_name(def_id),
778 EiiImplResolution::Known(decl) => decl.name.name,
779 EiiImplResolution::Error(_eg) => continue,
780 };
781 self.dcx().emit_err(errors::EiiWithTrackCaller {
782 attr_span,
783 name,
784 sig_span: sig.span,
785 });
786 }
787 }
788 }
789 _ => {}
790 }
791 }
792
793 fn check_non_exhaustive(
795 &self,
796 attr_span: Span,
797 span: Span,
798 target: Target,
799 item: Option<ItemLike<'_>>,
800 ) {
801 match target {
802 Target::Struct => {
803 if let Some(ItemLike::Item(hir::Item {
804 kind: hir::ItemKind::Struct(_, _, hir::VariantData::Struct { fields, .. }),
805 ..
806 })) = item
807 && !fields.is_empty()
808 && fields.iter().any(|f| f.default.is_some())
809 {
810 self.dcx().emit_err(errors::NonExhaustiveWithDefaultFieldValues {
811 attr_span,
812 defn_span: span,
813 });
814 }
815 }
816 _ => {}
817 }
818 }
819
820 fn check_target_feature(
822 &self,
823 hir_id: HirId,
824 attr_span: Span,
825 target: Target,
826 attrs: &[Attribute],
827 ) {
828 match target {
829 Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
830 | Target::Fn => {
831 if let Some((lang_item, _)) = hir::lang_items::extract(attrs)
833 && !self.tcx.sess.target.is_like_wasm
836 && !self.tcx.sess.opts.actually_rustdoc
837 {
838 let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap();
839
840 self.dcx().emit_err(errors::LangItemWithTargetFeature {
841 attr_span,
842 name: lang_item,
843 sig_span: sig.span,
844 });
845 }
846 }
847 _ => {}
848 }
849 }
850
851 fn check_doc_alias_value(&self, span: Span, hir_id: HirId, target: Target, alias: Symbol) {
852 if let Some(location) = match target {
853 Target::AssocTy => {
854 if let DefKind::Impl { .. } =
855 self.tcx.def_kind(self.tcx.local_parent(hir_id.owner.def_id))
856 {
857 Some("type alias in implementation block")
858 } else {
859 None
860 }
861 }
862 Target::AssocConst => {
863 let parent_def_id = self.tcx.hir_get_parent_item(hir_id).def_id;
864 let containing_item = self.tcx.hir_expect_item(parent_def_id);
865 let err = "associated constant in trait implementation block";
867 match containing_item.kind {
868 ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) => Some(err),
869 _ => None,
870 }
871 }
872 Target::Param => return,
874 Target::Expression
875 | Target::Statement
876 | Target::Arm
877 | Target::ForeignMod
878 | Target::Closure
879 | Target::Impl { .. }
880 | Target::WherePredicate => Some(target.name()),
881 Target::ExternCrate
882 | Target::Use
883 | Target::Static
884 | Target::Const
885 | Target::Fn
886 | Target::Mod
887 | Target::GlobalAsm
888 | Target::TyAlias
889 | Target::Enum
890 | Target::Variant
891 | Target::Struct
892 | Target::Field
893 | Target::Union
894 | Target::Trait
895 | Target::TraitAlias
896 | Target::Method(..)
897 | Target::ForeignFn
898 | Target::ForeignStatic
899 | Target::ForeignTy
900 | Target::GenericParam { .. }
901 | Target::MacroDef
902 | Target::PatField
903 | Target::ExprField
904 | Target::Crate
905 | Target::MacroCall
906 | Target::Delegation { .. } => None,
907 } {
908 self.tcx.dcx().emit_err(errors::DocAliasBadLocation { span, location });
909 return;
910 }
911 if self.tcx.hir_opt_name(hir_id) == Some(alias) {
912 self.tcx.dcx().emit_err(errors::DocAliasNotAnAlias { span, attr_str: alias });
913 return;
914 }
915 }
916
917 fn check_doc_fake_variadic(&self, span: Span, hir_id: HirId) {
918 let item_kind = match self.tcx.hir_node(hir_id) {
919 hir::Node::Item(item) => Some(&item.kind),
920 _ => None,
921 };
922 match item_kind {
923 Some(ItemKind::Impl(i)) => {
924 let is_valid = doc_fake_variadic_is_allowed_self_ty(i.self_ty)
925 || if let Some(&[hir::GenericArg::Type(ty)]) = i
926 .of_trait
927 .and_then(|of_trait| of_trait.trait_ref.path.segments.last())
928 .map(|last_segment| last_segment.args().args)
929 {
930 #[allow(non_exhaustive_omitted_patterns)] match &ty.kind {
hir::TyKind::Tup([_]) => true,
_ => false,
}matches!(&ty.kind, hir::TyKind::Tup([_]))
931 } else {
932 false
933 };
934 if !is_valid {
935 self.dcx().emit_err(errors::DocFakeVariadicNotValid { span });
936 }
937 }
938 _ => {
939 self.dcx().emit_err(errors::DocKeywordOnlyImpl { span });
940 }
941 }
942 }
943
944 fn check_doc_search_unbox(&self, span: Span, hir_id: HirId) {
945 let hir::Node::Item(item) = self.tcx.hir_node(hir_id) else {
946 self.dcx().emit_err(errors::DocSearchUnboxInvalid { span });
947 return;
948 };
949 match item.kind {
950 ItemKind::Enum(_, generics, _) | ItemKind::Struct(_, generics, _)
951 if generics.params.len() != 0 => {}
952 ItemKind::Trait(_, _, _, _, generics, _, items)
953 if generics.params.len() != 0
954 || items.iter().any(|item| {
955 #[allow(non_exhaustive_omitted_patterns)] match self.tcx.def_kind(item.owner_id)
{
DefKind::AssocTy => true,
_ => false,
}matches!(self.tcx.def_kind(item.owner_id), DefKind::AssocTy)
956 }) => {}
957 ItemKind::TyAlias(_, generics, _) if generics.params.len() != 0 => {}
958 _ => {
959 self.dcx().emit_err(errors::DocSearchUnboxInvalid { span });
960 }
961 }
962 }
963
964 fn check_doc_inline(&self, hir_id: HirId, target: Target, inline: &[(DocInline, Span)]) {
974 let span = match inline {
975 [] => return,
976 [(_, span)] => *span,
977 [(inline, span), rest @ ..] => {
978 for (inline2, span2) in rest {
979 if inline2 != inline {
980 let mut spans = MultiSpan::from_spans(<[_]>::into_vec(::alloc::boxed::box_new([*span, *span2]))vec![*span, *span2]);
981 spans.push_span_label(*span, fluent::passes_doc_inline_conflict_first);
982 spans.push_span_label(*span2, fluent::passes_doc_inline_conflict_second);
983 self.dcx().emit_err(errors::DocInlineConflict { spans });
984 return;
985 }
986 }
987 *span
988 }
989 };
990
991 match target {
992 Target::Use | Target::ExternCrate => {}
993 _ => {
994 self.tcx.emit_node_span_lint(
995 INVALID_DOC_ATTRIBUTES,
996 hir_id,
997 span,
998 errors::DocInlineOnlyUse {
999 attr_span: span,
1000 item_span: self.tcx.hir_span(hir_id),
1001 },
1002 );
1003 }
1004 }
1005 }
1006
1007 fn check_doc_masked(&self, span: Span, hir_id: HirId, target: Target) {
1008 if target != Target::ExternCrate {
1009 self.tcx.emit_node_span_lint(
1010 INVALID_DOC_ATTRIBUTES,
1011 hir_id,
1012 span,
1013 errors::DocMaskedOnlyExternCrate {
1014 attr_span: span,
1015 item_span: self.tcx.hir_span(hir_id),
1016 },
1017 );
1018 return;
1019 }
1020
1021 if self.tcx.extern_mod_stmt_cnum(hir_id.owner.def_id).is_none() {
1022 self.tcx.emit_node_span_lint(
1023 INVALID_DOC_ATTRIBUTES,
1024 hir_id,
1025 span,
1026 errors::DocMaskedNotExternCrateSelf {
1027 attr_span: span,
1028 item_span: self.tcx.hir_span(hir_id),
1029 },
1030 );
1031 }
1032 }
1033
1034 fn check_doc_keyword_and_attribute(&self, span: Span, hir_id: HirId, attr_name: &'static str) {
1035 let item_kind = match self.tcx.hir_node(hir_id) {
1036 hir::Node::Item(item) => Some(&item.kind),
1037 _ => None,
1038 };
1039 match item_kind {
1040 Some(ItemKind::Mod(_, module)) => {
1041 if !module.item_ids.is_empty() {
1042 self.dcx().emit_err(errors::DocKeywordAttributeEmptyMod { span, attr_name });
1043 return;
1044 }
1045 }
1046 _ => {
1047 self.dcx().emit_err(errors::DocKeywordAttributeNotMod { span, attr_name });
1048 return;
1049 }
1050 }
1051 }
1052
1053 fn check_doc_attrs(&self, attr: &DocAttribute, hir_id: HirId, target: Target) {
1060 let DocAttribute {
1061 aliases,
1062 hidden: _,
1065 inline,
1066 cfg: _,
1068 auto_cfg: _,
1070 auto_cfg_change: _,
1072 fake_variadic,
1073 keyword,
1074 masked,
1075 notable_trait: _,
1077 search_unbox,
1078 html_favicon_url: _,
1080 html_logo_url: _,
1082 html_playground_url: _,
1084 html_root_url: _,
1086 html_no_source: _,
1088 issue_tracker_base_url: _,
1090 rust_logo,
1091 test_attrs: _,
1093 no_crate_inject: _,
1095 attribute,
1096 } = attr;
1097
1098 for (alias, span) in aliases {
1099 self.check_doc_alias_value(*span, hir_id, target, *alias);
1100 }
1101
1102 if let Some((_, span)) = keyword {
1103 self.check_doc_keyword_and_attribute(*span, hir_id, "keyword");
1104 }
1105 if let Some((_, span)) = attribute {
1106 self.check_doc_keyword_and_attribute(*span, hir_id, "attribute");
1107 }
1108
1109 if let Some(span) = fake_variadic {
1110 self.check_doc_fake_variadic(*span, hir_id);
1111 }
1112
1113 if let Some(span) = search_unbox {
1114 self.check_doc_search_unbox(*span, hir_id);
1115 }
1116
1117 self.check_doc_inline(hir_id, target, inline);
1118
1119 if let Some(span) = rust_logo
1120 && !self.tcx.features().rustdoc_internals()
1121 {
1122 feature_err(
1123 &self.tcx.sess,
1124 sym::rustdoc_internals,
1125 *span,
1126 fluent::passes_doc_rust_logo,
1127 )
1128 .emit();
1129 }
1130
1131 if let Some(span) = masked {
1132 self.check_doc_masked(*span, hir_id, target);
1133 }
1134 }
1135
1136 fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute]) {
1137 if {
{
'done:
{
for i in attrs {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::FfiConst(_)) =>
{
break 'done Some(());
}
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, AttributeKind::FfiConst(_)) {
1138 self.dcx().emit_err(errors::BothFfiConstAndPure { attr_span });
1140 }
1141 }
1142
1143 fn check_may_dangle(&self, hir_id: HirId, attr_span: Span) {
1145 if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id)
1146 && #[allow(non_exhaustive_omitted_patterns)] match param.kind {
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { ..
} => true,
_ => false,
}matches!(
1147 param.kind,
1148 hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. }
1149 )
1150 && #[allow(non_exhaustive_omitted_patterns)] match param.source {
hir::GenericParamSource::Generics => true,
_ => false,
}matches!(param.source, hir::GenericParamSource::Generics)
1151 && let parent_hir_id = self.tcx.parent_hir_id(hir_id)
1152 && let hir::Node::Item(item) = self.tcx.hir_node(parent_hir_id)
1153 && let hir::ItemKind::Impl(impl_) = item.kind
1154 && let Some(of_trait) = impl_.of_trait
1155 && let Some(def_id) = of_trait.trait_ref.trait_def_id()
1156 && self.tcx.is_lang_item(def_id, hir::LangItem::Drop)
1157 {
1158 return;
1159 }
1160
1161 self.dcx().emit_err(errors::InvalidMayDangle { attr_span });
1162 }
1163
1164 fn check_link(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
1166 if target == Target::ForeignMod
1167 && let hir::Node::Item(item) = self.tcx.hir_node(hir_id)
1168 && let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item
1169 && !#[allow(non_exhaustive_omitted_patterns)] match abi {
ExternAbi::Rust => true,
_ => false,
}matches!(abi, ExternAbi::Rust)
1170 {
1171 return;
1172 }
1173
1174 self.tcx.emit_node_span_lint(
1175 UNUSED_ATTRIBUTES,
1176 hir_id,
1177 attr_span,
1178 errors::Link { span: (target != Target::ForeignMod).then_some(span) },
1179 );
1180 }
1181
1182 fn check_rustc_legacy_const_generics(
1184 &self,
1185 item: Option<ItemLike<'_>>,
1186 attr_span: Span,
1187 index_list: &ThinVec<(usize, Span)>,
1188 ) {
1189 let Some(ItemLike::Item(Item {
1190 kind: ItemKind::Fn { sig: FnSig { decl, .. }, generics, .. },
1191 ..
1192 })) = item
1193 else {
1194 return;
1196 };
1197
1198 for param in generics.params {
1199 match param.kind {
1200 hir::GenericParamKind::Const { .. } => {}
1201 _ => {
1202 self.dcx().emit_err(errors::RustcLegacyConstGenericsOnly {
1203 attr_span,
1204 param_span: param.span,
1205 });
1206 return;
1207 }
1208 }
1209 }
1210
1211 if index_list.len() != generics.params.len() {
1212 self.dcx().emit_err(errors::RustcLegacyConstGenericsIndex {
1213 attr_span,
1214 generics_span: generics.span,
1215 });
1216 return;
1217 }
1218
1219 let arg_count = decl.inputs.len() + generics.params.len();
1220 for (index, span) in index_list {
1221 if *index >= arg_count {
1222 self.dcx().emit_err(errors::RustcLegacyConstGenericsIndexExceed {
1223 span: *span,
1224 arg_count,
1225 });
1226 }
1227 }
1228 }
1229
1230 fn check_rustc_dirty_clean(&self, attr: &Attribute) {
1233 if !self.tcx.sess.opts.unstable_opts.query_dep_graph {
1234 self.dcx().emit_err(errors::RustcDirtyClean { span: attr.span() });
1235 }
1236 }
1237
1238 fn check_repr(
1240 &self,
1241 attrs: &[Attribute],
1242 span: Span,
1243 target: Target,
1244 item: Option<ItemLike<'_>>,
1245 hir_id: HirId,
1246 ) {
1247 let (reprs, first_attr_span) = {
'done:
{
for i in attrs {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::Repr {
reprs, first_span }) => {
break 'done Some((reprs.as_slice(), Some(*first_span)));
}
_ => {}
}
}
None
}
}find_attr!(attrs, AttributeKind::Repr { reprs, first_span } => (reprs.as_slice(), Some(*first_span))).unwrap_or((&[], None));
1253
1254 let mut int_reprs = 0;
1255 let mut is_explicit_rust = false;
1256 let mut is_c = false;
1257 let mut is_simd = false;
1258 let mut is_transparent = false;
1259
1260 for (repr, repr_span) in reprs {
1261 match repr {
1262 ReprAttr::ReprRust => {
1263 is_explicit_rust = true;
1264 match target {
1265 Target::Struct | Target::Union | Target::Enum => continue,
1266 _ => {
1267 self.dcx().emit_err(errors::AttrApplication::StructEnumUnion {
1268 hint_span: *repr_span,
1269 span,
1270 });
1271 }
1272 }
1273 }
1274 ReprAttr::ReprC => {
1275 is_c = true;
1276 match target {
1277 Target::Struct | Target::Union | Target::Enum => continue,
1278 _ => {
1279 self.dcx().emit_err(errors::AttrApplication::StructEnumUnion {
1280 hint_span: *repr_span,
1281 span,
1282 });
1283 }
1284 }
1285 }
1286 ReprAttr::ReprAlign(align) => {
1287 match target {
1288 Target::Struct | Target::Union | Target::Enum => {}
1289 Target::Fn | Target::Method(_) if self.tcx.features().fn_align() => {
1290 self.dcx().emit_err(errors::ReprAlignShouldBeAlign {
1291 span: *repr_span,
1292 item: target.plural_name(),
1293 });
1294 }
1295 Target::Static if self.tcx.features().static_align() => {
1296 self.dcx().emit_err(errors::ReprAlignShouldBeAlignStatic {
1297 span: *repr_span,
1298 item: target.plural_name(),
1299 });
1300 }
1301 _ => {
1302 self.dcx().emit_err(errors::AttrApplication::StructEnumUnion {
1303 hint_span: *repr_span,
1304 span,
1305 });
1306 }
1307 }
1308
1309 self.check_align(*align, *repr_span);
1310 }
1311 ReprAttr::ReprPacked(_) => {
1312 if target != Target::Struct && target != Target::Union {
1313 self.dcx().emit_err(errors::AttrApplication::StructUnion {
1314 hint_span: *repr_span,
1315 span,
1316 });
1317 } else {
1318 continue;
1319 }
1320 }
1321 ReprAttr::ReprSimd => {
1322 is_simd = true;
1323 if target != Target::Struct {
1324 self.dcx().emit_err(errors::AttrApplication::Struct {
1325 hint_span: *repr_span,
1326 span,
1327 });
1328 } else {
1329 continue;
1330 }
1331 }
1332 ReprAttr::ReprTransparent => {
1333 is_transparent = true;
1334 match target {
1335 Target::Struct | Target::Union | Target::Enum => continue,
1336 _ => {
1337 self.dcx().emit_err(errors::AttrApplication::StructEnumUnion {
1338 hint_span: *repr_span,
1339 span,
1340 });
1341 }
1342 }
1343 }
1344 ReprAttr::ReprInt(_) => {
1345 int_reprs += 1;
1346 if target != Target::Enum {
1347 self.dcx().emit_err(errors::AttrApplication::Enum {
1348 hint_span: *repr_span,
1349 span,
1350 });
1351 } else {
1352 continue;
1353 }
1354 }
1355 };
1356 }
1357
1358 if let Some(first_attr_span) = first_attr_span
1360 && reprs.is_empty()
1361 && item.is_some()
1362 {
1363 match target {
1364 Target::Struct | Target::Union | Target::Enum => {}
1365 Target::Fn | Target::Method(_) => {
1366 self.dcx().emit_err(errors::ReprAlignShouldBeAlign {
1367 span: first_attr_span,
1368 item: target.plural_name(),
1369 });
1370 }
1371 _ => {
1372 self.dcx().emit_err(errors::AttrApplication::StructEnumUnion {
1373 hint_span: first_attr_span,
1374 span,
1375 });
1376 }
1377 }
1378 return;
1379 }
1380
1381 let hint_spans = reprs.iter().map(|(_, span)| *span);
1384
1385 if is_transparent && reprs.len() > 1 {
1387 let hint_spans = hint_spans.clone().collect();
1388 self.dcx().emit_err(errors::TransparentIncompatible {
1389 hint_spans,
1390 target: target.to_string(),
1391 });
1392 }
1393 if is_transparent
1396 && let Some(&pass_indirectly_span) =
1397 {
'done:
{
for i in attrs {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::RustcPassIndirectlyInNonRusticAbis(span))
=> {
break 'done Some(span);
}
_ => {}
}
}
None
}
}find_attr!(attrs, AttributeKind::RustcPassIndirectlyInNonRusticAbis(span) => span)
1398 {
1399 self.dcx().emit_err(errors::TransparentIncompatible {
1400 hint_spans: <[_]>::into_vec(::alloc::boxed::box_new([span, pass_indirectly_span]))vec![span, pass_indirectly_span],
1401 target: target.to_string(),
1402 });
1403 }
1404 if is_explicit_rust && (int_reprs > 0 || is_c || is_simd) {
1405 let hint_spans = hint_spans.clone().collect();
1406 self.dcx().emit_err(errors::ReprConflicting { hint_spans });
1407 }
1408 if (int_reprs > 1)
1410 || (is_simd && is_c)
1411 || (int_reprs == 1
1412 && is_c
1413 && item.is_some_and(|item| {
1414 if let ItemLike::Item(item) = item { is_c_like_enum(item) } else { false }
1415 }))
1416 {
1417 self.tcx.emit_node_span_lint(
1418 CONFLICTING_REPR_HINTS,
1419 hir_id,
1420 hint_spans.collect::<Vec<Span>>(),
1421 errors::ReprConflictingLint,
1422 );
1423 }
1424 }
1425
1426 fn check_align(&self, align: Align, span: Span) {
1427 if align.bytes() > 2_u64.pow(29) {
1428 self.dcx().span_delayed_bug(
1430 span,
1431 "alignment greater than 2^29 should be errored on elsewhere",
1432 );
1433 } else {
1434 let max = Size::from_bits(self.tcx.sess.target.pointer_width).signed_int_max() as u64;
1439 if align.bytes() > max {
1440 self.dcx().emit_err(errors::InvalidReprAlignForTarget { span, size: max });
1441 }
1442 }
1443 }
1444
1445 fn check_macro_only_attr(
1450 &self,
1451 attr_span: Span,
1452 span: Span,
1453 target: Target,
1454 attrs: &[Attribute],
1455 ) {
1456 match target {
1457 Target::Fn => {
1458 for attr in attrs {
1459 if attr.is_proc_macro_attr() {
1460 return;
1462 }
1463 }
1464 self.tcx.dcx().emit_err(errors::MacroOnlyAttribute { attr_span, span });
1465 }
1466 _ => {}
1467 }
1468 }
1469
1470 fn check_rustc_allow_const_fn_unstable(
1473 &self,
1474 hir_id: HirId,
1475 attr_span: Span,
1476 span: Span,
1477 target: Target,
1478 ) {
1479 match target {
1480 Target::Fn | Target::Method(_) => {
1481 if !self.tcx.is_const_fn(hir_id.expect_owner().to_def_id()) {
1482 self.tcx.dcx().emit_err(errors::RustcAllowConstFnUnstable { attr_span, span });
1483 }
1484 }
1485 _ => {}
1486 }
1487 }
1488
1489 fn check_stability(
1490 &self,
1491 attr_span: Span,
1492 item_span: Span,
1493 level: &StabilityLevel,
1494 feature: Symbol,
1495 ) {
1496 if level.is_unstable()
1499 && ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some()
1500 {
1501 self.tcx
1502 .dcx()
1503 .emit_err(errors::UnstableAttrForAlreadyStableFeature { attr_span, item_span });
1504 }
1505 }
1506
1507 fn check_deprecated(&self, hir_id: HirId, attr_span: Span, target: Target) {
1508 match target {
1509 Target::AssocConst | Target::Method(..) | Target::AssocTy
1510 if self.tcx.def_kind(self.tcx.local_parent(hir_id.owner.def_id))
1511 == DefKind::Impl { of_trait: true } =>
1512 {
1513 self.tcx.emit_node_span_lint(
1514 UNUSED_ATTRIBUTES,
1515 hir_id,
1516 attr_span,
1517 errors::DeprecatedAnnotationHasNoEffect { span: attr_span },
1518 );
1519 }
1520 _ => {}
1521 }
1522 }
1523
1524 fn check_macro_export(&self, hir_id: HirId, attr_span: Span, target: Target) {
1525 if target != Target::MacroDef {
1526 return;
1527 }
1528
1529 let (_, macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro();
1531 let is_decl_macro = !macro_definition.macro_rules;
1532
1533 if is_decl_macro {
1534 self.tcx.emit_node_span_lint(
1535 UNUSED_ATTRIBUTES,
1536 hir_id,
1537 attr_span,
1538 errors::MacroExport::OnDeclMacro,
1539 );
1540 }
1541 }
1542
1543 fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute, style: Option<AttrStyle>) {
1544 let note = if attr.has_any_name(&[
1547 sym::allow,
1548 sym::expect,
1549 sym::warn,
1550 sym::deny,
1551 sym::forbid,
1552 sym::feature,
1553 ]) && attr.meta_item_list().is_some_and(|list| list.is_empty())
1554 {
1555 errors::UnusedNote::EmptyList { name: attr.name().unwrap() }
1556 } else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
1557 && let Some(meta) = attr.meta_item_list()
1558 && let [meta] = meta.as_slice()
1559 && let Some(item) = meta.meta_item()
1560 && let MetaItemKind::NameValue(_) = &item.kind
1561 && item.path == sym::reason
1562 {
1563 errors::UnusedNote::NoLints { name: attr.name().unwrap() }
1564 } else if attr.has_any_name(&[sym::allow, sym::warn, sym::deny, sym::forbid, sym::expect])
1565 && let Some(meta) = attr.meta_item_list()
1566 && meta.iter().any(|meta| {
1567 meta.meta_item().map_or(false, |item| item.path == sym::linker_messages)
1568 })
1569 {
1570 if hir_id != CRATE_HIR_ID {
1571 match style {
1572 Some(ast::AttrStyle::Outer) => {
1573 let attr_span = attr.span();
1574 let bang_position = self
1575 .tcx
1576 .sess
1577 .source_map()
1578 .span_until_char(attr_span, '[')
1579 .shrink_to_hi();
1580
1581 self.tcx.emit_node_span_lint(
1582 UNUSED_ATTRIBUTES,
1583 hir_id,
1584 attr_span,
1585 errors::OuterCrateLevelAttr {
1586 suggestion: errors::OuterCrateLevelAttrSuggestion { bang_position },
1587 },
1588 )
1589 }
1590 Some(ast::AttrStyle::Inner) | None => self.tcx.emit_node_span_lint(
1591 UNUSED_ATTRIBUTES,
1592 hir_id,
1593 attr.span(),
1594 errors::InnerCrateLevelAttr,
1595 ),
1596 };
1597 return;
1598 } else {
1599 let never_needs_link = self
1600 .tcx
1601 .crate_types()
1602 .iter()
1603 .all(|kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
CrateType::Rlib | CrateType::Staticlib => true,
_ => false,
}matches!(kind, CrateType::Rlib | CrateType::Staticlib));
1604 if never_needs_link {
1605 errors::UnusedNote::LinkerMessagesBinaryCrateOnly
1606 } else {
1607 return;
1608 }
1609 }
1610 } else if attr.has_name(sym::default_method_body_is_const) {
1611 errors::UnusedNote::DefaultMethodBodyConst
1612 } else {
1613 return;
1614 };
1615
1616 self.tcx.emit_node_span_lint(
1617 UNUSED_ATTRIBUTES,
1618 hir_id,
1619 attr.span(),
1620 errors::Unused { attr_span: attr.span(), note },
1621 );
1622 }
1623
1624 fn check_proc_macro(&self, hir_id: HirId, target: Target, kind: ProcMacroKind) {
1628 if target != Target::Fn {
1629 return;
1630 }
1631
1632 let tcx = self.tcx;
1633 let Some(token_stream_def_id) = tcx.get_diagnostic_item(sym::TokenStream) else {
1634 return;
1635 };
1636 let Some(token_stream) = tcx.type_of(token_stream_def_id).no_bound_vars() else {
1637 return;
1638 };
1639
1640 let def_id = hir_id.expect_owner().def_id;
1641 let param_env = ty::ParamEnv::empty();
1642
1643 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
1644 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
1645
1646 let span = tcx.def_span(def_id);
1647 let fresh_args = infcx.fresh_args_for_item(span, def_id.to_def_id());
1648 let sig = tcx.liberate_late_bound_regions(
1649 def_id.to_def_id(),
1650 tcx.fn_sig(def_id).instantiate(tcx, fresh_args),
1651 );
1652
1653 let mut cause = ObligationCause::misc(span, def_id);
1654 let sig = ocx.normalize(&cause, param_env, sig);
1655
1656 let errors = ocx.try_evaluate_obligations();
1658 if !errors.is_empty() {
1659 return;
1660 }
1661
1662 let expected_sig = tcx.mk_fn_sig(
1663 std::iter::repeat_n(
1664 token_stream,
1665 match kind {
1666 ProcMacroKind::Attribute => 2,
1667 ProcMacroKind::Derive | ProcMacroKind::FunctionLike => 1,
1668 },
1669 ),
1670 token_stream,
1671 false,
1672 Safety::Safe,
1673 ExternAbi::Rust,
1674 );
1675
1676 if let Err(terr) = ocx.eq(&cause, param_env, expected_sig, sig) {
1677 let mut diag = tcx.dcx().create_err(errors::ProcMacroBadSig { span, kind });
1678
1679 let hir_sig = tcx.hir_fn_sig_by_hir_id(hir_id);
1680 if let Some(hir_sig) = hir_sig {
1681 #[allow(rustc::diagnostic_outside_of_impl)] match terr {
1683 TypeError::ArgumentMutability(idx) | TypeError::ArgumentSorts(_, idx) => {
1684 if let Some(ty) = hir_sig.decl.inputs.get(idx) {
1685 diag.span(ty.span);
1686 cause.span = ty.span;
1687 } else if idx == hir_sig.decl.inputs.len() {
1688 let span = hir_sig.decl.output.span();
1689 diag.span(span);
1690 cause.span = span;
1691 }
1692 }
1693 TypeError::ArgCount => {
1694 if let Some(ty) = hir_sig.decl.inputs.get(expected_sig.inputs().len()) {
1695 diag.span(ty.span);
1696 cause.span = ty.span;
1697 }
1698 }
1699 TypeError::SafetyMismatch(_) => {
1700 }
1702 TypeError::AbiMismatch(_) => {
1703 }
1705 TypeError::VariadicMismatch(_) => {
1706 }
1708 _ => {}
1709 }
1710 }
1711
1712 infcx.err_ctxt().note_type_err(
1713 &mut diag,
1714 &cause,
1715 None,
1716 Some(param_env.and(ValuePairs::PolySigs(ExpectedFound {
1717 expected: ty::Binder::dummy(expected_sig),
1718 found: ty::Binder::dummy(sig),
1719 }))),
1720 terr,
1721 false,
1722 None,
1723 );
1724 diag.emit();
1725 self.abort.set(true);
1726 }
1727
1728 let errors = ocx.evaluate_obligations_error_on_ambiguity();
1729 if !errors.is_empty() {
1730 infcx.err_ctxt().report_fulfillment_errors(errors);
1731 self.abort.set(true);
1732 }
1733 }
1734
1735 fn check_rustc_pub_transparent(&self, attr_span: Span, span: Span, attrs: &[Attribute]) {
1736 if !{
'done:
{
for i in attrs {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::Repr { reprs, ..
}) => {
break 'done
Some(reprs.iter().any(|(r, _)|
r == &ReprAttr::ReprTransparent));
}
_ => {}
}
}
None
}
}find_attr!(attrs, AttributeKind::Repr { reprs, .. } => reprs.iter().any(|(r, _)| r == &ReprAttr::ReprTransparent))
1737 .unwrap_or(false)
1738 {
1739 self.dcx().emit_err(errors::RustcPubTransparent { span, attr_span });
1740 }
1741 }
1742
1743 fn check_rustc_force_inline(&self, hir_id: HirId, attrs: &[Attribute], target: Target) {
1744 if let (Target::Closure, None) = (
1745 target,
1746 {
'done:
{
for i in attrs {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force {
attr_span, .. }, _)) => {
break 'done Some(*attr_span);
}
_ => {}
}
}
None
}
}find_attr!(attrs, AttributeKind::Inline(InlineAttr::Force { attr_span, .. }, _) => *attr_span),
1747 ) {
1748 let is_coro = #[allow(non_exhaustive_omitted_patterns)] match self.tcx.hir_expect_expr(hir_id).kind
{
hir::ExprKind::Closure(hir::Closure {
kind: hir::ClosureKind::Coroutine(..) |
hir::ClosureKind::CoroutineClosure(..), .. }) => true,
_ => false,
}matches!(
1749 self.tcx.hir_expect_expr(hir_id).kind,
1750 hir::ExprKind::Closure(hir::Closure {
1751 kind: hir::ClosureKind::Coroutine(..) | hir::ClosureKind::CoroutineClosure(..),
1752 ..
1753 })
1754 );
1755 let parent_did = self.tcx.hir_get_parent_item(hir_id).to_def_id();
1756 let parent_span = self.tcx.def_span(parent_did);
1757
1758 if let Some(attr_span) = {
'done:
{
for i in self.tcx.get_all_attrs(parent_did) {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force {
attr_span, .. }, _)) => {
break 'done Some(*attr_span);
}
_ => {}
}
}
None
}
}find_attr!(
1759 self.tcx.get_all_attrs(parent_did),
1760 AttributeKind::Inline(InlineAttr::Force { attr_span, .. }, _) => *attr_span
1761 ) && is_coro
1762 {
1763 self.dcx().emit_err(errors::RustcForceInlineCoro { attr_span, span: parent_span });
1764 }
1765 }
1766 }
1767
1768 fn check_mix_no_mangle_export(&self, hir_id: HirId, attrs: &[Attribute]) {
1769 if let Some(export_name_span) = {
'done:
{
for i in attrs {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::ExportName {
span: export_name_span, .. }) => {
break 'done Some(*export_name_span);
}
_ => {}
}
}
None
}
}find_attr!(attrs, AttributeKind::ExportName { span: export_name_span, .. } => *export_name_span)
1770 && let Some(no_mangle_span) =
1771 {
'done:
{
for i in attrs {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::NoMangle(no_mangle_span))
=> {
break 'done Some(*no_mangle_span);
}
_ => {}
}
}
None
}
}find_attr!(attrs, AttributeKind::NoMangle(no_mangle_span) => *no_mangle_span)
1772 {
1773 let no_mangle_attr = if no_mangle_span.edition() >= Edition::Edition2024 {
1774 "#[unsafe(no_mangle)]"
1775 } else {
1776 "#[no_mangle]"
1777 };
1778 let export_name_attr = if export_name_span.edition() >= Edition::Edition2024 {
1779 "#[unsafe(export_name)]"
1780 } else {
1781 "#[export_name]"
1782 };
1783
1784 self.tcx.emit_node_span_lint(
1785 lint::builtin::UNUSED_ATTRIBUTES,
1786 hir_id,
1787 no_mangle_span,
1788 errors::MixedExportNameAndNoMangle {
1789 no_mangle_span,
1790 export_name_span,
1791 no_mangle_attr,
1792 export_name_attr,
1793 },
1794 );
1795 }
1796 }
1797
1798 fn check_autodiff(&self, _hir_id: HirId, _attr: &Attribute, span: Span, target: Target) {
1800 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_passes/src/check_attr.rs:1800",
"rustc_passes::check_attr", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_passes/src/check_attr.rs"),
::tracing_core::__macro_support::Option::Some(1800u32),
::tracing_core::__macro_support::Option::Some("rustc_passes::check_attr"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("check_autodiff")
as &dyn Value))])
});
} else { ; }
};debug!("check_autodiff");
1801 match target {
1802 Target::Fn => {}
1803 _ => {
1804 self.dcx().emit_err(errors::AutoDiffAttr { attr_span: span });
1805 self.abort.set(true);
1806 }
1807 }
1808 }
1809
1810 fn check_loop_match(&self, hir_id: HirId, attr_span: Span, target: Target) {
1811 let node_span = self.tcx.hir_span(hir_id);
1812
1813 if !#[allow(non_exhaustive_omitted_patterns)] match target {
Target::Expression => true,
_ => false,
}matches!(target, Target::Expression) {
1814 return; }
1816
1817 if !#[allow(non_exhaustive_omitted_patterns)] match self.tcx.hir_expect_expr(hir_id).kind
{
hir::ExprKind::Loop(..) => true,
_ => false,
}matches!(self.tcx.hir_expect_expr(hir_id).kind, hir::ExprKind::Loop(..)) {
1818 self.dcx().emit_err(errors::LoopMatchAttr { attr_span, node_span });
1819 };
1820 }
1821
1822 fn check_const_continue(&self, hir_id: HirId, attr_span: Span, target: Target) {
1823 let node_span = self.tcx.hir_span(hir_id);
1824
1825 if !#[allow(non_exhaustive_omitted_patterns)] match target {
Target::Expression => true,
_ => false,
}matches!(target, Target::Expression) {
1826 return; }
1828
1829 if !#[allow(non_exhaustive_omitted_patterns)] match self.tcx.hir_expect_expr(hir_id).kind
{
hir::ExprKind::Break(..) => true,
_ => false,
}matches!(self.tcx.hir_expect_expr(hir_id).kind, hir::ExprKind::Break(..)) {
1830 self.dcx().emit_err(errors::ConstContinueAttr { attr_span, node_span });
1831 };
1832 }
1833
1834 fn check_custom_mir(
1835 &self,
1836 dialect: Option<(MirDialect, Span)>,
1837 phase: Option<(MirPhase, Span)>,
1838 attr_span: Span,
1839 ) {
1840 let Some((dialect, dialect_span)) = dialect else {
1841 if let Some((_, phase_span)) = phase {
1842 self.dcx()
1843 .emit_err(errors::CustomMirPhaseRequiresDialect { attr_span, phase_span });
1844 }
1845 return;
1846 };
1847
1848 match dialect {
1849 MirDialect::Analysis => {
1850 if let Some((MirPhase::Optimized, phase_span)) = phase {
1851 self.dcx().emit_err(errors::CustomMirIncompatibleDialectAndPhase {
1852 dialect,
1853 phase: MirPhase::Optimized,
1854 attr_span,
1855 dialect_span,
1856 phase_span,
1857 });
1858 }
1859 }
1860
1861 MirDialect::Built => {
1862 if let Some((phase, phase_span)) = phase {
1863 self.dcx().emit_err(errors::CustomMirIncompatibleDialectAndPhase {
1864 dialect,
1865 phase,
1866 attr_span,
1867 dialect_span,
1868 phase_span,
1869 });
1870 }
1871 }
1872 MirDialect::Runtime => {}
1873 }
1874 }
1875}
1876
1877impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> {
1878 type NestedFilter = nested_filter::OnlyBodies;
1879
1880 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
1881 self.tcx
1882 }
1883
1884 fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
1885 if let ItemKind::Macro(_, macro_def, _) = item.kind {
1889 let def_id = item.owner_id.to_def_id();
1890 if macro_def.macro_rules
1891 && !{
{
'done:
{
for i in self.tcx.get_all_attrs(def_id) {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::MacroExport { ..
}) => {
break 'done Some(());
}
_ => {}
}
}
None
}
}.is_some()
}find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::MacroExport { .. })
1892 {
1893 check_non_exported_macro_for_invalid_attrs(self.tcx, item);
1894 }
1895 }
1896
1897 let target = Target::from_item(item);
1898 self.check_attributes(item.hir_id(), item.span, target, Some(ItemLike::Item(item)));
1899 intravisit::walk_item(self, item)
1900 }
1901
1902 fn visit_where_predicate(&mut self, where_predicate: &'tcx hir::WherePredicate<'tcx>) {
1903 let spans = self
1908 .tcx
1909 .hir_attrs(where_predicate.hir_id)
1910 .iter()
1911 .filter(|attr| {
1913 #[allow(non_exhaustive_omitted_patterns)] match attr {
Attribute::Parsed(AttributeKind::DocComment { .. } |
AttributeKind::Doc(_)) | Attribute::Unparsed(_) => true,
_ => false,
}matches!(
1914 attr,
1915 Attribute::Parsed(AttributeKind::DocComment { .. } | AttributeKind::Doc(_))
1916 | Attribute::Unparsed(_)
1917 )
1918 })
1919 .map(|attr| attr.span())
1920 .collect::<Vec<_>>();
1921 if !spans.is_empty() {
1922 self.tcx.dcx().emit_err(errors::UnsupportedAttributesInWhere { span: spans.into() });
1923 }
1924 self.check_attributes(
1925 where_predicate.hir_id,
1926 where_predicate.span,
1927 Target::WherePredicate,
1928 None,
1929 );
1930 intravisit::walk_where_predicate(self, where_predicate)
1931 }
1932
1933 fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) {
1934 let target = Target::from_generic_param(generic_param);
1935 self.check_attributes(generic_param.hir_id, generic_param.span, target, None);
1936 intravisit::walk_generic_param(self, generic_param)
1937 }
1938
1939 fn visit_trait_item(&mut self, trait_item: &'tcx TraitItem<'tcx>) {
1940 let target = Target::from_trait_item(trait_item);
1941 self.check_attributes(trait_item.hir_id(), trait_item.span, target, None);
1942 intravisit::walk_trait_item(self, trait_item)
1943 }
1944
1945 fn visit_field_def(&mut self, struct_field: &'tcx hir::FieldDef<'tcx>) {
1946 self.check_attributes(struct_field.hir_id, struct_field.span, Target::Field, None);
1947 intravisit::walk_field_def(self, struct_field);
1948 }
1949
1950 fn visit_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) {
1951 self.check_attributes(arm.hir_id, arm.span, Target::Arm, None);
1952 intravisit::walk_arm(self, arm);
1953 }
1954
1955 fn visit_foreign_item(&mut self, f_item: &'tcx ForeignItem<'tcx>) {
1956 let target = Target::from_foreign_item(f_item);
1957 self.check_attributes(f_item.hir_id(), f_item.span, target, Some(ItemLike::ForeignItem));
1958 intravisit::walk_foreign_item(self, f_item)
1959 }
1960
1961 fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
1962 let target = target_from_impl_item(self.tcx, impl_item);
1963 self.check_attributes(impl_item.hir_id(), impl_item.span, target, None);
1964 intravisit::walk_impl_item(self, impl_item)
1965 }
1966
1967 fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
1968 if let hir::StmtKind::Let(l) = stmt.kind {
1970 self.check_attributes(l.hir_id, stmt.span, Target::Statement, None);
1971 }
1972 intravisit::walk_stmt(self, stmt)
1973 }
1974
1975 fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
1976 let target = match expr.kind {
1977 hir::ExprKind::Closure { .. } => Target::Closure,
1978 _ => Target::Expression,
1979 };
1980
1981 self.check_attributes(expr.hir_id, expr.span, target, None);
1982 intravisit::walk_expr(self, expr)
1983 }
1984
1985 fn visit_expr_field(&mut self, field: &'tcx hir::ExprField<'tcx>) {
1986 self.check_attributes(field.hir_id, field.span, Target::ExprField, None);
1987 intravisit::walk_expr_field(self, field)
1988 }
1989
1990 fn visit_variant(&mut self, variant: &'tcx hir::Variant<'tcx>) {
1991 self.check_attributes(variant.hir_id, variant.span, Target::Variant, None);
1992 intravisit::walk_variant(self, variant)
1993 }
1994
1995 fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
1996 self.check_attributes(param.hir_id, param.span, Target::Param, None);
1997
1998 intravisit::walk_param(self, param);
1999 }
2000
2001 fn visit_pat_field(&mut self, field: &'tcx hir::PatField<'tcx>) {
2002 self.check_attributes(field.hir_id, field.span, Target::PatField, None);
2003 intravisit::walk_pat_field(self, field);
2004 }
2005}
2006
2007fn is_c_like_enum(item: &Item<'_>) -> bool {
2008 if let ItemKind::Enum(_, _, ref def) = item.kind {
2009 for variant in def.variants {
2010 match variant.data {
2011 hir::VariantData::Unit(..) => { }
2012 _ => return false,
2013 }
2014 }
2015 true
2016 } else {
2017 false
2018 }
2019}
2020
2021fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
2024 const ATTRS_TO_CHECK: &[Symbol] =
2028 &[sym::derive, sym::test, sym::test_case, sym::global_allocator, sym::bench];
2029
2030 for attr in attrs {
2031 let (span, name) = if let Some(a) =
2033 ATTRS_TO_CHECK.iter().find(|attr_to_check| attr.has_name(**attr_to_check))
2034 {
2035 (attr.span(), *a)
2036 } else if let Attribute::Parsed(AttributeKind::Repr {
2037 reprs: _,
2038 first_span: first_attr_span,
2039 }) = attr
2040 {
2041 (*first_attr_span, sym::repr)
2042 } else {
2043 continue;
2044 };
2045
2046 let item = tcx
2047 .hir_free_items()
2048 .map(|id| tcx.hir_item(id))
2049 .find(|item| !item.span.is_dummy()) .map(|item| errors::ItemFollowingInnerAttr {
2051 span: if let Some(ident) = item.kind.ident() { ident.span } else { item.span },
2052 kind: tcx.def_descr(item.owner_id.to_def_id()),
2053 });
2054 let err = tcx.dcx().create_err(errors::InvalidAttrAtCrateLevel {
2055 span,
2056 sugg_span: tcx
2057 .sess
2058 .source_map()
2059 .span_to_snippet(span)
2060 .ok()
2061 .filter(|src| src.starts_with("#!["))
2062 .map(|_| span.with_lo(span.lo() + BytePos(1)).with_hi(span.lo() + BytePos(2))),
2063 name,
2064 item,
2065 });
2066
2067 if let Attribute::Unparsed(p) = attr {
2068 tcx.dcx().try_steal_replace_and_emit_err(
2069 p.path.span,
2070 StashKey::UndeterminedMacroResolution,
2071 err,
2072 );
2073 } else {
2074 err.emit();
2075 }
2076 }
2077}
2078
2079fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) {
2080 let attrs = tcx.hir_attrs(item.hir_id());
2081
2082 if let Some(attr_span) = {
'done:
{
for i in attrs {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::Inline(i, span))
if
!#[allow(non_exhaustive_omitted_patterns)] match i {
InlineAttr::Force { .. } => true,
_ => false,
} => {
break 'done Some(*span);
}
_ => {}
}
}
None
}
}find_attr!(attrs, AttributeKind::Inline(i, span) if !matches!(i, InlineAttr::Force{..}) => *span)
2083 {
2084 tcx.dcx().emit_err(errors::NonExportedMacroInvalidAttrs { attr_span });
2085 }
2086}
2087
2088fn check_mod_attrs(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
2089 let check_attr_visitor = &mut CheckAttrVisitor { tcx, abort: Cell::new(false) };
2090 tcx.hir_visit_item_likes_in_module(module_def_id, check_attr_visitor);
2091 if module_def_id.to_local_def_id().is_top_level_module() {
2092 check_attr_visitor.check_attributes(CRATE_HIR_ID, DUMMY_SP, Target::Mod, None);
2093 check_invalid_crate_level_attr(tcx, tcx.hir_krate_attrs());
2094 }
2095 if check_attr_visitor.abort.get() {
2096 tcx.dcx().abort_if_errors()
2097 }
2098}
2099
2100pub(crate) fn provide(providers: &mut Providers) {
2101 *providers = Providers { check_mod_attrs, ..*providers };
2102}
2103
2104fn check_duplicates(
2106 tcx: TyCtxt<'_>,
2107 attr_span: Span,
2108 attr: &Attribute,
2109 hir_id: HirId,
2110 duplicates: AttributeDuplicates,
2111 seen: &mut FxHashMap<Symbol, Span>,
2112) {
2113 use AttributeDuplicates::*;
2114 if #[allow(non_exhaustive_omitted_patterns)] match duplicates {
WarnFollowingWordOnly => true,
_ => false,
}matches!(duplicates, WarnFollowingWordOnly) && !attr.is_word() {
2115 return;
2116 }
2117 let attr_name = attr.name().unwrap();
2118 match duplicates {
2119 DuplicatesOk => {}
2120 WarnFollowing | FutureWarnFollowing | WarnFollowingWordOnly | FutureWarnPreceding => {
2121 match seen.entry(attr_name) {
2122 Entry::Occupied(mut entry) => {
2123 let (this, other) = if #[allow(non_exhaustive_omitted_patterns)] match duplicates {
FutureWarnPreceding => true,
_ => false,
}matches!(duplicates, FutureWarnPreceding) {
2124 let to_remove = entry.insert(attr_span);
2125 (to_remove, attr_span)
2126 } else {
2127 (attr_span, *entry.get())
2128 };
2129 tcx.emit_node_span_lint(
2130 UNUSED_ATTRIBUTES,
2131 hir_id,
2132 this,
2133 errors::UnusedDuplicate {
2134 this,
2135 other,
2136 warning: #[allow(non_exhaustive_omitted_patterns)] match duplicates {
FutureWarnFollowing | FutureWarnPreceding => true,
_ => false,
}matches!(
2137 duplicates,
2138 FutureWarnFollowing | FutureWarnPreceding
2139 ),
2140 },
2141 );
2142 }
2143 Entry::Vacant(entry) => {
2144 entry.insert(attr_span);
2145 }
2146 }
2147 }
2148 ErrorFollowing | ErrorPreceding => match seen.entry(attr_name) {
2149 Entry::Occupied(mut entry) => {
2150 let (this, other) = if #[allow(non_exhaustive_omitted_patterns)] match duplicates {
ErrorPreceding => true,
_ => false,
}matches!(duplicates, ErrorPreceding) {
2151 let to_remove = entry.insert(attr_span);
2152 (to_remove, attr_span)
2153 } else {
2154 (attr_span, *entry.get())
2155 };
2156 tcx.dcx().emit_err(errors::UnusedMultiple { this, other, name: attr_name });
2157 }
2158 Entry::Vacant(entry) => {
2159 entry.insert(attr_span);
2160 }
2161 },
2162 }
2163}
2164
2165fn doc_fake_variadic_is_allowed_self_ty(self_ty: &hir::Ty<'_>) -> bool {
2166 #[allow(non_exhaustive_omitted_patterns)] match &self_ty.kind {
hir::TyKind::Tup([_]) => true,
_ => false,
}matches!(&self_ty.kind, hir::TyKind::Tup([_]))
2167 || if let hir::TyKind::FnPtr(fn_ptr_ty) = &self_ty.kind {
2168 fn_ptr_ty.decl.inputs.len() == 1
2169 } else {
2170 false
2171 }
2172 || (if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &self_ty.kind
2173 && let Some(&[hir::GenericArg::Type(ty)]) =
2174 path.segments.last().map(|last| last.args().args)
2175 {
2176 doc_fake_variadic_is_allowed_self_ty(ty.as_unambig_ty())
2177 } else {
2178 false
2179 })
2180}