Skip to content

Commit 79cd224

Browse files
committed
Auto merge of rust-lang#69366 - Centril:unified-items, r=petrochenkov
parse: unify item parsing & filter illegal item kinds This PR fully unifies item parsing into a single `fn parse_item_common` method which produces `Option<Item>`. The `Item` is then mapped into `ForeignItem` and `AssocItem` as necessary by transforming the `*Kind` and converting contextually bad variants into `None`, thereby filtering them away. The PR does not yet unmerge the definition of `ForeignItemKind` from `AssocItemKind`. I've left that as future work as it didn't feel like this parser-focused PR would be the best one to deal with it. Changes to the AST data structures are instead kept to a reasonable minimum. Based on rust-lang#69361. Fixes rust-lang#48137. RELNOTES: Now, `item` macro fragments can be interpolated into `impl`, `trait`, and `extern` contexts. See `src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs` for the relevant test. r? @petrochenkov cc @estebank
2 parents 6d0e58b + 1c75f5a commit 79cd224

File tree

88 files changed

+1977
-644
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+1977
-644
lines changed

src/librustc_ast_lowering/item.rs

+28-32
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
173173
}
174174
ids
175175
}
176-
ItemKind::Const(ref ty, ..) => {
176+
ItemKind::Const(_, ref ty, ..) => {
177177
let mut ids = smallvec![i.id];
178178
if self.sess.features_untracked().impl_trait_in_bindings {
179179
let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids };
@@ -264,11 +264,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
264264
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
265265
hir::ItemKind::Static(ty, m, body_id)
266266
}
267-
ItemKind::Const(ref t, ref e) => {
267+
ItemKind::Const(_, ref t, ref e) => {
268268
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
269269
hir::ItemKind::Const(ty, body_id)
270270
}
271-
ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => {
271+
ItemKind::Fn(_, FnSig { ref decl, header }, ref generics, ref body) => {
272272
let fn_def_id = self.resolver.definitions().local_def_id(id);
273273
self.with_new_scopes(|this| {
274274
this.current_item = Some(ident.span);
@@ -297,24 +297,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
297297
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
298298
ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
299299
ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
300-
ItemKind::TyAlias(ref generics, _, Some(ref ty)) => match ty.kind.opaque_top_hack() {
300+
ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => match ty.kind.opaque_top_hack() {
301301
None => {
302302
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
303-
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
303+
let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
304304
hir::ItemKind::TyAlias(ty, generics)
305305
}
306306
Some(bounds) => {
307307
let ctx = || ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc);
308308
let ty = hir::OpaqueTy {
309-
generics: self.lower_generics(generics, ctx()),
309+
generics: self.lower_generics(gen, ctx()),
310310
bounds: self.lower_param_bounds(bounds, ctx()),
311311
impl_trait_fn: None,
312312
origin: hir::OpaqueTyOrigin::TypeAlias,
313313
};
314314
hir::ItemKind::OpaqueTy(ty)
315315
}
316316
},
317-
ItemKind::TyAlias(ref generics, _, None) => {
317+
ItemKind::TyAlias(_, ref generics, _, None) => {
318318
let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err));
319319
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
320320
hir::ItemKind::TyAlias(ty, generics)
@@ -654,7 +654,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
654654
ident: i.ident,
655655
attrs: self.lower_attrs(&i.attrs),
656656
kind: match i.kind {
657-
ForeignItemKind::Fn(ref sig, ref generics, _) => {
657+
ForeignItemKind::Fn(_, ref sig, ref generics, _) => {
658658
let fdec = &sig.decl;
659659
let (generics, (fn_dec, fn_args)) = self.add_in_band_defs(
660660
generics,
@@ -675,7 +675,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
675675
let ty = self.lower_ty(t, ImplTraitContext::disallowed());
676676
hir::ForeignItemKind::Static(ty, m)
677677
}
678-
ForeignItemKind::Const(ref t, _) => {
678+
ForeignItemKind::Const(_, ref t, _) => {
679679
// For recovery purposes.
680680
let ty = self.lower_ty(t, ImplTraitContext::disallowed());
681681
hir::ForeignItemKind::Static(ty, Mutability::Not)
@@ -758,24 +758,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
758758

759759
let (generics, kind) = match i.kind {
760760
AssocItemKind::Static(ref ty, _, ref default) // Let's pretend this is a `const`.
761-
| AssocItemKind::Const(ref ty, ref default) => {
761+
| AssocItemKind::Const(_, ref ty, ref default) => {
762762
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
763763
let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
764764
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body))
765765
}
766-
AssocItemKind::Fn(ref sig, ref generics, None) => {
766+
AssocItemKind::Fn(_, ref sig, ref generics, None) => {
767767
let names = self.lower_fn_params_to_names(&sig.decl);
768768
let (generics, sig) =
769769
self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
770770
(generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names)))
771771
}
772-
AssocItemKind::Fn(ref sig, ref generics, Some(ref body)) => {
772+
AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => {
773773
let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
774774
let (generics, sig) =
775775
self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
776776
(generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id)))
777777
}
778-
AssocItemKind::TyAlias(ref generics, ref bounds, ref default) => {
778+
AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => {
779779
let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed()));
780780
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
781781
let kind = hir::TraitItemKind::Type(
@@ -801,22 +801,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
801801
fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef {
802802
let (kind, has_default) = match &i.kind {
803803
AssocItemKind::Static(_, _, default) // Let's pretend this is a `const` for recovery.
804-
| AssocItemKind::Const(_, default) => {
804+
| AssocItemKind::Const(_, _, default) => {
805805
(hir::AssocItemKind::Const, default.is_some())
806806
}
807-
AssocItemKind::TyAlias(_, _, default) => (hir::AssocItemKind::Type, default.is_some()),
808-
AssocItemKind::Fn(sig, _, default) => {
807+
AssocItemKind::TyAlias(_, _, _, default) => (hir::AssocItemKind::Type, default.is_some()),
808+
AssocItemKind::Fn(_, sig, _, default) => {
809809
(hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some())
810810
}
811811
AssocItemKind::Macro(..) => unimplemented!(),
812812
};
813-
hir::TraitItemRef {
814-
id: hir::TraitItemId { hir_id: self.lower_node_id(i.id) },
815-
ident: i.ident,
816-
span: i.span,
817-
defaultness: self.lower_defaultness(Defaultness::Default, has_default),
818-
kind,
819-
}
813+
let id = hir::TraitItemId { hir_id: self.lower_node_id(i.id) };
814+
let defaultness = hir::Defaultness::Default { has_value: has_default };
815+
hir::TraitItemRef { id, ident: i.ident, span: i.span, defaultness, kind }
820816
}
821817

822818
/// Construct `ExprKind::Err` for the given `span`.
@@ -827,15 +823,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
827823
fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> {
828824
let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
829825

830-
let (generics, kind) = match i.kind {
831-
AssocItemKind::Static(ref ty, _, ref expr) | AssocItemKind::Const(ref ty, ref expr) => {
826+
let (generics, kind) = match &i.kind {
827+
AssocItemKind::Static(ty, _, expr) | AssocItemKind::Const(_, ty, expr) => {
832828
let ty = self.lower_ty(ty, ImplTraitContext::disallowed());
833829
(
834830
hir::Generics::empty(),
835831
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
836832
)
837833
}
838-
AssocItemKind::Fn(ref sig, ref generics, ref body) => {
834+
AssocItemKind::Fn(_, sig, generics, body) => {
839835
self.current_item = Some(i.span);
840836
let asyncness = sig.header.asyncness;
841837
let body_id =
@@ -851,7 +847,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
851847

852848
(generics, hir::ImplItemKind::Method(sig, body_id))
853849
}
854-
AssocItemKind::TyAlias(ref generics, _, ref ty) => {
850+
AssocItemKind::TyAlias(_, generics, _, ty) => {
855851
let generics = self.lower_generics(generics, ImplTraitContext::disallowed());
856852
let kind = match ty {
857853
None => {
@@ -880,7 +876,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
880876
attrs: self.lower_attrs(&i.attrs),
881877
generics,
882878
vis: self.lower_visibility(&i.vis, None),
883-
defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
879+
defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */),
884880
kind,
885881
span: i.span,
886882
}
@@ -894,17 +890,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
894890
ident: i.ident,
895891
span: i.span,
896892
vis: self.lower_visibility(&i.vis, Some(i.id)),
897-
defaultness: self.lower_defaultness(i.defaultness, true /* [1] */),
893+
defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */),
898894
kind: match &i.kind {
899895
AssocItemKind::Static(..) // Let's pretend this is a `const` for recovery.
900896
| AssocItemKind::Const(..) => hir::AssocItemKind::Const,
901-
AssocItemKind::TyAlias(_, _, ty) => {
897+
AssocItemKind::TyAlias(.., ty) => {
902898
match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) {
903899
None => hir::AssocItemKind::Type,
904900
Some(_) => hir::AssocItemKind::OpaqueTy,
905901
}
906902
}
907-
AssocItemKind::Fn(sig, _, _) => {
903+
AssocItemKind::Fn(_, sig, ..) => {
908904
hir::AssocItemKind::Method { has_self: sig.decl.has_self() }
909905
}
910906
AssocItemKind::Macro(..) => unimplemented!(),
@@ -948,7 +944,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
948944

949945
fn lower_defaultness(&self, d: Defaultness, has_value: bool) -> hir::Defaultness {
950946
match d {
951-
Defaultness::Default => hir::Defaultness::Default { has_value: has_value },
947+
Defaultness::Default(_) => hir::Defaultness::Default { has_value },
952948
Defaultness::Final => {
953949
assert!(has_value);
954950
hir::Defaultness::Final

src/librustc_ast_lowering/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
462462
ItemKind::Struct(_, ref generics)
463463
| ItemKind::Union(_, ref generics)
464464
| ItemKind::Enum(_, ref generics)
465-
| ItemKind::TyAlias(ref generics, ..)
465+
| ItemKind::TyAlias(_, ref generics, ..)
466466
| ItemKind::Trait(_, _, ref generics, ..) => {
467467
let def_id = self.lctx.resolver.definitions().local_def_id(item.id);
468468
let count = generics
@@ -490,7 +490,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
490490
self.lctx.allocate_hir_id_counter(item.id);
491491
let owner = match (&item.kind, ctxt) {
492492
// Ignore patterns in trait methods without bodies.
493-
(AssocItemKind::Fn(_, _, None), AssocCtxt::Trait) => None,
493+
(AssocItemKind::Fn(_, _, _, None), AssocCtxt::Trait) => None,
494494
_ => Some(item.id),
495495
};
496496
self.with_hir_id_owner(owner, |this| visit::walk_assoc_item(this, item, ctxt));

src/librustc_ast_passes/ast_validation.rs

+24-15
Original file line numberDiff line numberDiff line change
@@ -400,9 +400,11 @@ impl<'a> AstValidator<'a> {
400400
}
401401

402402
fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
403-
if let Defaultness::Default = defaultness {
403+
if let Defaultness::Default(def_span) = defaultness {
404+
let span = self.session.source_map().def_span(span);
404405
self.err_handler()
405406
.struct_span_err(span, "`default` is only allowed on items in `impl` definitions")
407+
.span_label(def_span, "`default` because of this")
406408
.emit();
407409
}
408410
}
@@ -863,10 +865,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
863865
if polarity == ImplPolarity::Negative {
864866
self.err_handler().span_err(item.span, "inherent impls cannot be negative");
865867
}
866-
if defaultness == Defaultness::Default {
868+
if let Defaultness::Default(def_span) = defaultness {
869+
let span = self.session.source_map().def_span(item.span);
867870
self.err_handler()
868-
.struct_span_err(item.span, "inherent impls cannot be default")
869-
.note("only trait implementations may be annotated with default")
871+
.struct_span_err(span, "inherent impls cannot be `default`")
872+
.span_label(def_span, "`default` because of this")
873+
.note("only trait implementations may be annotated with `default`")
870874
.emit();
871875
}
872876
if let Const::Yes(span) = constness {
@@ -877,7 +881,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
877881
.emit();
878882
}
879883
}
880-
ItemKind::Fn(ref sig, ref generics, ref body) => {
884+
ItemKind::Fn(def, ref sig, ref generics, ref body) => {
885+
self.check_defaultness(item.span, def);
881886
self.check_const_fn_const_generic(item.span, sig, generics);
882887

883888
if body.is_none() {
@@ -961,15 +966,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
961966
self.err_handler().span_err(item.span, "unions cannot have zero fields");
962967
}
963968
}
964-
ItemKind::Const(.., None) => {
969+
ItemKind::Const(def, .., None) => {
970+
self.check_defaultness(item.span, def);
965971
let msg = "free constant item without body";
966972
self.error_item_without_body(item.span, "constant", msg, " = <expr>;");
967973
}
968974
ItemKind::Static(.., None) => {
969975
let msg = "free static item without body";
970976
self.error_item_without_body(item.span, "static", msg, " = <expr>;");
971977
}
972-
ItemKind::TyAlias(_, ref bounds, ref body) => {
978+
ItemKind::TyAlias(def, _, ref bounds, ref body) => {
979+
self.check_defaultness(item.span, def);
973980
if body.is_none() {
974981
let msg = "free type alias without body";
975982
self.error_item_without_body(item.span, "type", msg, " = <type>;");
@@ -984,11 +991,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
984991

985992
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
986993
match &fi.kind {
987-
ForeignItemKind::Fn(sig, _, body) => {
994+
ForeignItemKind::Fn(def, sig, _, body) => {
995+
self.check_defaultness(fi.span, *def);
988996
self.check_foreign_fn_bodyless(fi.ident, body.as_deref());
989997
self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header);
990998
}
991-
ForeignItemKind::TyAlias(generics, bounds, body) => {
999+
ForeignItemKind::TyAlias(def, generics, bounds, body) => {
1000+
self.check_defaultness(fi.span, *def);
9921001
self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span));
9931002
self.check_type_no_bounds(bounds, "`extern` blocks");
9941003
self.check_foreign_ty_genericless(generics);
@@ -1229,19 +1238,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12291238
}
12301239

12311240
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
1232-
if ctxt == AssocCtxt::Trait {
1233-
self.check_defaultness(item.span, item.defaultness);
1241+
if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
1242+
self.check_defaultness(item.span, item.kind.defaultness());
12341243
}
12351244

12361245
if ctxt == AssocCtxt::Impl {
12371246
match &item.kind {
1238-
AssocItemKind::Const(_, body) => {
1247+
AssocItemKind::Const(_, _, body) => {
12391248
self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
12401249
}
1241-
AssocItemKind::Fn(_, _, body) => {
1250+
AssocItemKind::Fn(_, _, _, body) => {
12421251
self.check_impl_item_provided(item.span, body, "function", " { <body> }");
12431252
}
1244-
AssocItemKind::TyAlias(_, bounds, body) => {
1253+
AssocItemKind::TyAlias(_, _, bounds, body) => {
12451254
self.check_impl_item_provided(item.span, body, "type", " = <type>;");
12461255
self.check_type_no_bounds(bounds, "`impl`s");
12471256
}
@@ -1251,7 +1260,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12511260

12521261
if ctxt == AssocCtxt::Trait || self.in_trait_impl {
12531262
self.invalid_visibility(&item.vis, None);
1254-
if let AssocItemKind::Fn(sig, _, _) = &item.kind {
1263+
if let AssocItemKind::Fn(_, sig, _, _) = &item.kind {
12551264
self.check_trait_fn_not_const(sig.header.constness);
12561265
self.check_trait_fn_not_async(item.span, sig.header.asyncness);
12571266
}

src/librustc_ast_passes/feature_gate.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
349349
);
350350
}
351351

352-
if let ast::Defaultness::Default = defaultness {
352+
if let ast::Defaultness::Default(_) = defaultness {
353353
gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
354354
}
355355
}
@@ -372,7 +372,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
372372
gate_feature_post!(&self, decl_macro, i.span, msg);
373373
}
374374

375-
ast::ItemKind::TyAlias(_, _, Some(ref ty)) => self.check_impl_trait(&ty),
375+
ast::ItemKind::TyAlias(_, _, _, Some(ref ty)) => self.check_impl_trait(&ty),
376376

377377
_ => {}
378378
}
@@ -543,17 +543,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
543543
}
544544

545545
fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
546-
if i.defaultness == ast::Defaultness::Default {
546+
if let ast::Defaultness::Default(_) = i.kind.defaultness() {
547547
gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
548548
}
549549

550550
match i.kind {
551-
ast::AssocItemKind::Fn(ref sig, _, _) => {
551+
ast::AssocItemKind::Fn(_, ref sig, _, _) => {
552552
if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) {
553553
gate_feature_post!(&self, const_fn, i.span, "const fn is unstable");
554554
}
555555
}
556-
ast::AssocItemKind::TyAlias(ref generics, _, ref ty) => {
556+
ast::AssocItemKind::TyAlias(_, ref generics, _, ref ty) => {
557557
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
558558
gate_feature_post!(
559559
&self,

0 commit comments

Comments
 (0)