Skip to content

Commit f728939

Browse files
committed
Support impl in foreign modules for macro use
Allow `impl` blocks in foreign modules for more ergonomic use in macros. `impl` blocks still have no meaning in foreign modules and will cause an error if still present during lowering. Also adds explicit tests for the previous similar foreign module macro extensions to ensure that neither this nor those are accepted or crash the compiler when *not* fed to a macro.
1 parent 57ee5cf commit f728939

File tree

37 files changed

+438
-177
lines changed

37 files changed

+438
-177
lines changed

compiler/rustc_ast/src/ast.rs

+5
Original file line numberDiff line numberDiff line change
@@ -3005,6 +3005,9 @@ pub enum ForeignItemKind {
30053005
TyAlias(Box<TyAlias>),
30063006
/// A macro expanding to foreign items.
30073007
MacCall(P<MacCall>),
3008+
/// An impl declaration - parseable for proc_macro purposes, but currently has no meaning in
3009+
/// real Rust code.
3010+
Impl(Box<Impl>),
30083011
}
30093012

30103013
impl From<ForeignItemKind> for ItemKind {
@@ -3014,6 +3017,7 @@ impl From<ForeignItemKind> for ItemKind {
30143017
ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind),
30153018
ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind),
30163019
ForeignItemKind::MacCall(a) => ItemKind::MacCall(a),
3020+
ForeignItemKind::Impl(i) => ItemKind::Impl(i),
30173021
}
30183022
}
30193023
}
@@ -3027,6 +3031,7 @@ impl TryFrom<ItemKind> for ForeignItemKind {
30273031
ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind),
30283032
ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind),
30293033
ItemKind::MacCall(a) => ForeignItemKind::MacCall(a),
3034+
ItemKind::Impl(i) => ForeignItemKind::Impl(i),
30303035
_ => return Err(item_kind),
30313036
})
30323037
}

compiler/rustc_ast/src/mut_visit.rs

+19
Original file line numberDiff line numberDiff line change
@@ -1198,6 +1198,25 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
11981198
visit_opt(ty, |ty| visitor.visit_ty(ty));
11991199
}
12001200
ForeignItemKind::MacCall(mac) => visitor.visit_mac_call(mac),
1201+
ForeignItemKind::Impl(box Impl {
1202+
defaultness,
1203+
unsafety,
1204+
generics,
1205+
constness,
1206+
polarity,
1207+
of_trait,
1208+
self_ty,
1209+
items,
1210+
}) => {
1211+
visit_defaultness(defaultness, visitor);
1212+
visit_unsafety(unsafety, visitor);
1213+
visitor.visit_generics(generics);
1214+
visit_constness(constness, visitor);
1215+
visit_polarity(polarity, visitor);
1216+
visit_opt(of_trait, |trait_ref| visitor.visit_trait_ref(trait_ref));
1217+
visitor.visit_ty(self_ty);
1218+
items.flat_map_in_place(|item| visitor.flat_map_impl_item(item));
1219+
}
12011220
}
12021221
visitor.visit_span(span);
12031222
visit_lazy_tts(tokens, visitor);

compiler/rustc_ast/src/visit.rs

+15
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,21 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI
575575
ForeignItemKind::MacCall(mac) => {
576576
visitor.visit_mac_call(mac);
577577
}
578+
ForeignItemKind::Impl(box Impl {
579+
defaultness: _,
580+
unsafety: _,
581+
ref generics,
582+
constness: _,
583+
polarity: _,
584+
ref of_trait,
585+
ref self_ty,
586+
ref items,
587+
}) => {
588+
visitor.visit_generics(generics);
589+
walk_list!(visitor, visit_trait_ref, of_trait);
590+
visitor.visit_ty(self_ty);
591+
walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl);
592+
}
578593
}
579594
}
580595

compiler/rustc_ast_lowering/src/item.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,11 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
142142
// Evaluate with the lifetimes in `params` in-scope.
143143
// This is used to track which lifetimes have already been defined,
144144
// and which need to be replicated when lowering an async fn.
145-
match parent_hir.node().expect_item().kind {
146-
hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }) => {
145+
match parent_hir.node() {
146+
hir::OwnerNode::Item(hir::Item {
147+
kind: hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }),
148+
..
149+
}) => {
147150
lctx.is_in_trait_impl = of_trait.is_some();
148151
}
149152
_ => {}
@@ -685,6 +688,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
685688
}
686689
ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type,
687690
ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"),
691+
// This is not a type, but we will have emitted an error earlier and want the
692+
// compiler to finish its work cleanly.
693+
ForeignItemKind::Impl(_) => hir::ForeignItemKind::Type,
688694
},
689695
vis_span: self.lower_span(i.vis.span),
690696
span: self.lower_span(i.span),

compiler/rustc_ast_passes/src/ast_validation.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12851285
self.check_foreign_item_ascii_only(fi.ident);
12861286
}
12871287
ForeignItemKind::MacCall(..) => {}
1288+
ForeignItemKind::Impl(..) => {
1289+
self.err_handler()
1290+
.struct_span_err(fi.span, "`impl` blocks are not allowed in `extern` blocks")
1291+
.emit();
1292+
return;
1293+
}
12881294
}
12891295

12901296
visit::walk_foreign_item(self, fi)

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
356356
gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
357357
}
358358
ast::ForeignItemKind::MacCall(..) => {}
359+
ast::ForeignItemKind::Impl(..) => {}
359360
}
360361

361362
visit::walk_foreign_item(self, i)

compiler/rustc_ast_pretty/src/pprust/state/item.rs

+47
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,53 @@ impl<'a> State<'a> {
5858
self.word(";");
5959
}
6060
}
61+
ast::ForeignItemKind::Impl(box ast::Impl {
62+
unsafety,
63+
polarity,
64+
defaultness,
65+
constness,
66+
ref generics,
67+
ref of_trait,
68+
ref self_ty,
69+
ref items,
70+
}) => {
71+
self.head("");
72+
self.print_visibility(&item.vis);
73+
self.print_defaultness(*defaultness);
74+
self.print_unsafety(*unsafety);
75+
self.word("impl");
76+
77+
if generics.params.is_empty() {
78+
self.nbsp();
79+
} else {
80+
self.print_generic_params(&generics.params);
81+
self.space();
82+
}
83+
84+
self.print_constness(*constness);
85+
86+
if let ast::ImplPolarity::Negative(_) = polarity {
87+
self.word("!");
88+
}
89+
90+
if let Some(ref t) = *of_trait {
91+
self.print_trait_ref(t);
92+
self.space();
93+
self.word_space("for");
94+
}
95+
96+
self.print_type(self_ty);
97+
self.print_where_clause(&generics.where_clause);
98+
99+
self.space();
100+
self.bopen();
101+
self.print_inner_attributes(&item.attrs);
102+
for impl_item in items {
103+
self.print_assoc_item(impl_item);
104+
}
105+
let empty = item.attrs.is_empty() && items.is_empty();
106+
self.bclose(item.span, empty);
107+
}
61108
}
62109
self.ann.post(self, AnnNode::SubItem(id))
63110
}

compiler/rustc_hir/src/hir.rs

+2
Original file line numberDiff line numberDiff line change
@@ -3186,6 +3186,8 @@ pub enum ForeignItemKind<'hir> {
31863186
Static(&'hir Ty<'hir>, Mutability),
31873187
/// A foreign type.
31883188
Type,
3189+
/// A foreign impl (currently meaningless)
3190+
Impl(&'hir Impl<'hir>),
31893191
}
31903192

31913193
/// A variable captured by a closure.

compiler/rustc_hir/src/intravisit.rs

+10-15
Original file line numberDiff line numberDiff line change
@@ -564,22 +564,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
564564
// `visit_enum_def()` takes care of visiting the `Item`'s `HirId`.
565565
visitor.visit_enum_def(enum_definition, item.hir_id())
566566
}
567-
ItemKind::Impl(Impl {
568-
unsafety: _,
569-
defaultness: _,
570-
polarity: _,
571-
constness: _,
572-
defaultness_span: _,
573-
ref generics,
574-
ref of_trait,
575-
ref self_ty,
576-
items,
577-
}) => {
567+
ItemKind::Impl(impl_) => {
578568
visitor.visit_id(item.hir_id());
579-
visitor.visit_generics(generics);
580-
walk_list!(visitor, visit_trait_ref, of_trait);
581-
visitor.visit_ty(self_ty);
582-
walk_list!(visitor, visit_impl_item_ref, *items);
569+
walk_impl(visitor, impl_);
583570
}
584571
ItemKind::Struct(ref struct_definition, ref generics)
585572
| ItemKind::Union(ref struct_definition, ref generics) => {
@@ -798,6 +785,7 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v
798785
}
799786
ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
800787
ForeignItemKind::Type => (),
788+
ForeignItemKind::Impl(ref impl_) => walk_impl(visitor, impl_),
801789
}
802790
}
803791

@@ -978,6 +966,13 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
978966
}
979967
}
980968

969+
pub fn walk_impl<'v, V: Visitor<'v>>(visitor: &mut V, impl_: &'v Impl<'v>) {
970+
visitor.visit_generics(impl_.generics);
971+
walk_list!(visitor, visit_trait_ref, &impl_.of_trait);
972+
visitor.visit_ty(impl_.self_ty);
973+
walk_list!(visitor, visit_impl_item_ref, impl_.items);
974+
}
975+
981976
pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>(
982977
visitor: &mut V,
983978
foreign_item_ref: &'v ForeignItemRef,

compiler/rustc_hir/src/target.rs

+1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ impl Target {
139139
hir::ForeignItemKind::Fn(..) => Target::ForeignFn,
140140
hir::ForeignItemKind::Static(..) => Target::ForeignStatic,
141141
hir::ForeignItemKind::Type => Target::ForeignTy,
142+
hir::ForeignItemKind::Impl(..) => Target::Impl,
142143
}
143144
}
144145

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
260260
}
261261
hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true),
262262
hir::ForeignItemKind::Type => (),
263+
hir::ForeignItemKind::Impl(..) => (),
263264
}
264265
}
265266

compiler/rustc_hir_analysis/src/collect.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2217,7 +2217,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
22172217

22182218
Node::ForeignItem(item) => match item.kind {
22192219
ForeignItemKind::Static(..) => NO_GENERICS,
2220-
ForeignItemKind::Fn(_, _, ref generics) => *generics,
2220+
ForeignItemKind::Fn(_, _, ref generics)
2221+
| ForeignItemKind::Impl(hir::Impl { ref generics, .. }) => *generics,
22212222
ForeignItemKind::Type => NO_GENERICS,
22222223
},
22232224

compiler/rustc_hir_analysis/src/collect/type_of.rs

+1
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
364364
}
365365
ForeignItemKind::Static(t, _) => icx.to_ty(t),
366366
ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()),
367+
ForeignItemKind::Impl(..) => span_bug!(foreign_item.span, "compute_type_of_foreign_item: unexpected item type: {:?}", foreign_item.kind),
367368
},
368369

369370
Node::Ctor(&ref def) | Node::Variant(Variant { data: ref def, .. }) => match *def {

compiler/rustc_hir_pretty/src/lib.rs

+46-47
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,8 @@ impl<'a> State<'a> {
375375
pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) {
376376
self.hardbreak_if_not_bol();
377377
self.maybe_print_comment(item.span.lo());
378-
self.print_outer_attributes(self.attrs(item.hir_id()));
378+
let attrs = self.attrs(item.hir_id());
379+
self.print_outer_attributes(attrs);
379380
match item.kind {
380381
hir::ForeignItemKind::Fn(decl, arg_names, generics) => {
381382
self.head("");
@@ -415,6 +416,7 @@ impl<'a> State<'a> {
415416
self.end(); // end the head-ibox
416417
self.end() // end the outer cbox
417418
}
419+
hir::ForeignItemKind::Impl(impl_) => self.print_impl(impl_, attrs, item.span),
418420
}
419421
}
420422

@@ -477,6 +479,48 @@ impl<'a> State<'a> {
477479
self.end(); // end the outer ibox
478480
}
479481

482+
fn print_impl(
483+
&mut self,
484+
impl_: &hir::Impl<'_>,
485+
attrs: &[ast::Attribute],
486+
span: rustc_span::Span,
487+
) {
488+
self.head("");
489+
self.print_defaultness(impl_.defaultness);
490+
self.print_unsafety(impl_.unsafety);
491+
self.word_nbsp("impl");
492+
493+
if !impl_.generics.params.is_empty() {
494+
self.print_generic_params(impl_.generics.params);
495+
self.space();
496+
}
497+
498+
if impl_.constness == hir::Constness::Const {
499+
self.word_nbsp("const");
500+
}
501+
502+
if let hir::ImplPolarity::Negative(_) = impl_.polarity {
503+
self.word("!");
504+
}
505+
506+
if let Some(ref t) = impl_.of_trait {
507+
self.print_trait_ref(t);
508+
self.space();
509+
self.word_space("for");
510+
}
511+
512+
self.print_type(impl_.self_ty);
513+
self.print_where_clause(impl_.generics);
514+
515+
self.space();
516+
self.bopen();
517+
self.print_inner_attributes(attrs);
518+
for impl_item in impl_.items {
519+
self.ann.nested(self, Nested::ImplItem(impl_item.id));
520+
}
521+
self.bclose(span);
522+
}
523+
480524
/// Pretty-print an item
481525
pub fn print_item(&mut self, item: &hir::Item<'_>) {
482526
self.hardbreak_if_not_bol();
@@ -619,52 +663,7 @@ impl<'a> State<'a> {
619663
self.head("union");
620664
self.print_struct(struct_def, generics, item.ident.name, item.span, true);
621665
}
622-
hir::ItemKind::Impl(&hir::Impl {
623-
unsafety,
624-
polarity,
625-
defaultness,
626-
constness,
627-
defaultness_span: _,
628-
generics,
629-
ref of_trait,
630-
self_ty,
631-
items,
632-
}) => {
633-
self.head("");
634-
self.print_defaultness(defaultness);
635-
self.print_unsafety(unsafety);
636-
self.word_nbsp("impl");
637-
638-
if !generics.params.is_empty() {
639-
self.print_generic_params(generics.params);
640-
self.space();
641-
}
642-
643-
if constness == hir::Constness::Const {
644-
self.word_nbsp("const");
645-
}
646-
647-
if let hir::ImplPolarity::Negative(_) = polarity {
648-
self.word("!");
649-
}
650-
651-
if let Some(t) = of_trait {
652-
self.print_trait_ref(t);
653-
self.space();
654-
self.word_space("for");
655-
}
656-
657-
self.print_type(self_ty);
658-
self.print_where_clause(generics);
659-
660-
self.space();
661-
self.bopen();
662-
self.print_inner_attributes(attrs);
663-
for impl_item in items {
664-
self.ann.nested(self, Nested::ImplItem(impl_item.id));
665-
}
666-
self.bclose(item.span);
667-
}
666+
hir::ItemKind::Impl(impl_) => self.print_impl(impl_, attrs, item.span),
668667
hir::ItemKind::Trait(is_auto, unsafety, generics, bounds, trait_items) => {
669668
self.head("");
670669
self.print_is_auto(is_auto);

compiler/rustc_lint/src/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations {
13021302
hir::ForeignItemKind::Static(ref ty, _) => {
13031303
vis.check_foreign_static(it.hir_id(), ty.span);
13041304
}
1305-
hir::ForeignItemKind::Type => (),
1305+
hir::ForeignItemKind::Type | hir::ForeignItemKind::Impl(..) => (),
13061306
}
13071307
}
13081308
}

0 commit comments

Comments
 (0)