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() {