diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index f4b66b35420..22334a63988 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1016,11 +1016,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect_attr( &mut self, - attr: Option, - derives: Vec, + (attr, derives, after_derive): (Option, Vec, bool), item: Annotatable, kind: AstFragmentKind, - after_derive: bool, ) -> AstFragment { self.collect( kind, @@ -1048,10 +1046,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } /// If `item` is an attr invocation, remove and return the macro attribute and derive traits. - fn classify_item( + fn take_first_attr( &mut self, item: &mut impl HasAttrs, - ) -> (Option, Vec, /* after_derive */ bool) { + ) -> Option<(Option, Vec, /* after_derive */ bool)> { let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); item.visit_attrs(|mut attrs| { @@ -1059,23 +1057,23 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { traits = collect_derives(&mut self.cx, &mut attrs); }); - (attr, traits, after_derive) + if attr.is_some() || !traits.is_empty() { Some((attr, traits, after_derive)) } else { None } } - /// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough + /// Alternative to `take_first_attr()` that ignores `#[derive]` so invocations fallthrough /// to the unused-attributes lint (making it an error on statements and expressions /// is a breaking change) - fn classify_nonitem( + fn take_first_attr_no_derive( &mut self, nonitem: &mut impl HasAttrs, - ) -> (Option, /* after_derive */ bool) { + ) -> Option<(Option, Vec, /* after_derive */ bool)> { let (mut attr, mut after_derive) = (None, false); nonitem.visit_attrs(|mut attrs| { attr = self.find_attr_invoc(&mut attrs, &mut after_derive); }); - (attr, after_derive) + attr.map(|attr| (Some(attr), Vec::new(), after_derive)) } fn configure(&mut self, node: T) -> Option { @@ -1119,23 +1117,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { visit_clobber(expr.deref_mut(), |mut expr| { self.cfg.configure_expr_kind(&mut expr.kind); - // ignore derives so they remain unused - let (attr, after_derive) = self.classify_nonitem(&mut expr); - - if let Some(ref attr_value) = attr { + if let Some(attr) = self.take_first_attr_no_derive(&mut expr) { // Collect the invoc regardless of whether or not attributes are permitted here // expansion will eat the attribute so it won't error later. - self.cfg.maybe_emit_expr_attr_err(attr_value); + attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr)); // AstFragmentKind::Expr requires the macro to emit an expression. return self - .collect_attr( - attr, - vec![], - Annotatable::Expr(P(expr)), - AstFragmentKind::Expr, - after_derive, - ) + .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::Expr) .make_expr() .into_inner(); } @@ -1153,16 +1142,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> { let mut arm = configure!(self, arm); - let (attr, traits, after_derive) = self.classify_item(&mut arm); - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut arm) { return self - .collect_attr( - attr, - traits, - Annotatable::Arm(arm), - AstFragmentKind::Arms, - after_derive, - ) + .collect_attr(attr, Annotatable::Arm(arm), AstFragmentKind::Arms) .make_arms(); } @@ -1172,16 +1154,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> { let mut field = configure!(self, field); - let (attr, traits, after_derive) = self.classify_item(&mut field); - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut field) { return self - .collect_attr( - attr, - traits, - Annotatable::Field(field), - AstFragmentKind::Fields, - after_derive, - ) + .collect_attr(attr, Annotatable::Field(field), AstFragmentKind::Fields) .make_fields(); } @@ -1191,16 +1166,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> { let mut fp = configure!(self, fp); - let (attr, traits, after_derive) = self.classify_item(&mut fp); - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut fp) { return self - .collect_attr( - attr, - traits, - Annotatable::FieldPat(fp), - AstFragmentKind::FieldPats, - after_derive, - ) + .collect_attr(attr, Annotatable::FieldPat(fp), AstFragmentKind::FieldPats) .make_field_patterns(); } @@ -1210,16 +1178,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> { let mut p = configure!(self, p); - let (attr, traits, after_derive) = self.classify_item(&mut p); - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut p) { return self - .collect_attr( - attr, - traits, - Annotatable::Param(p), - AstFragmentKind::Params, - after_derive, - ) + .collect_attr(attr, Annotatable::Param(p), AstFragmentKind::Params) .make_params(); } @@ -1229,16 +1190,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> { let mut sf = configure!(self, sf); - let (attr, traits, after_derive) = self.classify_item(&mut sf); - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut sf) { return self - .collect_attr( - attr, - traits, - Annotatable::StructField(sf), - AstFragmentKind::StructFields, - after_derive, - ) + .collect_attr(attr, Annotatable::StructField(sf), AstFragmentKind::StructFields) .make_struct_fields(); } @@ -1248,16 +1202,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> { let mut variant = configure!(self, variant); - let (attr, traits, after_derive) = self.classify_item(&mut variant); - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut variant) { return self - .collect_attr( - attr, - traits, - Annotatable::Variant(variant), - AstFragmentKind::Variants, - after_derive, - ) + .collect_attr(attr, Annotatable::Variant(variant), AstFragmentKind::Variants) .make_variants(); } @@ -1269,20 +1216,11 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { expr.filter_map(|mut expr| { self.cfg.configure_expr_kind(&mut expr.kind); - // Ignore derives so they remain unused. - let (attr, after_derive) = self.classify_nonitem(&mut expr); - - if let Some(ref attr_value) = attr { - self.cfg.maybe_emit_expr_attr_err(attr_value); + if let Some(attr) = self.take_first_attr_no_derive(&mut expr) { + attr.0.as_ref().map(|attr| self.cfg.maybe_emit_expr_attr_err(attr)); return self - .collect_attr( - attr, - vec![], - Annotatable::Expr(P(expr)), - AstFragmentKind::OptExpr, - after_derive, - ) + .collect_attr(attr, Annotatable::Expr(P(expr)), AstFragmentKind::OptExpr) .make_opt_expr() .map(|expr| expr.into_inner()); } @@ -1321,25 +1259,13 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { // we'll expand attributes on expressions separately if !stmt.is_expr() { - let (attr, derives, after_derive) = if stmt.is_item() { - // FIXME: Handle custom attributes on statements (#15701) - (None, vec![], false) - } else { - // ignore derives on non-item statements so it falls through - // to the unused-attributes lint - let (attr, after_derive) = self.classify_nonitem(&mut stmt); - (attr, vec![], after_derive) - }; + // FIXME: Handle custom attributes on statements (#15701). + let attr = + if stmt.is_item() { None } else { self.take_first_attr_no_derive(&mut stmt) }; - if attr.is_some() || !derives.is_empty() { + if let Some(attr) = attr { return self - .collect_attr( - attr, - derives, - Annotatable::Stmt(P(stmt)), - AstFragmentKind::Stmts, - after_derive, - ) + .collect_attr(attr, Annotatable::Stmt(P(stmt)), AstFragmentKind::Stmts) .make_stmts(); } } @@ -1379,16 +1305,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { let mut item = configure!(self, item); - let (attr, traits, after_derive) = self.classify_item(&mut item); - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut item) { return self - .collect_attr( - attr, - traits, - Annotatable::Item(item), - AstFragmentKind::Items, - after_derive, - ) + .collect_attr(attr, Annotatable::Item(item), AstFragmentKind::Items) .make_items(); } @@ -1482,16 +1401,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn flat_map_trait_item(&mut self, item: P) -> SmallVec<[P; 1]> { let mut item = configure!(self, item); - let (attr, traits, after_derive) = self.classify_item(&mut item); - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut item) { return self - .collect_attr( - attr, - traits, - Annotatable::TraitItem(item), - AstFragmentKind::TraitItems, - after_derive, - ) + .collect_attr(attr, Annotatable::TraitItem(item), AstFragmentKind::TraitItems) .make_trait_items(); } @@ -1512,16 +1424,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { fn flat_map_impl_item(&mut self, item: P) -> SmallVec<[P; 1]> { let mut item = configure!(self, item); - let (attr, traits, after_derive) = self.classify_item(&mut item); - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut item) { return self - .collect_attr( - attr, - traits, - Annotatable::ImplItem(item), - AstFragmentKind::ImplItems, - after_derive, - ) + .collect_attr(attr, Annotatable::ImplItem(item), AstFragmentKind::ImplItems) .make_impl_items(); } @@ -1562,16 +1467,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { &mut self, mut foreign_item: P, ) -> SmallVec<[P; 1]> { - let (attr, traits, after_derive) = self.classify_item(&mut foreign_item); - - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut foreign_item) { return self .collect_attr( attr, - traits, Annotatable::ForeignItem(foreign_item), AstFragmentKind::ForeignItems, - after_derive, ) .make_foreign_items(); } @@ -1606,15 +1507,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { ) -> SmallVec<[ast::GenericParam; 1]> { let mut param = configure!(self, param); - let (attr, traits, after_derive) = self.classify_item(&mut param); - if attr.is_some() || !traits.is_empty() { + if let Some(attr) = self.take_first_attr(&mut param) { return self .collect_attr( attr, - traits, Annotatable::GenericParam(param), AstFragmentKind::GenericParams, - after_derive, ) .make_generic_params(); }