Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow parsing foreign impl blocks #102376

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3005,6 +3005,9 @@ pub enum ForeignItemKind {
TyAlias(Box<TyAlias>),
/// A macro expanding to foreign items.
MacCall(P<MacCall>),
/// An impl declaration - parseable for proc_macro purposes, but currently has no meaning in
/// real Rust code.
Impl(Box<Impl>),
}

impl From<ForeignItemKind> for ItemKind {
Expand All @@ -3014,6 +3017,7 @@ impl From<ForeignItemKind> 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),
}
}
}
Expand All @@ -3027,6 +3031,7 @@ impl TryFrom<ItemKind> 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),
})
}
Expand Down
19 changes: 19 additions & 0 deletions compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,25 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
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);
Expand Down
15 changes: 15 additions & 0 deletions compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}

Expand Down
10 changes: 8 additions & 2 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
_ => {}
Expand Down Expand Up @@ -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),
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
47 changes: 47 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust/state/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
25 changes: 10 additions & 15 deletions compiler/rustc_hir/src/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -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_),
}
}

Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) => (),
}
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/collect/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
93 changes: 46 additions & 47 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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("");
Expand Down Expand Up @@ -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),
}
}

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) => (),
}
}
}
Expand Down
Loading