diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index c3222b79e55c9..31e9c953404a0 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -1,5 +1,5 @@ use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind}; -use rustc_hir as hir; +use rustc_hir::{self as hir, Target}; use rustc_span::sym; use smallvec::SmallVec; @@ -109,7 +109,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }; let span = self.lower_span(l.span); let source = hir::LocalSource::Normal; - self.lower_attrs(hir_id, &l.attrs, l.span); + self.lower_attrs(hir_id, &l.attrs, l.span, Target::Statement); self.arena.alloc(hir::LetStmt { hir_id, super_, ty, pat, init, els, span, source }) } diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 15e736261d583..16e2da9342997 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -6,9 +6,8 @@ use rustc_ast::*; use rustc_ast_pretty::pprust::expr_to_string; use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_hir as hir; -use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; +use rustc_hir::{self as hir, HirId, Target}; use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; use rustc_session::errors::report_lit_error; @@ -75,7 +74,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if !e.attrs.is_empty() { let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]); let new_attrs = self - .lower_attrs_vec(&e.attrs, e.span, ex.hir_id) + .lower_attrs_vec(&e.attrs, e.span, ex.hir_id, Target::Expression) .into_iter() .chain(old_attrs.iter().cloned()); let new_attrs = &*self.arena.alloc_from_iter(new_attrs); @@ -98,7 +97,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } let expr_hir_id = self.lower_node_id(e.id); - self.lower_attrs(expr_hir_id, &e.attrs, e.span); + self.lower_attrs(expr_hir_id, &e.attrs, e.span, Target::Expression); let kind = match &e.kind { ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), @@ -636,7 +635,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let guard = arm.guard.as_ref().map(|cond| self.lower_expr(cond)); let hir_id = self.next_id(); let span = self.lower_span(arm.span); - self.lower_attrs(hir_id, &arm.attrs, arm.span); + self.lower_attrs(hir_id, &arm.attrs, arm.span, Target::Arm); let is_never_pattern = pat.is_never_pattern(); // We need to lower the body even if it's unneeded for never pattern in match, // ensure that we can get HirId for DefId if need (issue #137708). @@ -809,6 +808,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: unstable_span, }], span, + Target::Fn, ); } } @@ -1649,7 +1649,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> { let hir_id = self.lower_node_id(f.id); - self.lower_attrs(hir_id, &f.attrs, f.span); + self.lower_attrs(hir_id, &f.attrs, f.span, Target::ExprField); hir::ExprField { hir_id, ident: self.lower_ident(f.ident), @@ -1905,7 +1905,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // // Also, add the attributes to the outer returned expr node. let expr = self.expr_drop_temps_mut(for_span, match_expr); - self.lower_attrs(expr.hir_id, &e.attrs, e.span); + self.lower_attrs(expr.hir_id, &e.attrs, e.span, Target::Expression); expr } @@ -1962,7 +1962,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let val_ident = Ident::with_dummy_span(sym::val); let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident); let val_expr = self.expr_ident(span, val_ident, val_pat_nid); - self.lower_attrs(val_expr.hir_id, &attrs, span); + self.lower_attrs(val_expr.hir_id, &attrs, span, Target::Expression); let continue_pat = self.pat_cf_continue(unstable_span, val_pat); self.arm(continue_pat, val_expr) }; @@ -1993,7 +1993,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ret_expr = self.checked_return(Some(from_residual_expr)); self.arena.alloc(self.expr(try_span, ret_expr)) }; - self.lower_attrs(ret_expr.hir_id, &attrs, span); + self.lower_attrs(ret_expr.hir_id, &attrs, span, Target::Expression); let break_pat = self.pat_cf_break(try_span, residual_local); self.arm(break_pat, ret_expr) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ddf01b69e7f6a..a99fcec4f13d1 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -6,7 +6,7 @@ use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; -use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin}; +use rustc_hir::{self as hir, HirId, LifetimeSource, MethodKind, PredicateOrigin, Target}; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::span_bug; use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; @@ -81,7 +81,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { self.with_lctx(CRATE_NODE_ID, |lctx| { let module = lctx.lower_mod(&c.items, &c.spans); // FIXME(jdonszelman): is dummy span ever a problem here? - lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP); + lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, DUMMY_SP, Target::Crate); hir::OwnerNode::Crate(module) }) } @@ -137,7 +137,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { let vis_span = self.lower_span(i.vis.span); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); - let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); + let attrs = self.lower_attrs(hir_id, &i.attrs, i.span, Target::from_ast_item(i)); let kind = self.lower_item_kind(i.span, i.id, hir_id, attrs, vis_span, &i.kind); let item = hir::Item { owner_id: hir_id.expect_owner(), @@ -649,9 +649,9 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); let owner_id = hir_id.expect_owner(); - let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let (ident, kind) = match &i.kind { ForeignItemKind::Fn(box Fn { sig, ident, generics, define_opaque, .. }) => { + let attrs = self.lower_attrs(hir_id, &i.attrs, i.span, Target::ForeignFn); let fdec = &sig.decl; let itctx = ImplTraitContext::Universal; let (generics, (decl, fn_args)) = @@ -687,6 +687,7 @@ impl<'hir> LoweringContext<'_, 'hir> { safety, define_opaque, }) => { + self.lower_attrs(hir_id, &i.attrs, i.span, Target::ForeignStatic); let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); let safety = self.lower_safety(*safety, hir::Safety::Unsafe); @@ -696,6 +697,7 @@ impl<'hir> LoweringContext<'_, 'hir> { (ident, hir::ForeignItemKind::Static(ty, *mutability, safety)) } ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => { + self.lower_attrs(hir_id, &i.attrs, i.span, Target::ForeignTy); (ident, hir::ForeignItemKind::Type) } ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), @@ -718,7 +720,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_variant(&mut self, item_kind: &ItemKind, v: &Variant) -> hir::Variant<'hir> { let hir_id = self.lower_node_id(v.id); - self.lower_attrs(hir_id, &v.attrs, v.span); + self.lower_attrs(hir_id, &v.attrs, v.span, Target::Variant); hir::Variant { hir_id, def_id: self.local_def_id(v.id), @@ -801,7 +803,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::FieldDef<'hir> { let ty = self.lower_ty(&f.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FieldTy)); let hir_id = self.lower_node_id(f.id); - self.lower_attrs(hir_id, &f.attrs, f.span); + self.lower_attrs(hir_id, &f.attrs, f.span, Target::Field); hir::FieldDef { span: self.lower_span(f.span), hir_id, @@ -820,7 +822,6 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); - let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let trait_item_def_id = hir_id.expect_owner(); let (ident, generics, kind, has_default) = match &i.kind { @@ -832,6 +833,7 @@ impl<'hir> LoweringContext<'_, 'hir> { define_opaque, .. }) => { + self.lower_attrs(hir_id, &i.attrs, i.span, Target::AssocConst); let (generics, kind) = self.lower_generics( generics, i.id, @@ -861,6 +863,12 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Fn(box Fn { sig, ident, generics, body: None, define_opaque, .. }) => { + let attrs = self.lower_attrs( + hir_id, + &i.attrs, + i.span, + Target::Method(MethodKind::Trait { body: false }), + ); // FIXME(contracts): Deny contract here since it won't apply to // any impl method or callees. let idents = self.lower_fn_params_to_idents(&sig.decl); @@ -894,6 +902,12 @@ impl<'hir> LoweringContext<'_, 'hir> { define_opaque, .. }) => { + let attrs = self.lower_attrs( + hir_id, + &i.attrs, + i.span, + Target::Method(MethodKind::Trait { body: true }), + ); let body_id = self.lower_maybe_coroutine_body( sig.span, i.span, @@ -923,6 +937,7 @@ impl<'hir> LoweringContext<'_, 'hir> { AssocItemKind::Type(box TyAlias { ident, generics, where_clauses, bounds, ty, .. }) => { + self.lower_attrs(hir_id, &i.attrs, i.span, Target::AssocTy); let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, false); let (generics, kind) = self.lower_generics( @@ -949,6 +964,12 @@ impl<'hir> LoweringContext<'_, 'hir> { (*ident, generics, kind, ty.is_some()) } AssocItemKind::Delegation(box delegation) => { + self.lower_attrs( + hir_id, + &i.attrs, + i.span, + Target::Method(MethodKind::Trait { body: true }), + ); let delegation_results = self.lower_delegation(delegation, i.id, false); let item_kind = hir::TraitItemKind::Fn( delegation_results.sig, @@ -991,7 +1012,6 @@ impl<'hir> LoweringContext<'_, 'hir> { let has_value = true; let (defaultness, _) = self.lower_defaultness(i.kind.defaultness(), has_value); let hir_id = hir::HirId::make_owner(self.current_hir_id_owner.def_id); - let attrs = self.lower_attrs(hir_id, &i.attrs, i.span); let (ident, (generics, kind)) = match &i.kind { AssocItemKind::Const(box ConstItem { @@ -1001,21 +1021,26 @@ impl<'hir> LoweringContext<'_, 'hir> { expr, define_opaque, .. - }) => ( - *ident, - self.lower_generics( - generics, - i.id, - ImplTraitContext::Disallowed(ImplTraitPosition::Generic), - |this| { - let ty = this - .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy)); - let body = this.lower_const_body(i.span, expr.as_deref()); - this.lower_define_opaque(hir_id, &define_opaque); - hir::ImplItemKind::Const(ty, body) - }, - ), - ), + }) => { + self.lower_attrs(hir_id, &i.attrs, i.span, Target::AssocConst); + ( + *ident, + self.lower_generics( + generics, + i.id, + ImplTraitContext::Disallowed(ImplTraitPosition::Generic), + |this| { + let ty = this.lower_ty( + ty, + ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy), + ); + let body = this.lower_const_body(i.span, expr.as_deref()); + this.lower_define_opaque(hir_id, &define_opaque); + hir::ImplItemKind::Const(ty, body) + }, + ), + ) + } AssocItemKind::Fn(box Fn { sig, ident, @@ -1025,6 +1050,16 @@ impl<'hir> LoweringContext<'_, 'hir> { define_opaque, .. }) => { + let attrs = self.lower_attrs( + hir_id, + &i.attrs, + i.span, + if is_in_trait_impl { + Target::Method(MethodKind::Trait { body: true }) + } else { + Target::Method(MethodKind::Inherent) + }, + ); let body_id = self.lower_maybe_coroutine_body( sig.span, i.span, @@ -1048,6 +1083,7 @@ impl<'hir> LoweringContext<'_, 'hir> { (*ident, (generics, hir::ImplItemKind::Fn(sig, body_id))) } AssocItemKind::Type(box TyAlias { ident, generics, where_clauses, ty, .. }) => { + self.lower_attrs(hir_id, &i.attrs, i.span, Target::AssocTy); let mut generics = generics.clone(); add_ty_alias_where_clause(&mut generics, *where_clauses, false); ( @@ -1161,7 +1197,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> { let hir_id = self.lower_node_id(param.id); - self.lower_attrs(hir_id, ¶m.attrs, param.span); + self.lower_attrs(hir_id, ¶m.attrs, param.span, Target::Param); hir::Param { hir_id, pat: self.lower_pat(¶m.pat), @@ -1841,7 +1877,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> hir::WherePredicate<'hir> { let hir_id = self.lower_node_id(pred.id); let span = self.lower_span(pred.span); - self.lower_attrs(hir_id, &pred.attrs, span); + self.lower_attrs(hir_id, &pred.attrs, span, Target::WherePredicate); let kind = self.arena.alloc(match &pred.kind { WherePredicateKind::BoundPredicate(WhereBoundPredicate { bound_generic_params, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9aef189a29d49..fb22925e1b045 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -42,7 +42,7 @@ use std::sync::Arc; use rustc_ast::node_id::NodeMap; use rustc_ast::{self as ast, *}; -use rustc_attr_parsing::{AttributeParser, Late, OmitDoc}; +use rustc_attr_parsing::{AttributeParser, AttributeTarget, Late, OmitDoc}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -53,8 +53,8 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; use rustc_hir::lints::DelayedLint; use rustc_hir::{ - self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource, - LifetimeSyntax, ParamName, TraitCandidate, + self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, + LifetimeSource, LifetimeSyntax, ParamName, Target, TraitCandidate, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; @@ -942,11 +942,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { id: HirId, attrs: &[Attribute], target_span: Span, + target: Target, ) -> &'hir [hir::Attribute] { if attrs.is_empty() { &[] } else { - let lowered_attrs = self.lower_attrs_vec(attrs, self.lower_span(target_span), id); + let lowered_attrs = + self.lower_attrs_vec(attrs, self.lower_span(target_span), id, target); assert_eq!(id.owner, self.current_hir_id_owner); let ret = self.arena.alloc_from_iter(lowered_attrs); @@ -971,12 +973,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { attrs: &[Attribute], target_span: Span, target_hir_id: HirId, + target: Target, ) -> Vec { let l = self.span_lowerer(); self.attribute_parser.parse_attribute_list( attrs, - target_span, - target_hir_id, + AttributeTarget { kind: target, span: target_span, id: target_hir_id }, OmitDoc::Lower, |s| l.lower(s), |l| { @@ -1939,7 +1941,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let (name, kind) = self.lower_generic_param_kind(param, source); let hir_id = self.lower_node_id(param.id); - self.lower_attrs(hir_id, ¶m.attrs, param.span()); + self.lower_attrs( + hir_id, + ¶m.attrs, + param.span(), + Target::from_generic_param_kind(&kind), + ); hir::GenericParam { hir_id, def_id: self.local_def_id(param.id), diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index e444062104813..40ba6e89e4736 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -4,7 +4,7 @@ use rustc_ast::ptr::P; use rustc_ast::*; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{self as hir, LangItem}; +use rustc_hir::{self as hir, LangItem, Target}; use rustc_middle::span_bug; use rustc_span::source_map::{Spanned, respan}; use rustc_span::{DesugaringKind, Ident, Span}; @@ -94,7 +94,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let fs = self.arena.alloc_from_iter(fields.iter().map(|f| { let hir_id = self.lower_node_id(f.id); - self.lower_attrs(hir_id, &f.attrs, f.span); + self.lower_attrs(hir_id, &f.attrs, f.span, Target::PatField); hir::PatField { hir_id, diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 35ff48cb5f24b..43c3ecf15e7e0 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -159,5 +159,13 @@ attr_parsing_unused_multiple = .suggestion = remove this attribute .note = attribute also specified here +attr_parsing_generic_wrong_target = + attribute is not valid here + .label = cannot be applied to {$target} + .help = {$num_ok_targets -> + [1] this attribute is only valid on {$ok_targets} + *[other] this attribute is valid on {$ok_targets} + } + -attr_parsing_previously_accepted = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index bb28121c2c5d0..cae7035f6533f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -7,7 +7,7 @@ use super::{ AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser, }; -use crate::context::{AcceptContext, FinalizeContext, Stage}; +use crate::context::{AcceptContext, FinalizeContext, FinalizedAttribute, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport}; @@ -139,7 +139,7 @@ impl AttributeParser for NakedParser { } })]; - fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option { + fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> FinalizedAttribute { // FIXME(jdonszelmann): upgrade this list to *parsed* attributes // once all of these have parsed forms. That'd make the check much nicer... // @@ -185,7 +185,9 @@ impl AttributeParser for NakedParser { sym::doc, ]; - let span = self.span?; + let Some(span) = self.span else { + return cx.none(); + }; // only if we found a naked attribute do we do the somewhat expensive check 'outer: for other_attr in cx.all_attrs { @@ -222,7 +224,7 @@ impl AttributeParser for NakedParser { }); } - Some(AttributeKind::Naked(span)) + cx.some(AttributeKind::Naked(span)) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index c911908dfb381..511446046bbf7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -4,7 +4,7 @@ use rustc_span::{Span, Symbol, sym}; use thin_vec::ThinVec; use super::{AcceptMapping, AttributeParser}; -use crate::context::{FinalizeContext, Stage}; +use crate::context::{FinalizeContext, FinalizedAttribute, Stage}; use crate::session_diagnostics; #[derive(Default)] @@ -42,12 +42,12 @@ impl AttributeParser for ConfusablesParser { }, )]; - fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { + fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> FinalizedAttribute { if self.confusables.is_empty() { - return None; + return cx.none(); } - Some(AttributeKind::Confusables { + cx.some(AttributeKind::Confusables { symbols: self.confusables, first_span: self.first_span.unwrap(), }) diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 0c10517d04401..f9266b256d446 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -21,7 +21,7 @@ use rustc_feature::{AttributeTemplate, template}; use rustc_span::{Span, Symbol}; use thin_vec::ThinVec; -use crate::context::{AcceptContext, FinalizeContext, Stage}; +use crate::context::{AcceptContext, FinalizeContext, FinalizedAttribute, Stage}; use crate::parser::ArgParser; use crate::session_diagnostics::UnusedMultiple; @@ -54,6 +54,64 @@ pub(crate) mod util; type AcceptFn = for<'sess> fn(&mut T, &mut AcceptContext<'_, 'sess, S>, &ArgParser<'_>); type AcceptMapping = &'static [(&'static [Symbol], AttributeTemplate, AcceptFn)]; +#[macro_export] +macro_rules! targets { + ( + $($($pat: tt)|* => $judgement: tt),* $(,)? + ) => { + |cx: &FinalizeContext<'_, '_, _>, error_span: Span| { + use rustc_hir::Target::*; + + let acceptable_targets = || { + let targets: Vec<_> = targets!(@find_valid [] $([$($pat)|* => $judgement])*); + let len = targets.len(); + + (rustc_errors::DiagArgValue::StrListSepByAnd(targets), len) + }; + + match cx.target.kind { + $( + $($pat)|* => targets!(@judge [acceptable_targets cx error_span] $judgement) + ),* + }; + } + }; + + (@find_valid [$($tt:tt)*] [_ => $first_judgement: tt] $([$($pat: tt)|* => $judgement: tt])*) => { + targets!(@find_valid [$($tt)*] $([$($pat)|* => $judgement])*) + }; + (@find_valid [$($tt:tt)*] [$($first_pat: tt)|* => ok] $([$($pat: tt)|* => $judgement: tt])*) => { + targets!(@find_valid [$($tt)* $([$first_pat.name().into()])*] $([$($pat)|* => $judgement])*) + }; + (@find_valid [$($tt:tt)*] [$($first_pat: tt)|* => $first_judgement: tt] $([$($pat: path)|* => $judgement: tt])*) => { + targets!(@find_valid [$($tt)*] $([$($pat)|* => $judgement])*) + }; + (@find_valid [$([$($tt:tt)*])*]) => { + vec![$($($tt)*),*] + }; + + (@judge [$($tt:tt)*] ok) => { + {} + }; + (@judge [$($tt:tt)*] err) => {compile_error!( + "did you mean `error`?" + )}; + (@judge [$ok: ident $cx: ident $error_span: ident] error) => { + { + let (res, num) = $ok(); + $cx.emit_err($crate::session_diagnostics::GenericWrongTarget { + attr_span: $error_span, + target_span: $cx.target.span, + target: $cx.target.kind.name(), + ok_targets: res, + num_ok_targets: num, + }); + } + }; + (@judge [$($tt:tt)*] warn) => {}; + (@judge [$($tt:tt)*] $expr: expr) => {$expr}; +} + /// An [`AttributeParser`] is a type which searches for syntactic attributes. /// /// Parsers are often tiny state machines that gets to see all syntactical attributes on an item. @@ -87,7 +145,9 @@ pub(crate) trait AttributeParser: Default + 'static { /// that'd be equivalent to unconditionally applying an attribute to /// every single syntax item that could have attributes applied to it. /// Your accept mappings should determine whether this returns something. - fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option; + /// + /// You can produce a [`FinalizedAttribute`] through `cx.some(...)` or `cx.none()` + fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> FinalizedAttribute; } /// Alternative to [`AttributeParser`] that automatically handles state management. @@ -163,8 +223,9 @@ impl, S: Stage> AttributeParser for Single }, )]; - fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { - Some(self.1?.0) + fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> FinalizedAttribute { + let (kind, span) = self.1?; + cx.some(kind, |_, _| todo!(), span) } } @@ -304,21 +365,15 @@ pub(crate) trait CombineAttributeParser: 'static { /// Use in combination with [`CombineAttributeParser`]. /// `Combine` implements [`AttributeParser`]. -pub(crate) struct Combine, S: Stage> { - phantom: PhantomData<(S, T)>, - /// A list of all items produced by parsing attributes so far. One attribute can produce any amount of items. - items: ThinVec<>::Item>, - /// The full span of the first attribute that was encountered. - first_span: Option, -} +pub(crate) struct Combine, S: Stage>( + PhantomData<(S, T)>, + ThinVec<>::Item>, + Option, +); impl, S: Stage> Default for Combine { fn default() -> Self { - Self { - phantom: Default::default(), - items: Default::default(), - first_span: Default::default(), - } + Self(Default::default(), Default::default(), None) } } @@ -327,17 +382,20 @@ impl, S: Stage> AttributeParser for Combine>::TEMPLATE, |group: &mut Combine, cx, args| { - // Keep track of the span of the first attribute, for diagnostics - group.first_span.get_or_insert(cx.attr_span); - group.items.extend(T::extend(cx, args)) + group.1.extend(T::extend(cx, args)); + + if group.2.is_none() { + // TODO: multispan? + group.2 = Some(cx.attr_span) + } }, )]; - fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { - if let Some(first_span) = self.first_span { - Some(T::CONVERT(self.items, first_span)) + fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> FinalizedAttribute { + if self.1.is_empty() { + cx.none() } else { - None + cx.some(T::CONVERT(self.1), |_, _| todo!(), self.2.unwrap()) } } } diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 521acbb607c7e..473bc512350c3 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -5,7 +5,7 @@ use rustc_feature::{AttributeTemplate, template}; use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use super::{AcceptMapping, AttributeParser, CombineAttributeParser, ConvertFn, FinalizeContext}; -use crate::context::{AcceptContext, Stage}; +use crate::context::{AcceptContext, FinalizedAttribute, Stage}; use crate::parser::{ArgParser, MetaItemListParser, MetaItemParser}; use crate::session_diagnostics; use crate::session_diagnostics::IncorrectReprFormatGenericCause; @@ -317,8 +317,8 @@ impl AlignParser { impl AttributeParser for AlignParser { const ATTRIBUTES: AcceptMapping = &[(Self::PATH, Self::TEMPLATE, Self::parse)]; - fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { + fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> FinalizedAttribute { let (align, span) = self.0?; - Some(AttributeKind::Align { align, span }) + cx.some(AttributeKind::Align { align, span }) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index c54fc6b41f8e4..03bb26e715574 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -11,9 +11,10 @@ use rustc_span::{Ident, Span, Symbol, sym}; use super::util::parse_version; use super::{AcceptMapping, AttributeParser, OnDuplicate}; use crate::attributes::NoArgsAttributeParser; -use crate::context::{AcceptContext, FinalizeContext, Stage}; +use crate::context::{AcceptContext, FinalizeContext, FinalizedAttribute, Stage}; use crate::parser::{ArgParser, MetaItemParser}; use crate::session_diagnostics::{self, UnsupportedLiteralReason}; +use crate::targets; macro_rules! reject_outside_std { ($cx: ident) => { @@ -87,7 +88,7 @@ impl AttributeParser for StabilityParser { ), ]; - fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option { + fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> FinalizedAttribute { if let Some(atum) = self.allowed_through_unstable_modules { if let Some(( Stability { @@ -100,7 +101,7 @@ impl AttributeParser for StabilityParser { *allowed_through_unstable_modules = Some(atum); } else { cx.dcx().emit_err(session_diagnostics::RustcAllowedUnstablePairing { - span: cx.target_span, + span: cx.target.span, }); } } @@ -109,7 +110,7 @@ impl AttributeParser for StabilityParser { for other_attr in cx.all_attrs { if other_attr.word_is(sym::unstable_feature_bound) { cx.emit_err(session_diagnostics::UnstableFeatureBoundIncompatibleStability { - span: cx.target_span, + span: cx.target.span, }); } } @@ -117,7 +118,7 @@ impl AttributeParser for StabilityParser { let (stability, span) = self.stability?; - Some(AttributeKind::Stability { stability, span }) + cx.some(AttributeKind::Stability { stability, span }) } } @@ -142,10 +143,10 @@ impl AttributeParser for BodyStabilityParser { }, )]; - fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option { + fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> FinalizedAttribute { let (stability, span) = self.stability?; - Some(AttributeKind::BodyStability { stability, span }) + cx.some(AttributeKind::BodyStability { stability, span }) } } @@ -205,19 +206,26 @@ impl AttributeParser for ConstStabilityParser { }), ]; - fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> Option { + fn finalize(mut self, cx: &FinalizeContext<'_, '_, S>) -> FinalizedAttribute { if self.promotable { if let Some((ref mut stab, _)) = self.stability { stab.promotable = true; } else { cx.dcx() - .emit_err(session_diagnostics::RustcPromotablePairing { span: cx.target_span }); + .emit_err(session_diagnostics::RustcPromotablePairing { span: cx.target.span }); } } let (stability, span) = self.stability?; - Some(AttributeKind::ConstStability { stability, span }) + cx.some( + AttributeKind::ConstStability { stability, span }, + targets! { + Expression => ok, + _ => error, + }, + span, + ) } } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 9b86d10184082..8df971b70c467 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -1,6 +1,8 @@ use std::cell::RefCell; use std::collections::BTreeMap; -use std::ops::{Deref, DerefMut}; +use std::convert::Infallible; +use std::marker::PhantomData; +use std::ops::{Deref, DerefMut, FromResidual}; use std::sync::LazyLock; use private::Sealed; @@ -9,7 +11,7 @@ use rustc_attr_data_structures::AttributeKind; use rustc_attr_data_structures::lints::{AttributeLint, AttributeLintKind}; use rustc_errors::{DiagCtxtHandle, Diagnostic}; use rustc_feature::{AttributeTemplate, Features}; -use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId}; +use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId, Target}; use rustc_session::Session; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; @@ -66,7 +68,7 @@ macro_rules! group_type { ($stage: ty) => { LazyLock<( BTreeMap<&'static [Symbol], Vec<(AttributeTemplate, Box Fn(&mut AcceptContext<'_, 'sess, $stage>, &ArgParser<'a>) + Send + Sync>)>>, - Vec) -> Option>> + Vec) -> FinalizedAttribute>> )> }; } @@ -97,7 +99,7 @@ macro_rules! attribute_parsers { ) => { pub(crate) static $name: group_type!($ty) = LazyLock::new(|| { let mut accepts = BTreeMap::<_, Vec<(AttributeTemplate, Box Fn(&mut AcceptContext<'_, 'sess, $ty>, &ArgParser<'a>) + Send + Sync>)>>::new(); - let mut finalizes = Vec::) -> Option>>::new(); + let mut finalizes = Vec::) -> FinalizedAttribute>>::new(); $( { thread_local! { @@ -209,6 +211,39 @@ mod private { impl Sealed for super::Late {} } +/// Can only be constructed through a [`FinalizeContext`]. +/// +/// Implements `FromResidual` to allow conversions from None. +/// In other words, in [`AttributeParser::finalize`](crate::attributes::AttributeParser::finalize) you can use the `?` operator. +/// +/// Note: this is not an Option but a wrapper so it can serve as a proof that target applicability was checked. +pub(crate) struct FinalizedAttribute { + parsed: Option, +} + +impl FromResidual> for FinalizedAttribute { + fn from_residual(_: Option) -> Self { + Self { parsed: None } + } +} + +impl FinalizeContext<'_, '_, S> { + pub(crate) fn none(&self) -> FinalizedAttribute { + FinalizedAttribute { parsed: None } + } + + /// targets can be conveniently passed using [`targets!()`](crate::attributes::targets) + pub(crate) fn some( + &self, + attribute: AttributeKind, + target_valid: impl FnOnce(&Self, Span), + target_error_span: Span, + ) -> FinalizedAttribute { + target_valid(self, target_error_span); + FinalizedAttribute { parsed: Some(attribute) } + } +} + // allow because it's a sealed trait #[allow(private_interfaces)] pub trait Stage: Sized + 'static + Sealed { @@ -303,7 +338,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { if !S::SHOULD_EMIT_LINTS { return; } - let id = self.target_id; + let id = self.target.id; (self.emit_lint)(AttributeLint { id, span, kind: lint }); } @@ -535,6 +570,16 @@ impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> { } } +/// Information about the syntactical component this attribute was applied to +pub struct AttributeTarget { + /// The kind of target + pub kind: Target, + /// The target's span + pub span: Span, + /// The target's id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to + pub id: S::Id, +} + /// Context given to every attribute parser during finalization. /// /// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create @@ -544,9 +589,7 @@ pub struct SharedContext<'p, 'sess, S: Stage> { /// diagnostics context. pub(crate) cx: &'p mut AttributeParser<'sess, S>, /// The span of the syntactical component this attribute was applied to - pub(crate) target_span: Span, - /// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to - pub(crate) target_id: S::Id, + pub(crate) target: &'p AttributeTarget, emit_lint: &'p mut dyn FnMut(AttributeLint), } @@ -653,8 +696,7 @@ impl<'sess> AttributeParser<'sess, Early> { sess: &'sess Session, attrs: &[ast::Attribute], sym: Symbol, - target_span: Span, - target_node_id: NodeId, + target: AttributeTarget, features: Option<&'sess Features>, ) -> Option { let mut p = Self { @@ -664,16 +706,10 @@ impl<'sess> AttributeParser<'sess, Early> { sess, stage: Early { emit_errors: ShouldEmit::Nothing }, }; - let mut parsed = p.parse_attribute_list( - attrs, - target_span, - target_node_id, - OmitDoc::Skip, - std::convert::identity, - |_lint| { + let mut parsed = + p.parse_attribute_list(attrs, target, OmitDoc::Skip, std::convert::identity, |_lint| { panic!("can't emit lints here for now (nothing uses this atm)"); - }, - ); + }); assert!(parsed.len() <= 1); parsed.pop() @@ -752,8 +788,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { pub fn parse_attribute_list( &mut self, attrs: &[ast::Attribute], - target_span: Span, - target_id: S::Id, + target: AttributeTarget, omit_doc: OmitDoc, lower_span: impl Copy + Fn(Span) -> Span, @@ -816,8 +851,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext { shared: SharedContext { cx: self, - target_span, - target_id, + target: &target, emit_lint: &mut emit_lint, }, attr_span: lower_span(attr.span), @@ -858,14 +892,9 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { let mut parsed_attributes = Vec::new(); for f in &S::parsers().1 { if let Some(attr) = f(&mut FinalizeContext { - shared: SharedContext { - cx: self, - target_span, - target_id, - emit_lint: &mut emit_lint, - }, + shared: SharedContext { cx: self, target: &target, emit_lint: &mut emit_lint }, all_attrs: &attr_paths, - }) { + }).parsed { parsed_attributes.push(Attribute::Parsed(attr)); } } diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index dc54cb6b840cf..5ad06bfb61f18 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -80,6 +80,7 @@ #![allow(internal_features)] #![doc(rust_logo)] #![feature(rustdoc_internals)] +#![feature(try_trait_v2)] #![recursion_limit = "256"] // tidy-alphabetical-end @@ -95,7 +96,7 @@ pub use attributes::cfg_old::*; pub use attributes::util::{ find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version, }; -pub use context::{AttributeParser, Early, Late, OmitDoc, ShouldEmit}; +pub use context::{AttributeParser, AttributeTarget, Early, Late, OmitDoc, ShouldEmit}; pub use lints::emit_attribute_lint; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 1de25ca252b82..c935b750b9f11 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -705,3 +705,18 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError { diag } } + +#[derive(Diagnostic)] +#[diag(attr_parsing_generic_wrong_target)] +#[help] +pub(crate) struct GenericWrongTarget { + #[primary_span] + pub attr_span: Span, + #[label] + pub target_span: Span, + + pub target: &'static str, + + pub ok_targets: DiagArgValue, + pub num_ok_targets: usize, +} diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index b24e55637613a..2b161788be310 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -188,9 +188,9 @@ use rustc_ast::{ GenericParamKind, Generics, Mutability, PatKind, Safety, VariantData, }; use rustc_attr_data_structures::{AttributeKind, ReprPacked}; -use rustc_attr_parsing::AttributeParser; +use rustc_attr_parsing::{AttributeParser, AttributeTarget}; use rustc_expand::base::{Annotatable, ExtCtxt}; -use rustc_hir::Attribute; +use rustc_hir::{Attribute, Target}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use thin_vec::{ThinVec, thin_vec}; use ty::{Bounds, Path, Ref, Self_, Ty}; @@ -488,8 +488,12 @@ impl<'a> TraitDef<'a> { match item { Annotatable::Item(item) => { let is_packed = matches!( - AttributeParser::parse_limited(cx.sess, &item.attrs, sym::repr, item.span, item.id, None), - Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..))) + AttributeParser::parse_limited(cx.sess, &item.attrs, sym::repr, AttributeTarget { + span: item.span, + id: item.id, + kind: Target::from_ast_item(item), + }), + Some(Attribute::Parsed(AttributeKind::Repr {reprs, ..})) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..))) ); let newitem = match &item.kind { diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index d617f44f8d8e4..2bd7a6a03e4b0 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -6,6 +6,8 @@ use std::fmt::{self, Display}; +use rustc_ast as ast; + use crate::def::DefKind; use crate::{Item, ItemKind, TraitItem, TraitItemKind, hir}; @@ -41,7 +43,9 @@ pub enum Target { Union, Trait, TraitAlias, - Impl { of_trait: bool }, + Impl { + of_trait: bool, + }, Expression, Statement, Arm, @@ -51,12 +55,19 @@ pub enum Target { ForeignFn, ForeignStatic, ForeignTy, - GenericParam { kind: GenericParamKind, has_default: bool }, + GenericParam { + kind: GenericParamKind, + has_default: bool, + }, MacroDef, Param, PatField, ExprField, WherePredicate, + + /// Applying things to macro calls should always be an error. + ErrorMacroCall, + Crate, } impl Display for Target { @@ -98,7 +109,9 @@ impl Target { | Target::Param | Target::PatField | Target::ExprField - | Target::WherePredicate => false, + | Target::WherePredicate + | Target::ErrorMacroCall + | Target::Crate => false, } } @@ -123,6 +136,30 @@ impl Target { } } + pub fn from_ast_item(item: &ast::Item) -> Target { + match item.kind { + ast::ItemKind::ExternCrate(..) => Target::ExternCrate, + ast::ItemKind::Use(..) => Target::Use, + ast::ItemKind::Static { .. } => Target::Static, + ast::ItemKind::Const(..) => Target::Const, + ast::ItemKind::Fn { .. } => Target::Fn, + ast::ItemKind::Mod(..) => Target::Mod, + ast::ItemKind::ForeignMod { .. } => Target::ForeignMod, + ast::ItemKind::GlobalAsm { .. } => Target::GlobalAsm, + ast::ItemKind::TyAlias(..) => Target::TyAlias, + ast::ItemKind::Enum(..) => Target::Enum, + ast::ItemKind::Struct(..) => Target::Struct, + ast::ItemKind::Union(..) => Target::Union, + ast::ItemKind::Trait(..) => Target::Trait, + ast::ItemKind::TraitAlias(..) => Target::TraitAlias, + ast::ItemKind::Impl(ref i) => Target::Impl { of_trait: i.of_trait.is_some() }, + ast::ItemKind::MacCall(..) => Target::ErrorMacroCall, + ast::ItemKind::MacroDef(..) => Target::MacroDef, + ast::ItemKind::Delegation(..) => Target::Fn, + ast::ItemKind::DelegationMac(..) => panic!("macros should be expanded"), + } + } + // FIXME: For now, should only be used with def_kinds from ItemIds pub fn from_def_kind(def_kind: DefKind) -> Target { match def_kind { @@ -167,8 +204,8 @@ impl Target { } } - pub fn from_generic_param(generic_param: &hir::GenericParam<'_>) -> Target { - match generic_param.kind { + pub fn from_generic_param_kind(generic_param_kind: &hir::GenericParamKind<'_>) -> Target { + match generic_param_kind { hir::GenericParamKind::Type { default, .. } => Target::GenericParam { kind: GenericParamKind::Type, has_default: default.is_some(), @@ -227,6 +264,8 @@ impl Target { Target::PatField => "pattern field", Target::ExprField => "struct field", Target::WherePredicate => "where predicate", + Target::ErrorMacroCall => "macro call", + Target::Crate => "crate root", } } } diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index db89396d1dc23..508316f004fb9 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,11 +1,11 @@ use rustc_abi::ExternAbi; use rustc_attr_data_structures::{AttributeKind, ReprAttr, find_attr}; -use rustc_attr_parsing::AttributeParser; +use rustc_attr_parsing::{AttributeParser, AttributeTarget}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{FnKind, Visitor}; -use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind}; +use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind, Target}; use rustc_middle::hir::nested_filter::All; use rustc_middle::ty; use rustc_session::config::CrateType; @@ -167,8 +167,12 @@ impl NonCamelCaseTypes { impl EarlyLintPass for NonCamelCaseTypes { fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) { let has_repr_c = matches!( - AttributeParser::parse_limited(cx.sess(), &it.attrs, sym::repr, it.span, it.id, None), - Some(Attribute::Parsed(AttributeKind::Repr { reprs, ..})) if reprs.iter().any(|(r, _)| r == &ReprAttr::ReprC) + AttributeParser::parse_limited(cx.sess(), &it.attrs, sym::repr, AttributeTarget { + kind: Target::from_ast_item(it), + span: it.span, + id: it.id + }), + Some(Attribute::Parsed(AttributeKind::Repr{reprs, ..})) if reprs.iter().any(|(r, _)| r == &ReprAttr::ReprC) ); if has_repr_c { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0b329cc38b070..f82473098d8b0 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1059,7 +1059,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | Target::GenericParam { .. } | Target::MacroDef | Target::PatField - | Target::ExprField => None, + | Target::ExprField + | Target::ErrorMacroCall + | Target::Crate => None, } { tcx.dcx().emit_err(errors::DocAliasBadLocation { span, attr_str, location }); return; @@ -2859,7 +2861,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { } fn visit_generic_param(&mut self, generic_param: &'tcx hir::GenericParam<'tcx>) { - let target = Target::from_generic_param(generic_param); + let target = Target::from_generic_param_kind(&generic_param.kind); self.check_attributes(generic_param.hir_id, generic_param.span, target, None); intravisit::walk_generic_param(self, generic_param) } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 7d51fef28d3ba..d618f3e8921e2 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -4,9 +4,9 @@ use rustc_ast::visit::FnKind; use rustc_ast::*; use rustc_attr_parsing::{AttributeParser, Early, OmitDoc, ShouldEmit}; use rustc_expand::expand::AstFragment; -use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::def_id::LocalDefId; +use rustc_hir::{self as hir, Target}; use rustc_middle::span_bug; use rustc_span::hygiene::LocalExpnId; use rustc_span::{Span, Symbol, sym}; @@ -136,8 +136,11 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { ); let attrs = parser.parse_attribute_list( &i.attrs, - i.span, - i.id, + rustc_attr_parsing::AttributeTarget { + kind: Target::MacroDef, + span: i.span, + id: i.id, + }, OmitDoc::Skip, std::convert::identity, |_l| {