Change:
currently happily ignores any additional attributes in case there are more than one. While this is fine for attributes which don't care about duplicates or emit a warning/error in case there are more than one, this isn't currently checked in the compiler, potentially causing bugs. similar to the check in we should check that the attr declaration in has an acceptable way of dealing with duplicates. in case there are any questions on how to implement this, feel free to open a thread on zulip and pinging me there. <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
claim

Discussion:
) { let span = cx .tcx <del> .get_attr(instance.def_id(), sym::target_feature) </del> <ins> .get_attrs(instance.def_id(), sym::target_feature) .next() </ins> .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span); let msg = format!( "the target features {} must all be either enabled or disabled together",

BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local) } <ins> pub fn is_valid_for_get_attr(name: Symbol) -> bool { BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| match attr.duplicates { WarnFollowing | ErrorFollowing | ErrorPreceding | FutureWarnFollowing | FutureWarnPreceding => true, DuplicatesOk | WarnFollowingWordOnly => false, }) } </ins> pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> = LazyLock::new(|| { let mut map = FxHashMap::default();

pub use builtin_attrs::AttributeDuplicates; pub use builtin_attrs::{ deprecated_attributes, find_gated_cfg, is_builtin_attr_name, is_builtin_only_local, <del> AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, </del> <ins> is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP, </ins> }; pub use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};

} pub fn get_attr(self, did: DefId, attr: Symbol) -> Option<&'tcx ast::Attribute> { <del> self.get_attrs(did, attr).next() </del> <ins> if cfg!(debug_assertions) && !rustc_feature::is_valid_for_get_attr(attr) { bug!("get_attr: unexpected called with DefId `{:?}`, attr `{:?}`", did, attr); } else { self.get_attrs(did, attr).next() } </ins> } /// Determines whether an item is annotated with an attribute.

def.destructor(tcx); // force the destructor to be evaluated if vs.is_empty() { <del> if let Some(attr) = tcx.get_attr(def_id.to_def_id(), sym::repr) { </del> <ins> if let Some(attr) = tcx.get_attrs(def_id.to_def_id(), sym::repr).next() { </ins> struct_span_err!( tcx.sess, attr.span,

<ins> // issue #100631, make sure `TyCtxt::get_attr` only called by case that compiler // can reasonably deal with multiple attributes. // `repr` will use `TyCtxt::get_attrs` since it's `DuplicatesOk`. #[repr(C)] //~ ERROR: unsupported representation for zero-variant enum [E0084] #[repr(C)] enum Foo {} fn main() {} </ins>

<ins> error[E0084]: unsupported representation for zero-variant enum --> $DIR/issue-100631.rs:4:1 | LL | #[repr(C)] | ^^^^^^^^^^ LL | #[repr(C)] LL | enum Foo {} | -------- zero-variant enum error: aborting due to previous error For more information about this error, try `rustc --explain E0084`. </ins>