From f728939a12e7fba48958d49f19ed117926a491fc Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Sat, 17 Sep 2022 13:24:03 -0700 Subject: [PATCH] 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. --- compiler/rustc_ast/src/ast.rs | 5 + compiler/rustc_ast/src/mut_visit.rs | 19 +++ compiler/rustc_ast/src/visit.rs | 15 ++ compiler/rustc_ast_lowering/src/item.rs | 10 +- .../rustc_ast_passes/src/ast_validation.rs | 6 + compiler/rustc_ast_passes/src/feature_gate.rs | 1 + .../rustc_ast_pretty/src/pprust/state/item.rs | 47 +++++++ compiler/rustc_hir/src/hir.rs | 2 + compiler/rustc_hir/src/intravisit.rs | 25 ++-- compiler/rustc_hir/src/target.rs | 1 + .../rustc_hir_analysis/src/check/wfcheck.rs | 1 + compiler/rustc_hir_analysis/src/collect.rs | 3 +- .../rustc_hir_analysis/src/collect/type_of.rs | 1 + compiler/rustc_hir_pretty/src/lib.rs | 93 +++++++------ compiler/rustc_lint/src/types.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +- compiler/rustc_middle/src/hir/map/mod.rs | 1 + compiler/rustc_passes/src/hir_stats.rs | 4 +- .../rustc_resolve/src/build_reduced_graph.rs | 1 + compiler/rustc_resolve/src/late.rs | 17 +++ compiler/rustc_resolve/src/late/lifetimes.rs | 8 +- .../rustc_save_analysis/src/dump_visitor.rs | 1 + compiler/rustc_save_analysis/src/lib.rs | 2 + compiler/rustc_save_analysis/src/sig.rs | 1 + compiler/rustc_ty_utils/src/assoc.rs | 63 ++++++--- src/librustdoc/clean/mod.rs | 2 + src/test/ui/macro-only/extern-impl-block.rs | 11 ++ .../ui/macro-only/extern-impl-block.stderr | 10 ++ src/test/ui/macro-only/unsafe-foreign-mod.rs | 7 + .../ui/macro-only/unsafe-foreign-mod.stderr | 17 +++ src/test/ui/macro-only/unsafe-mod.rs | 8 ++ src/test/ui/macro-only/unsafe-mod.stderr | 23 ++++ .../ui/parser/default-on-wrong-item-kind.rs | 1 - .../parser/default-on-wrong-item-kind.stderr | 130 ++++++++---------- .../proc-macro/auxiliary/macro-only-syntax.rs | 19 +++ src/test/ui/proc-macro/extern-impl-block.rs | 13 ++ src/tools/rustfmt/src/items.rs | 41 ++++-- 37 files changed, 438 insertions(+), 177 deletions(-) create mode 100644 src/test/ui/macro-only/extern-impl-block.rs create mode 100644 src/test/ui/macro-only/extern-impl-block.stderr create mode 100644 src/test/ui/macro-only/unsafe-foreign-mod.rs create mode 100644 src/test/ui/macro-only/unsafe-foreign-mod.stderr create mode 100644 src/test/ui/macro-only/unsafe-mod.rs create mode 100644 src/test/ui/macro-only/unsafe-mod.stderr create mode 100644 src/test/ui/proc-macro/extern-impl-block.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 0efde1e7b2124..35bb20496b4c8 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3005,6 +3005,9 @@ pub enum ForeignItemKind { TyAlias(Box), /// A macro expanding to foreign items. MacCall(P), + /// An impl declaration - parseable for proc_macro purposes, but currently has no meaning in + /// real Rust code. + Impl(Box), } impl From for ItemKind { @@ -3014,6 +3017,7 @@ impl From for ItemKind { ForeignItemKind::Fn(fn_kind) => ItemKind::Fn(fn_kind), ForeignItemKind::TyAlias(ty_alias_kind) => ItemKind::TyAlias(ty_alias_kind), ForeignItemKind::MacCall(a) => ItemKind::MacCall(a), + ForeignItemKind::Impl(i) => ItemKind::Impl(i), } } } @@ -3027,6 +3031,7 @@ impl TryFrom for ForeignItemKind { ItemKind::Fn(fn_kind) => ForeignItemKind::Fn(fn_kind), ItemKind::TyAlias(ty_alias_kind) => ForeignItemKind::TyAlias(ty_alias_kind), ItemKind::MacCall(a) => ForeignItemKind::MacCall(a), + ItemKind::Impl(i) => ForeignItemKind::Impl(i), _ => return Err(item_kind), }) } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index ad68d6e755e02..075fb11a5408b 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1198,6 +1198,25 @@ pub fn noop_flat_map_foreign_item( visit_opt(ty, |ty| visitor.visit_ty(ty)); } ForeignItemKind::MacCall(mac) => visitor.visit_mac_call(mac), + ForeignItemKind::Impl(box Impl { + defaultness, + unsafety, + generics, + constness, + polarity, + of_trait, + self_ty, + items, + }) => { + visit_defaultness(defaultness, visitor); + visit_unsafety(unsafety, visitor); + visitor.visit_generics(generics); + visit_constness(constness, visitor); + visit_polarity(polarity, visitor); + visit_opt(of_trait, |trait_ref| visitor.visit_trait_ref(trait_ref)); + visitor.visit_ty(self_ty); + items.flat_map_in_place(|item| visitor.flat_map_impl_item(item)); + } } visitor.visit_span(span); visit_lazy_tts(tokens, visitor); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index a71e055a4b3e5..524cc6355ccb5 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -575,6 +575,21 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI ForeignItemKind::MacCall(mac) => { visitor.visit_mac_call(mac); } + ForeignItemKind::Impl(box Impl { + defaultness: _, + unsafety: _, + ref generics, + constness: _, + polarity: _, + ref of_trait, + ref self_ty, + ref items, + }) => { + visitor.visit_generics(generics); + walk_list!(visitor, visit_trait_ref, of_trait); + visitor.visit_ty(self_ty); + walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl); + } } } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index d9b18d68e537f..11022f7703298 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -142,8 +142,11 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { // Evaluate with the lifetimes in `params` in-scope. // This is used to track which lifetimes have already been defined, // and which need to be replicated when lowering an async fn. - match parent_hir.node().expect_item().kind { - hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }) => { + match parent_hir.node() { + hir::OwnerNode::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { ref of_trait, .. }), + .. + }) => { lctx.is_in_trait_impl = of_trait.is_some(); } _ => {} @@ -685,6 +688,9 @@ impl<'hir> LoweringContext<'_, 'hir> { } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), + // This is not a type, but we will have emitted an error earlier and want the + // compiler to finish its work cleanly. + ForeignItemKind::Impl(_) => hir::ForeignItemKind::Type, }, vis_span: self.lower_span(i.vis.span), span: self.lower_span(i.span), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index ecf74c7602027..c7e23ab7a8a89 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1285,6 +1285,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::MacCall(..) => {} + ForeignItemKind::Impl(..) => { + self.err_handler() + .struct_span_err(fi.span, "`impl` blocks are not allowed in `extern` blocks") + .emit(); + return; + } } visit::walk_foreign_item(self, fi) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 0017a28cf1b18..05c98d6f5097d 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -356,6 +356,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, extern_types, i.span, "extern types are experimental"); } ast::ForeignItemKind::MacCall(..) => {} + ast::ForeignItemKind::Impl(..) => {} } visit::walk_foreign_item(self, i) diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 54bac29a6cee0..b7ca6d164e943 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -58,6 +58,53 @@ impl<'a> State<'a> { self.word(";"); } } + ast::ForeignItemKind::Impl(box ast::Impl { + unsafety, + polarity, + defaultness, + constness, + ref generics, + ref of_trait, + ref self_ty, + ref items, + }) => { + self.head(""); + self.print_visibility(&item.vis); + self.print_defaultness(*defaultness); + self.print_unsafety(*unsafety); + self.word("impl"); + + if generics.params.is_empty() { + self.nbsp(); + } else { + self.print_generic_params(&generics.params); + self.space(); + } + + self.print_constness(*constness); + + if let ast::ImplPolarity::Negative(_) = polarity { + self.word("!"); + } + + if let Some(ref t) = *of_trait { + self.print_trait_ref(t); + self.space(); + self.word_space("for"); + } + + self.print_type(self_ty); + self.print_where_clause(&generics.where_clause); + + self.space(); + self.bopen(); + self.print_inner_attributes(&item.attrs); + for impl_item in items { + self.print_assoc_item(impl_item); + } + let empty = item.attrs.is_empty() && items.is_empty(); + self.bclose(item.span, empty); + } } self.ann.post(self, AnnNode::SubItem(id)) } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c1948052e3c51..c1f4c9967b3e1 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3186,6 +3186,8 @@ pub enum ForeignItemKind<'hir> { Static(&'hir Ty<'hir>, Mutability), /// A foreign type. Type, + /// A foreign impl (currently meaningless) + Impl(&'hir Impl<'hir>), } /// A variable captured by a closure. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 8f5f314ecae1d..1d2260ecb8de4 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -564,22 +564,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`. visitor.visit_enum_def(enum_definition, item.hir_id()) } - ItemKind::Impl(Impl { - unsafety: _, - defaultness: _, - polarity: _, - constness: _, - defaultness_span: _, - ref generics, - ref of_trait, - ref self_ty, - items, - }) => { + ItemKind::Impl(impl_) => { visitor.visit_id(item.hir_id()); - visitor.visit_generics(generics); - walk_list!(visitor, visit_trait_ref, of_trait); - visitor.visit_ty(self_ty); - walk_list!(visitor, visit_impl_item_ref, *items); + walk_impl(visitor, impl_); } ItemKind::Struct(ref struct_definition, ref generics) | 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 } ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ), ForeignItemKind::Type => (), + ForeignItemKind::Impl(ref impl_) => walk_impl(visitor, impl_), } } @@ -978,6 +966,13 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt } } +pub fn walk_impl<'v, V: Visitor<'v>>(visitor: &mut V, impl_: &'v Impl<'v>) { + visitor.visit_generics(impl_.generics); + walk_list!(visitor, visit_trait_ref, &impl_.of_trait); + visitor.visit_ty(impl_.self_ty); + walk_list!(visitor, visit_impl_item_ref, impl_.items); +} + pub fn walk_foreign_item_ref<'v, V: Visitor<'v>>( visitor: &mut V, foreign_item_ref: &'v ForeignItemRef, diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 5917d5e346e37..1612a4fc42dc7 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -139,6 +139,7 @@ impl Target { hir::ForeignItemKind::Fn(..) => Target::ForeignFn, hir::ForeignItemKind::Static(..) => Target::ForeignStatic, hir::ForeignItemKind::Type => Target::ForeignTy, + hir::ForeignItemKind::Impl(..) => Target::Impl, } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 7965ec1b43f41..048bb84542ed8 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -260,6 +260,7 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) { } hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true), hir::ForeignItemKind::Type => (), + hir::ForeignItemKind::Impl(..) => (), } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e7deae2b557cd..f435021d26962 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -2217,7 +2217,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP Node::ForeignItem(item) => match item.kind { ForeignItemKind::Static(..) => NO_GENERICS, - ForeignItemKind::Fn(_, _, ref generics) => *generics, + ForeignItemKind::Fn(_, _, ref generics) + | ForeignItemKind::Impl(hir::Impl { ref generics, .. }) => *generics, ForeignItemKind::Type => NO_GENERICS, }, diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 24fb0b1fd26b5..b1b8c13426e0c 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -364,6 +364,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } ForeignItemKind::Static(t, _) => icx.to_ty(t), ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()), + ForeignItemKind::Impl(..) => span_bug!(foreign_item.span, "compute_type_of_foreign_item: unexpected item type: {:?}", foreign_item.kind), }, Node::Ctor(&ref def) | Node::Variant(Variant { data: ref def, .. }) => match *def { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 35a58296e370e..a7cdbdad3fae6 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -375,7 +375,8 @@ impl<'a> State<'a> { pub fn print_foreign_item(&mut self, item: &hir::ForeignItem<'_>) { self.hardbreak_if_not_bol(); self.maybe_print_comment(item.span.lo()); - self.print_outer_attributes(self.attrs(item.hir_id())); + let attrs = self.attrs(item.hir_id()); + self.print_outer_attributes(attrs); match item.kind { hir::ForeignItemKind::Fn(decl, arg_names, generics) => { self.head(""); @@ -415,6 +416,7 @@ impl<'a> State<'a> { self.end(); // end the head-ibox self.end() // end the outer cbox } + hir::ForeignItemKind::Impl(impl_) => self.print_impl(impl_, attrs, item.span), } } @@ -477,6 +479,48 @@ impl<'a> State<'a> { self.end(); // end the outer ibox } + fn print_impl( + &mut self, + impl_: &hir::Impl<'_>, + attrs: &[ast::Attribute], + span: rustc_span::Span, + ) { + self.head(""); + self.print_defaultness(impl_.defaultness); + self.print_unsafety(impl_.unsafety); + self.word_nbsp("impl"); + + if !impl_.generics.params.is_empty() { + self.print_generic_params(impl_.generics.params); + self.space(); + } + + if impl_.constness == hir::Constness::Const { + self.word_nbsp("const"); + } + + if let hir::ImplPolarity::Negative(_) = impl_.polarity { + self.word("!"); + } + + if let Some(ref t) = impl_.of_trait { + self.print_trait_ref(t); + self.space(); + self.word_space("for"); + } + + self.print_type(impl_.self_ty); + self.print_where_clause(impl_.generics); + + self.space(); + self.bopen(); + self.print_inner_attributes(attrs); + for impl_item in impl_.items { + self.ann.nested(self, Nested::ImplItem(impl_item.id)); + } + self.bclose(span); + } + /// Pretty-print an item pub fn print_item(&mut self, item: &hir::Item<'_>) { self.hardbreak_if_not_bol(); @@ -619,52 +663,7 @@ impl<'a> State<'a> { self.head("union"); self.print_struct(struct_def, generics, item.ident.name, item.span, true); } - hir::ItemKind::Impl(&hir::Impl { - unsafety, - polarity, - defaultness, - constness, - defaultness_span: _, - generics, - ref of_trait, - self_ty, - items, - }) => { - self.head(""); - self.print_defaultness(defaultness); - self.print_unsafety(unsafety); - self.word_nbsp("impl"); - - if !generics.params.is_empty() { - self.print_generic_params(generics.params); - self.space(); - } - - if constness == hir::Constness::Const { - self.word_nbsp("const"); - } - - if let hir::ImplPolarity::Negative(_) = polarity { - self.word("!"); - } - - if let Some(t) = of_trait { - self.print_trait_ref(t); - self.space(); - self.word_space("for"); - } - - self.print_type(self_ty); - self.print_where_clause(generics); - - self.space(); - self.bopen(); - self.print_inner_attributes(attrs); - for impl_item in items { - self.ann.nested(self, Nested::ImplItem(impl_item.id)); - } - self.bclose(item.span); - } + hir::ItemKind::Impl(impl_) => self.print_impl(impl_, attrs, item.span), hir::ItemKind::Trait(is_auto, unsafety, generics, bounds, trait_items) => { self.head(""); self.print_is_auto(is_auto); diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 4fb6d65a6e98f..e90f9c2387554 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1302,7 +1302,7 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations { hir::ForeignItemKind::Static(ref ty, _) => { vis.check_foreign_static(it.hir_id(), ty.span); } - hir::ForeignItemKind::Type => (), + hir::ForeignItemKind::Type | hir::ForeignItemKind::Impl(..) => (), } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7cf00ca41fefb..344cfb3596fe4 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1966,7 +1966,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.tables.constness.set(def_id.index, constness); record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } - hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => {} + hir::ForeignItemKind::Static(..) + | hir::ForeignItemKind::Type + | hir::ForeignItemKind::Impl(..) => {} } if let hir::ForeignItemKind::Fn(..) = nitem.kind { if tcx.is_intrinsic(def_id) { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index b5f7b26ea7ab6..e3dbed6fbaae9 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -235,6 +235,7 @@ impl<'hir> Map<'hir> { ForeignItemKind::Fn(..) => DefKind::Fn, ForeignItemKind::Static(_, mt) => DefKind::Static(mt), ForeignItemKind::Type => DefKind::ForeignTy, + ForeignItemKind::Impl(..) => DefKind::Impl, }, Node::TraitItem(item) => match item.kind { TraitItemKind::Const(..) => DefKind::AssocConst, diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 0be2fc0534467..44e8f47d6ff0d 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -254,7 +254,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem<'v>) { record_variants!( (self, i, i.kind, Id::Node(i.hir_id()), hir, ForeignItem, ForeignItemKind), - [Fn, Static, Type] + [Fn, Static, Type, Impl] ); hir_visit::walk_foreign_item(self, i) } @@ -476,7 +476,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_foreign_item(&mut self, i: &'v ast::ForeignItem) { record_variants!( (self, i, i.kind, Id::None, ast, ForeignItem, ForeignItemKind), - [Static, Fn, TyAlias, MacCall] + [Static, Fn, TyAlias, MacCall, Impl] ); ast_visit::walk_foreign_item(self, i) } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 81b67b758f7e1..febeccc839b1e 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -928,6 +928,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ForeignItemKind::Static(_, mt, _) => (DefKind::Static(mt), ValueNS), ForeignItemKind::TyAlias(..) => (DefKind::ForeignTy, TypeNS), ForeignItemKind::MacCall(_) => unreachable!(), + ForeignItemKind::Impl(_) => (DefKind::Impl, TypeNS), }; let parent = self.parent_scope.module; let expansion = self.parent_scope.expansion; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 558db003867d2..4e5d334eaa014 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -783,6 +783,23 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { ForeignItemKind::MacCall(..) => { panic!("unexpanded macro in resolve!") } + ForeignItemKind::Impl(box Impl { + ref generics, + ref of_trait, + ref self_ty, + items: ref impl_items, + .. + }) => { + self.diagnostic_metadata.current_impl_items = Some(impl_items); + self.resolve_implementation( + generics, + of_trait, + &self_ty, + foreign_item.id, + impl_items, + ); + self.diagnostic_metadata.current_impl_items = None; + } } } fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) { diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 9fb1af20ac976..b979504058953 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -634,15 +634,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { match item.kind { - hir::ForeignItemKind::Fn(_, _, ref generics) => { + hir::ForeignItemKind::Fn(_, _, ref generics) + | hir::ForeignItemKind::Impl(hir::Impl { ref generics, .. }) => { self.visit_early_late(item.hir_id(), generics, |this| { intravisit::walk_foreign_item(this, item); }) } - hir::ForeignItemKind::Static(..) => { - intravisit::walk_foreign_item(self, item); - } - hir::ForeignItemKind::Type => { + hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => { intravisit::walk_foreign_item(self, item); } } diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index adbc119387dba..dc6f1c6361391 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -1463,6 +1463,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { self.dumper.dump_def(&access, var_data); } } + hir::ForeignItemKind::Impl(..) => {} } } } diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index ad7aca3cb9494..543cc252c3820 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -201,6 +201,8 @@ impl<'tcx> SaveContext<'tcx> { } // FIXME(plietar): needs a new DefKind in rls-data hir::ForeignItemKind::Type => None, + // foreign impl blocks have no semantics + hir::ForeignItemKind::Impl(..) => None, } } diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index bae1828cd182d..93dac064f492b 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -789,6 +789,7 @@ impl<'hir> Sig for hir::ForeignItem<'hir> { Ok(Signature { text, defs, refs: vec![] }) } + hir::ForeignItemKind::Impl(..) => Err("foreign impl has no semantics"), } } } diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs index 3e2553c425edd..06dd509fbd0b6 100644 --- a/compiler/rustc_ty_utils/src/assoc.rs +++ b/compiler/rustc_ty_utils/src/assoc.rs @@ -14,16 +14,25 @@ pub fn provide(providers: &mut ty::query::Providers) { } fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { - let item = tcx.hir().expect_item(def_id.expect_local()); - match item.kind { - hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter( - trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()), - ), - hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( - impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.def_id.to_def_id()), - ), - hir::ItemKind::TraitAlias(..) => &[], - _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), + let node = tcx.hir().get_by_def_id(def_id.expect_local()); + match node { + hir::Node::Item(item) => match item.kind { + hir::ItemKind::Trait(.., ref trait_item_refs) => tcx.arena.alloc_from_iter( + trait_item_refs.iter().map(|trait_item_ref| trait_item_ref.id.def_id.to_def_id()), + ), + hir::ItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( + impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.def_id.to_def_id()), + ), + hir::ItemKind::TraitAlias(..) => &[], + _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"), + }, + hir::Node::ForeignItem(foreign_item) => match foreign_item.kind { + hir::ForeignItemKind::Impl(ref impl_) => tcx.arena.alloc_from_iter( + impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.def_id.to_def_id()), + ), + _ => span_bug!(foreign_item.span, "associated_item_def_ids: not impl or trait"), + }, + _ => bug!("associated_item_ids: not item or foreign item"), } } @@ -42,9 +51,12 @@ fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap, def_id: DefId) -> ty::AssocItem { let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let parent_def_id = tcx.hir().get_parent_item(id); - let parent_item = tcx.hir().expect_item(parent_def_id.def_id); - match parent_item.kind { - hir::ItemKind::Impl(ref impl_) => { + match tcx.hir().get_by_def_id(parent_def_id.def_id) { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(ref impl_), .. }) + | hir::Node::ForeignItem(hir::ForeignItem { + kind: hir::ForeignItemKind::Impl(ref impl_), + .. + }) => { if let Some(impl_item_ref) = impl_.items.iter().find(|i| i.id.def_id.to_def_id() == def_id) { @@ -52,9 +64,12 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { debug_assert_eq!(assoc_item.def_id, def_id); return assoc_item; } + bug!("impl item def_id not found in expected parent impl") } - hir::ItemKind::Trait(.., ref trait_item_refs) => { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Trait(.., ref trait_item_refs), .. + }) => { if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.def_id.to_def_id() == def_id) { @@ -62,16 +77,20 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { debug_assert_eq!(assoc_item.def_id, def_id); return assoc_item; } + bug!("trait item def_id not found in expected parent trait") } - - _ => {} + hir::Node::Item(parent_item) => span_bug!( + parent_item.span, + "unexpected parent of trait or impl item or item not found: {:?}", + parent_item.kind + ), + hir::Node::ForeignItem(parent_item) => span_bug!( + parent_item.span, + "unexpected parent of foreign impl item or item not found: {:?}", + parent_item.kind + ), + _ => bug!("Parent of associated item should be an item or foreign item"), } - - span_bug!( - parent_item.span, - "unexpected parent of trait or impl item or item not found: {:?}", - parent_item.kind - ) } fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 704292c10486b..1c50f73248617 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2218,6 +2218,8 @@ fn clean_maybe_renamed_foreign_item<'tcx>( ForeignStaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: None }) } hir::ForeignItemKind::Type => ForeignTypeItem, + // This should be unreachable, as this AST will be rejected earlier + hir::ForeignItemKind::Impl(..) => bug!("foreign impl should only exist in macros"), }; Item::from_hir_id_and_parts( diff --git a/src/test/ui/macro-only/extern-impl-block.rs b/src/test/ui/macro-only/extern-impl-block.rs new file mode 100644 index 0000000000000..638aedf279e9e --- /dev/null +++ b/src/test/ui/macro-only/extern-impl-block.rs @@ -0,0 +1,11 @@ +// check-fail + +struct T; + +extern { + impl T { //~ERROR `impl` blocks are not allowed in `extern` blocks + fn f(); + } +} + +fn main() {} diff --git a/src/test/ui/macro-only/extern-impl-block.stderr b/src/test/ui/macro-only/extern-impl-block.stderr new file mode 100644 index 0000000000000..fa1b46476b420 --- /dev/null +++ b/src/test/ui/macro-only/extern-impl-block.stderr @@ -0,0 +1,10 @@ +error: `impl` blocks are not allowed in `extern` blocks + --> $DIR/extern-impl-block.rs:6:5 + | +LL | / impl T { +LL | | fn f(); +LL | | } + | |_____^ + +error: aborting due to previous error + diff --git a/src/test/ui/macro-only/unsafe-foreign-mod.rs b/src/test/ui/macro-only/unsafe-foreign-mod.rs new file mode 100644 index 0000000000000..cc338f4030c80 --- /dev/null +++ b/src/test/ui/macro-only/unsafe-foreign-mod.rs @@ -0,0 +1,7 @@ +// check-fail + +unsafe extern "C++" { //~ERROR extern block cannot be declared unsafe + //~|ERROR invalid ABI +} + +fn main() {} diff --git a/src/test/ui/macro-only/unsafe-foreign-mod.stderr b/src/test/ui/macro-only/unsafe-foreign-mod.stderr new file mode 100644 index 0000000000000..a37d65b75f094 --- /dev/null +++ b/src/test/ui/macro-only/unsafe-foreign-mod.stderr @@ -0,0 +1,17 @@ +error: extern block cannot be declared unsafe + --> $DIR/unsafe-foreign-mod.rs:3:1 + | +LL | unsafe extern "C++" { + | ^^^^^^ + +error[E0703]: invalid ABI: found `C++` + --> $DIR/unsafe-foreign-mod.rs:3:15 + | +LL | unsafe extern "C++" { + | ^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions. + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0703`. diff --git a/src/test/ui/macro-only/unsafe-mod.rs b/src/test/ui/macro-only/unsafe-mod.rs new file mode 100644 index 0000000000000..e06d18b8600f0 --- /dev/null +++ b/src/test/ui/macro-only/unsafe-mod.rs @@ -0,0 +1,8 @@ +// check-fail + +unsafe mod m { //~ERROR module cannot be declared unsafe + pub unsafe mod inner; //~ERROR module cannot be declared unsafe + //~|ERROR file not found for module +} + +fn main() {} diff --git a/src/test/ui/macro-only/unsafe-mod.stderr b/src/test/ui/macro-only/unsafe-mod.stderr new file mode 100644 index 0000000000000..539fd31f061be --- /dev/null +++ b/src/test/ui/macro-only/unsafe-mod.stderr @@ -0,0 +1,23 @@ +error[E0583]: file not found for module `inner` + --> $DIR/unsafe-mod.rs:4:5 + | +LL | pub unsafe mod inner; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: to create the module `inner`, create file "$DIR/m/inner.rs" or "$DIR/m/inner/mod.rs" + +error: module cannot be declared unsafe + --> $DIR/unsafe-mod.rs:3:1 + | +LL | unsafe mod m { + | ^^^^^^ + +error: module cannot be declared unsafe + --> $DIR/unsafe-mod.rs:4:9 + | +LL | pub unsafe mod inner; + | ^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0583`. diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs index 98a95cfa35a9e..f506bb80f9c1a 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.rs +++ b/src/test/ui/parser/default-on-wrong-item-kind.rs @@ -54,7 +54,6 @@ extern "C" { default trait foo = Ord; //~ ERROR a trait alias cannot be `default` //~^ ERROR trait alias is not supported in `extern` blocks default impl foo {} - //~^ ERROR implementation is not supported in `extern` blocks default!(); default::foo::bar!(); default default!(); //~ ERROR an item macro invocation cannot be `default` diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr index af513f7617b09..9ad8a5ba35867 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.stderr +++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr @@ -272,16 +272,8 @@ LL | default trait foo = Ord; | = help: consider moving the trait alias out to a nearby module scope -error: implementation is not supported in `extern` blocks - --> $DIR/default-on-wrong-item-kind.rs:56:5 - | -LL | default impl foo {} - | ^^^^^^^^^^^^^^^^ - | - = help: consider moving the implementation out to a nearby module scope - error: an item macro invocation cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:60:5 + --> $DIR/default-on-wrong-item-kind.rs:59:5 | LL | default default!(); | ^^^^^^^ `default` because of this @@ -289,7 +281,7 @@ LL | default default!(); = note: only associated `fn`, `const`, and `type` items can be `default` error: an item macro invocation cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:61:5 + --> $DIR/default-on-wrong-item-kind.rs:60:5 | LL | default default::foo::bar!(); | ^^^^^^^ `default` because of this @@ -297,7 +289,7 @@ LL | default default::foo::bar!(); = note: only associated `fn`, `const`, and `type` items can be `default` error: a macro definition cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:62:5 + --> $DIR/default-on-wrong-item-kind.rs:61:5 | LL | default macro foo {} | ^^^^^^^ `default` because of this @@ -305,7 +297,7 @@ LL | default macro foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: macro definition is not supported in `extern` blocks - --> $DIR/default-on-wrong-item-kind.rs:62:5 + --> $DIR/default-on-wrong-item-kind.rs:61:5 | LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ @@ -313,7 +305,7 @@ LL | default macro foo {} = help: consider moving the macro definition out to a nearby module scope error: a macro definition cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:64:5 + --> $DIR/default-on-wrong-item-kind.rs:63:5 | LL | default macro_rules! foo {} | ^^^^^^^ `default` because of this @@ -321,7 +313,7 @@ LL | default macro_rules! foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: macro definition is not supported in `extern` blocks - --> $DIR/default-on-wrong-item-kind.rs:64:5 + --> $DIR/default-on-wrong-item-kind.rs:63:5 | LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -329,7 +321,7 @@ LL | default macro_rules! foo {} = help: consider moving the macro definition out to a nearby module scope error: an extern crate cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:70:5 + --> $DIR/default-on-wrong-item-kind.rs:69:5 | LL | default extern crate foo; | ^^^^^^^ `default` because of this @@ -337,7 +329,7 @@ LL | default extern crate foo; = note: only associated `fn`, `const`, and `type` items can be `default` error: extern crate is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:70:5 + --> $DIR/default-on-wrong-item-kind.rs:69:5 | LL | default extern crate foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -345,7 +337,7 @@ LL | default extern crate foo; = help: consider moving the extern crate out to a nearby module scope error: a `use` import cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:72:5 + --> $DIR/default-on-wrong-item-kind.rs:71:5 | LL | default use foo; | ^^^^^^^ `default` because of this @@ -353,7 +345,7 @@ LL | default use foo; = note: only associated `fn`, `const`, and `type` items can be `default` error: `use` import is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:72:5 + --> $DIR/default-on-wrong-item-kind.rs:71:5 | LL | default use foo; | ^^^^^^^^^^^^^^^^ @@ -361,7 +353,7 @@ LL | default use foo; = help: consider moving the `use` import out to a nearby module scope error: a static item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:74:5 + --> $DIR/default-on-wrong-item-kind.rs:73:5 | LL | default static foo: u8; | ^^^^^^^ `default` because of this @@ -369,13 +361,13 @@ LL | default static foo: u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: associated `static` items are not allowed - --> $DIR/default-on-wrong-item-kind.rs:74:5 + --> $DIR/default-on-wrong-item-kind.rs:73:5 | LL | default static foo: u8; | ^^^^^^^^^^^^^^^^^^^^^^^ error: a module cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:78:5 + --> $DIR/default-on-wrong-item-kind.rs:77:5 | LL | default mod foo {} | ^^^^^^^ `default` because of this @@ -383,7 +375,7 @@ LL | default mod foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: module is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:78:5 + --> $DIR/default-on-wrong-item-kind.rs:77:5 | LL | default mod foo {} | ^^^^^^^^^^^^^^^ @@ -391,7 +383,7 @@ LL | default mod foo {} = help: consider moving the module out to a nearby module scope error: an extern block cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:80:5 + --> $DIR/default-on-wrong-item-kind.rs:79:5 | LL | default extern "C" {} | ^^^^^^^ `default` because of this @@ -399,7 +391,7 @@ LL | default extern "C" {} = note: only associated `fn`, `const`, and `type` items can be `default` error: extern block is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:80:5 + --> $DIR/default-on-wrong-item-kind.rs:79:5 | LL | default extern "C" {} | ^^^^^^^^^^^^^^^^^^ @@ -407,7 +399,7 @@ LL | default extern "C" {} = help: consider moving the extern block out to a nearby module scope error: an enum cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:83:5 + --> $DIR/default-on-wrong-item-kind.rs:82:5 | LL | default enum foo {} | ^^^^^^^ `default` because of this @@ -415,7 +407,7 @@ LL | default enum foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: enum is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:83:5 + --> $DIR/default-on-wrong-item-kind.rs:82:5 | LL | default enum foo {} | ^^^^^^^^^^^^^^^^ @@ -423,7 +415,7 @@ LL | default enum foo {} = help: consider moving the enum out to a nearby module scope error: a struct cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:85:5 + --> $DIR/default-on-wrong-item-kind.rs:84:5 | LL | default struct foo {} | ^^^^^^^ `default` because of this @@ -431,7 +423,7 @@ LL | default struct foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: struct is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:85:5 + --> $DIR/default-on-wrong-item-kind.rs:84:5 | LL | default struct foo {} | ^^^^^^^^^^^^^^^^^^ @@ -439,7 +431,7 @@ LL | default struct foo {} = help: consider moving the struct out to a nearby module scope error: a union cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:87:5 + --> $DIR/default-on-wrong-item-kind.rs:86:5 | LL | default union foo {} | ^^^^^^^ `default` because of this @@ -447,7 +439,7 @@ LL | default union foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: union is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:87:5 + --> $DIR/default-on-wrong-item-kind.rs:86:5 | LL | default union foo {} | ^^^^^^^^^^^^^^^^^ @@ -455,7 +447,7 @@ LL | default union foo {} = help: consider moving the union out to a nearby module scope error: a trait cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:89:5 + --> $DIR/default-on-wrong-item-kind.rs:88:5 | LL | default trait foo {} | ^^^^^^^ `default` because of this @@ -463,7 +455,7 @@ LL | default trait foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: trait is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:89:5 + --> $DIR/default-on-wrong-item-kind.rs:88:5 | LL | default trait foo {} | ^^^^^^^^^^^^^^^^^ @@ -471,7 +463,7 @@ LL | default trait foo {} = help: consider moving the trait out to a nearby module scope error: a trait alias cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:91:5 + --> $DIR/default-on-wrong-item-kind.rs:90:5 | LL | default trait foo = Ord; | ^^^^^^^ `default` because of this @@ -479,7 +471,7 @@ LL | default trait foo = Ord; = note: only associated `fn`, `const`, and `type` items can be `default` error: trait alias is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:91:5 + --> $DIR/default-on-wrong-item-kind.rs:90:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -487,7 +479,7 @@ LL | default trait foo = Ord; = help: consider moving the trait alias out to a nearby module scope error: implementation is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:93:5 + --> $DIR/default-on-wrong-item-kind.rs:92:5 | LL | default impl foo {} | ^^^^^^^^^^^^^^^^ @@ -495,7 +487,7 @@ LL | default impl foo {} = help: consider moving the implementation out to a nearby module scope error: an item macro invocation cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:97:5 + --> $DIR/default-on-wrong-item-kind.rs:96:5 | LL | default default!(); | ^^^^^^^ `default` because of this @@ -503,7 +495,7 @@ LL | default default!(); = note: only associated `fn`, `const`, and `type` items can be `default` error: an item macro invocation cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:98:5 + --> $DIR/default-on-wrong-item-kind.rs:97:5 | LL | default default::foo::bar!(); | ^^^^^^^ `default` because of this @@ -511,7 +503,7 @@ LL | default default::foo::bar!(); = note: only associated `fn`, `const`, and `type` items can be `default` error: a macro definition cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:99:5 + --> $DIR/default-on-wrong-item-kind.rs:98:5 | LL | default macro foo {} | ^^^^^^^ `default` because of this @@ -519,7 +511,7 @@ LL | default macro foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: macro definition is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:99:5 + --> $DIR/default-on-wrong-item-kind.rs:98:5 | LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ @@ -527,7 +519,7 @@ LL | default macro foo {} = help: consider moving the macro definition out to a nearby module scope error: a macro definition cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:101:5 + --> $DIR/default-on-wrong-item-kind.rs:100:5 | LL | default macro_rules! foo {} | ^^^^^^^ `default` because of this @@ -535,7 +527,7 @@ LL | default macro_rules! foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: macro definition is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:101:5 + --> $DIR/default-on-wrong-item-kind.rs:100:5 | LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -543,7 +535,7 @@ LL | default macro_rules! foo {} = help: consider moving the macro definition out to a nearby module scope error: an extern crate cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:107:5 + --> $DIR/default-on-wrong-item-kind.rs:106:5 | LL | default extern crate foo; | ^^^^^^^ `default` because of this @@ -551,7 +543,7 @@ LL | default extern crate foo; = note: only associated `fn`, `const`, and `type` items can be `default` error: extern crate is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:107:5 + --> $DIR/default-on-wrong-item-kind.rs:106:5 | LL | default extern crate foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -559,7 +551,7 @@ LL | default extern crate foo; = help: consider moving the extern crate out to a nearby module scope error: a `use` import cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:109:5 + --> $DIR/default-on-wrong-item-kind.rs:108:5 | LL | default use foo; | ^^^^^^^ `default` because of this @@ -567,7 +559,7 @@ LL | default use foo; = note: only associated `fn`, `const`, and `type` items can be `default` error: `use` import is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:109:5 + --> $DIR/default-on-wrong-item-kind.rs:108:5 | LL | default use foo; | ^^^^^^^^^^^^^^^^ @@ -575,7 +567,7 @@ LL | default use foo; = help: consider moving the `use` import out to a nearby module scope error: a static item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:111:5 + --> $DIR/default-on-wrong-item-kind.rs:110:5 | LL | default static foo: u8; | ^^^^^^^ `default` because of this @@ -583,13 +575,13 @@ LL | default static foo: u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: associated `static` items are not allowed - --> $DIR/default-on-wrong-item-kind.rs:111:5 + --> $DIR/default-on-wrong-item-kind.rs:110:5 | LL | default static foo: u8; | ^^^^^^^^^^^^^^^^^^^^^^^ error: a module cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:115:5 + --> $DIR/default-on-wrong-item-kind.rs:114:5 | LL | default mod foo {} | ^^^^^^^ `default` because of this @@ -597,7 +589,7 @@ LL | default mod foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: module is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:115:5 + --> $DIR/default-on-wrong-item-kind.rs:114:5 | LL | default mod foo {} | ^^^^^^^^^^^^^^^ @@ -605,7 +597,7 @@ LL | default mod foo {} = help: consider moving the module out to a nearby module scope error: an extern block cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:117:5 + --> $DIR/default-on-wrong-item-kind.rs:116:5 | LL | default extern "C" {} | ^^^^^^^ `default` because of this @@ -613,7 +605,7 @@ LL | default extern "C" {} = note: only associated `fn`, `const`, and `type` items can be `default` error: extern block is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:117:5 + --> $DIR/default-on-wrong-item-kind.rs:116:5 | LL | default extern "C" {} | ^^^^^^^^^^^^^^^^^^ @@ -621,7 +613,7 @@ LL | default extern "C" {} = help: consider moving the extern block out to a nearby module scope error: an enum cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:120:5 + --> $DIR/default-on-wrong-item-kind.rs:119:5 | LL | default enum foo {} | ^^^^^^^ `default` because of this @@ -629,7 +621,7 @@ LL | default enum foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: enum is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:120:5 + --> $DIR/default-on-wrong-item-kind.rs:119:5 | LL | default enum foo {} | ^^^^^^^^^^^^^^^^ @@ -637,7 +629,7 @@ LL | default enum foo {} = help: consider moving the enum out to a nearby module scope error: a struct cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:122:5 + --> $DIR/default-on-wrong-item-kind.rs:121:5 | LL | default struct foo {} | ^^^^^^^ `default` because of this @@ -645,7 +637,7 @@ LL | default struct foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: struct is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:122:5 + --> $DIR/default-on-wrong-item-kind.rs:121:5 | LL | default struct foo {} | ^^^^^^^^^^^^^^^^^^ @@ -653,7 +645,7 @@ LL | default struct foo {} = help: consider moving the struct out to a nearby module scope error: a union cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:124:5 + --> $DIR/default-on-wrong-item-kind.rs:123:5 | LL | default union foo {} | ^^^^^^^ `default` because of this @@ -661,7 +653,7 @@ LL | default union foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: union is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:124:5 + --> $DIR/default-on-wrong-item-kind.rs:123:5 | LL | default union foo {} | ^^^^^^^^^^^^^^^^^ @@ -669,7 +661,7 @@ LL | default union foo {} = help: consider moving the union out to a nearby module scope error: a trait cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:126:5 + --> $DIR/default-on-wrong-item-kind.rs:125:5 | LL | default trait foo {} | ^^^^^^^ `default` because of this @@ -677,7 +669,7 @@ LL | default trait foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: trait is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:126:5 + --> $DIR/default-on-wrong-item-kind.rs:125:5 | LL | default trait foo {} | ^^^^^^^^^^^^^^^^^ @@ -685,7 +677,7 @@ LL | default trait foo {} = help: consider moving the trait out to a nearby module scope error: a trait alias cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:128:5 + --> $DIR/default-on-wrong-item-kind.rs:127:5 | LL | default trait foo = Ord; | ^^^^^^^ `default` because of this @@ -693,7 +685,7 @@ LL | default trait foo = Ord; = note: only associated `fn`, `const`, and `type` items can be `default` error: trait alias is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:128:5 + --> $DIR/default-on-wrong-item-kind.rs:127:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -701,7 +693,7 @@ LL | default trait foo = Ord; = help: consider moving the trait alias out to a nearby module scope error: implementation is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:130:5 + --> $DIR/default-on-wrong-item-kind.rs:129:5 | LL | default impl foo {} | ^^^^^^^^^^^^^^^^ @@ -709,7 +701,7 @@ LL | default impl foo {} = help: consider moving the implementation out to a nearby module scope error: an item macro invocation cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:134:5 + --> $DIR/default-on-wrong-item-kind.rs:133:5 | LL | default default!(); | ^^^^^^^ `default` because of this @@ -717,7 +709,7 @@ LL | default default!(); = note: only associated `fn`, `const`, and `type` items can be `default` error: an item macro invocation cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:135:5 + --> $DIR/default-on-wrong-item-kind.rs:134:5 | LL | default default::foo::bar!(); | ^^^^^^^ `default` because of this @@ -725,7 +717,7 @@ LL | default default::foo::bar!(); = note: only associated `fn`, `const`, and `type` items can be `default` error: a macro definition cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:136:5 + --> $DIR/default-on-wrong-item-kind.rs:135:5 | LL | default macro foo {} | ^^^^^^^ `default` because of this @@ -733,7 +725,7 @@ LL | default macro foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: macro definition is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:136:5 + --> $DIR/default-on-wrong-item-kind.rs:135:5 | LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ @@ -741,7 +733,7 @@ LL | default macro foo {} = help: consider moving the macro definition out to a nearby module scope error: a macro definition cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:138:5 + --> $DIR/default-on-wrong-item-kind.rs:137:5 | LL | default macro_rules! foo {} | ^^^^^^^ `default` because of this @@ -749,12 +741,12 @@ LL | default macro_rules! foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: macro definition is not supported in `trait`s or `impl`s - --> $DIR/default-on-wrong-item-kind.rs:138:5 + --> $DIR/default-on-wrong-item-kind.rs:137:5 | LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | = help: consider moving the macro definition out to a nearby module scope -error: aborting due to 95 previous errors +error: aborting due to 94 previous errors diff --git a/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs b/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs index c72306c3d50b3..33b51dc204bad 100644 --- a/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs +++ b/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs @@ -63,6 +63,25 @@ pub fn expect_unsafe_extern_cpp_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream::new() } +// extern "C" { +// impl T { +// fn f(); +// } +// } +#[proc_macro_attribute] +pub fn expect_extern_impl_block(_attrs: TokenStream, input: TokenStream) -> TokenStream { + let tokens = &mut input.into_iter(); + expect(tokens, "extern"); + let extern_tokens = &mut expect_brace(tokens); + expect(extern_tokens, "impl"); + expect(extern_tokens, "T"); + let impl_tokens = &mut expect_brace(extern_tokens); + expect(impl_tokens, "fn"); + let f = expect(impl_tokens, "f"); + check_useful_span(f, "extern-impl-block.rs"); + TokenStream::new() +} + fn expect(tokens: &mut token_stream::IntoIter, expected: &str) -> TokenTree { match tokens.next() { Some(token) if token.to_string() == expected => token, diff --git a/src/test/ui/proc-macro/extern-impl-block.rs b/src/test/ui/proc-macro/extern-impl-block.rs new file mode 100644 index 0000000000000..1ccb6d904ab58 --- /dev/null +++ b/src/test/ui/proc-macro/extern-impl-block.rs @@ -0,0 +1,13 @@ +// run-pass +// aux-build:macro-only-syntax.rs + +extern crate macro_only_syntax; + +#[macro_only_syntax::expect_extern_impl_block] +extern { + impl T { + fn f(); + } +} + +fn main() {} diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 8f35068e35f04..101e0398b8033 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -658,6 +658,17 @@ pub(crate) fn format_impl( item: &ast::Item, iimpl: &ast::Impl, offset: Indent, +) -> Option { + rewrite_impl(context, &item.vis, item.span, &item.attrs, iimpl, offset) +} + +fn rewrite_impl( + context: &RewriteContext<'_>, + visibility: &ast::Visibility, + span: Span, + attrs: &[ast::Attribute], + iimpl: &ast::Impl, + offset: Indent, ) -> Option { let ast::Impl { generics, @@ -666,7 +677,7 @@ pub(crate) fn format_impl( .. } = iimpl; let mut result = String::with_capacity(128); - let ref_and_type = format_impl_ref_and_type(context, item, iimpl, offset)?; + let ref_and_type = format_impl_ref_and_type(context, visibility, iimpl, offset)?; let sep = offset.to_string_with_newline(context.config); result.push_str(&ref_and_type); @@ -677,7 +688,7 @@ pub(crate) fn format_impl( }; let mut option = WhereClauseOption::snuggled(&ref_and_type); - let snippet = context.snippet(item.span); + let snippet = context.snippet(span); let open_pos = snippet.find_uncommented("{")? + 1; if !contains_comment(&snippet[open_pos..]) && items.is_empty() @@ -689,7 +700,7 @@ pub(crate) fn format_impl( option.allow_single_line(); } - let missing_span = mk_sp(self_ty.span.hi(), item.span.hi()); + let missing_span = mk_sp(self_ty.span.hi(), span.hi()); let where_span_end = context.snippet_provider.opt_span_before(missing_span, "{"); let where_clause_str = rewrite_where_clause( context, @@ -722,7 +733,7 @@ pub(crate) fn format_impl( } } - if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, item)? { + if is_impl_single_line(context, items.as_slice(), &result, &where_clause_str, span)? { result.push_str(&where_clause_str); if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) { // if the where_clause contains extra comments AND @@ -757,7 +768,7 @@ pub(crate) fn format_impl( result.push('{'); // this is an impl body snippet(impl SampleImpl { /* here */ }) let lo = max(self_ty.span.hi(), generics.where_clause.span.hi()); - let snippet = context.snippet(mk_sp(lo, item.span.hi())); + let snippet = context.snippet(mk_sp(lo, span.hi())); let open_pos = snippet.find_uncommented("{")? + 1; if !items.is_empty() || contains_comment(&snippet[open_pos..]) { @@ -766,10 +777,10 @@ pub(crate) fn format_impl( visitor.block_indent = item_indent; visitor.last_pos = lo + BytePos(open_pos as u32); - visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner); + visitor.visit_attrs(&attrs, ast::AttrStyle::Inner); visitor.visit_impl_items(items); - visitor.format_missing(item.span.hi() - BytePos(1)); + visitor.format_missing(span.hi() - BytePos(1)); let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config); let outer_indent_str = offset.block_only().to_string_with_newline(context.config); @@ -791,9 +802,9 @@ fn is_impl_single_line( items: &[ptr::P], result: &str, where_clause_str: &str, - item: &ast::Item, + span: Span, ) -> Option { - let snippet = context.snippet(item.span); + let snippet = context.snippet(span); let open_pos = snippet.find_uncommented("{")? + 1; Some( @@ -807,7 +818,7 @@ fn is_impl_single_line( fn format_impl_ref_and_type( context: &RewriteContext<'_>, - item: &ast::Item, + visibility: &ast::Visibility, iimpl: &ast::Impl, offset: Indent, ) -> Option { @@ -823,7 +834,7 @@ fn format_impl_ref_and_type( } = *iimpl; let mut result = String::with_capacity(128); - result.push_str(&format_visibility(context, &item.vis)); + result.push_str(&format_visibility(context, visibility)); result.push_str(format_defaultness(defaultness)); result.push_str(format_unsafety(unsafety)); @@ -3233,6 +3244,14 @@ impl Rewrite for ast::ForeignItem { ast::ForeignItemKind::MacCall(ref mac) => { rewrite_macro(mac, None, context, shape, MacroPosition::Item) } + ast::ForeignItemKind::Impl(ref impl_) => rewrite_impl( + context, + &self.vis, + self.span, + &self.attrs, + impl_, + shape.indent, + ), }?; let missing_span = if self.attrs.is_empty() {