Skip to content

Commit 9e5b35b

Browse files
auto-impl: parser support
This patch introduce AST elements for `auto impl` inside the `trait` and `impl` block. This patch does not handle the name resolution, yet. It will be handled in the next patch series. Signed-off-by: Xiangfei Ding <dingxiangfei2009@protonmail.ch>
1 parent 765fd2d commit 9e5b35b

71 files changed

Lines changed: 1217 additions & 191 deletions

File tree

Some content is hidden

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

compiler/rustc_ast/src/ast.rs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3645,6 +3645,8 @@ impl Item {
36453645
| ItemKind::DelegationMac(_)
36463646
| ItemKind::MacroDef(..) => None,
36473647
ItemKind::Static(_) => None,
3648+
ItemKind::AutoImpl(ai) => Some(&ai.generics),
3649+
ItemKind::ExternImpl(ei) => Some(&ei.generics),
36483650
ItemKind::Const(i) => Some(&i.generics),
36493651
ItemKind::Fn(i) => Some(&i.generics),
36503652
ItemKind::TyAlias(i) => Some(&i.generics),
@@ -3788,6 +3790,20 @@ pub struct Impl {
37883790
pub items: ThinVec<Box<AssocItem>>,
37893791
}
37903792

3793+
#[derive(Clone, Encodable, Decodable, Debug)]
3794+
pub struct AutoImpl {
3795+
pub generics: Generics,
3796+
pub constness: Const,
3797+
pub of_trait: Box<TraitImplHeader>,
3798+
pub items: ThinVec<Box<AssocItem>>,
3799+
}
3800+
3801+
#[derive(Clone, Encodable, Decodable, Debug)]
3802+
pub struct ExternImpl {
3803+
pub generics: Generics,
3804+
pub of_trait: Box<TraitImplHeader>,
3805+
}
3806+
37913807
#[derive(Clone, Encodable, Decodable, Debug)]
37923808
pub struct TraitImplHeader {
37933809
pub defaultness: Defaultness,
@@ -4001,6 +4017,10 @@ pub enum ItemKind {
40014017
///
40024018
/// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`.
40034019
Impl(Impl),
4020+
/// An `auto impl` implementation, such as a supertrait `auto impl`.
4021+
AutoImpl(Box<AutoImpl>),
4022+
/// An `extern impl` directive
4023+
ExternImpl(Box<ExternImpl>),
40044024
/// A macro invocation.
40054025
///
40064026
/// E.g., `foo!(..)`.
@@ -4039,6 +4059,8 @@ impl ItemKind {
40394059
| ItemKind::ForeignMod(_)
40404060
| ItemKind::GlobalAsm(_)
40414061
| ItemKind::Impl(_)
4062+
| ItemKind::AutoImpl(_)
4063+
| ItemKind::ExternImpl(_)
40424064
| ItemKind::MacCall(_)
40434065
| ItemKind::DelegationMac(_) => None,
40444066
}
@@ -4051,7 +4073,13 @@ impl ItemKind {
40514073
Use(..) | Static(..) | Const(..) | ConstBlock(..) | Fn(..) | Mod(..)
40524074
| GlobalAsm(..) | TyAlias(..) | Struct(..) | Union(..) | Trait(..) | TraitAlias(..)
40534075
| MacroDef(..) | Delegation(..) | DelegationMac(..) => "a",
4054-
ExternCrate(..) | ForeignMod(..) | MacCall(..) | Enum(..) | Impl { .. } => "an",
4076+
ExternCrate(..)
4077+
| ForeignMod(..)
4078+
| MacCall(..)
4079+
| Enum(..)
4080+
| Impl { .. }
4081+
| AutoImpl(..)
4082+
| ExternImpl(..) => "an",
40554083
}
40564084
}
40574085

@@ -4075,6 +4103,8 @@ impl ItemKind {
40754103
ItemKind::MacCall(..) => "item macro invocation",
40764104
ItemKind::MacroDef(..) => "macro definition",
40774105
ItemKind::Impl { .. } => "implementation",
4106+
ItemKind::AutoImpl { .. } => "`auto` implementation",
4107+
ItemKind::ExternImpl { .. } => "`extern` implementation",
40784108
ItemKind::Delegation(..) => "delegated function",
40794109
ItemKind::DelegationMac(..) => "delegation",
40804110
}
@@ -4090,6 +4120,8 @@ impl ItemKind {
40904120
| Self::Union(_, generics, _)
40914121
| Self::Trait(box Trait { generics, .. })
40924122
| Self::TraitAlias(box TraitAlias { generics, .. })
4123+
| Self::AutoImpl(box AutoImpl { generics, .. })
4124+
| Self::ExternImpl(box ExternImpl { generics, .. })
40934125
| Self::Impl(Impl { generics, .. }) => Some(generics),
40944126

40954127
Self::ExternCrate(..)
@@ -4133,6 +4165,10 @@ pub enum AssocItemKind {
41334165
Delegation(Box<Delegation>),
41344166
/// An associated list or glob delegation item.
41354167
DelegationMac(Box<DelegationMac>),
4168+
/// An `auto impl` item
4169+
AutoImpl(Box<AutoImpl>),
4170+
/// An `extern impl` item
4171+
ExternImpl(Box<ExternImpl>),
41364172
}
41374173

41384174
impl AssocItemKind {
@@ -4143,15 +4179,26 @@ impl AssocItemKind {
41434179
| AssocItemKind::Type(box TyAlias { ident, .. })
41444180
| AssocItemKind::Delegation(box Delegation { ident, .. }) => Some(ident),
41454181

4146-
AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(_) => None,
4182+
AssocItemKind::MacCall(_)
4183+
| AssocItemKind::DelegationMac(_)
4184+
| AssocItemKind::AutoImpl(_)
4185+
| AssocItemKind::ExternImpl(_) => None,
41474186
}
41484187
}
41494188

41504189
pub fn defaultness(&self) -> Defaultness {
41514190
match *self {
41524191
Self::Const(box ConstItem { defaultness, .. })
41534192
| Self::Fn(box Fn { defaultness, .. })
4154-
| Self::Type(box TyAlias { defaultness, .. }) => defaultness,
4193+
| Self::Type(box TyAlias { defaultness, .. })
4194+
| Self::AutoImpl(box AutoImpl {
4195+
of_trait: box TraitImplHeader { defaultness, .. },
4196+
..
4197+
})
4198+
| Self::ExternImpl(box ExternImpl {
4199+
of_trait: box TraitImplHeader { defaultness, .. },
4200+
..
4201+
}) => defaultness,
41554202
Self::MacCall(..) | Self::Delegation(..) | Self::DelegationMac(..) => {
41564203
Defaultness::Implicit
41574204
}
@@ -4168,6 +4215,8 @@ impl From<AssocItemKind> for ItemKind {
41684215
AssocItemKind::MacCall(a) => ItemKind::MacCall(a),
41694216
AssocItemKind::Delegation(delegation) => ItemKind::Delegation(delegation),
41704217
AssocItemKind::DelegationMac(delegation) => ItemKind::DelegationMac(delegation),
4218+
AssocItemKind::AutoImpl(ai) => ItemKind::AutoImpl(ai),
4219+
AssocItemKind::ExternImpl(ei) => ItemKind::ExternImpl(ei),
41714220
}
41724221
}
41734222
}
@@ -4183,6 +4232,8 @@ impl TryFrom<ItemKind> for AssocItemKind {
41834232
ItemKind::MacCall(a) => AssocItemKind::MacCall(a),
41844233
ItemKind::Delegation(d) => AssocItemKind::Delegation(d),
41854234
ItemKind::DelegationMac(d) => AssocItemKind::DelegationMac(d),
4235+
ItemKind::AutoImpl(ai) => AssocItemKind::AutoImpl(ai),
4236+
ItemKind::ExternImpl(ei) => AssocItemKind::ExternImpl(ei),
41864237
_ => return Err(item_kind),
41874238
})
41884239
}

compiler/rustc_ast/src/visit.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,8 @@ macro_rules! common_visitor_and_walkers {
558558
//fn visit_assoc_item(AssocItem, _ctxt: AssocCtxt);
559559
fn visit_assoc_item_constraint(AssocItemConstraint);
560560
fn visit_attribute(Attribute);
561+
fn visit_auto_impl(AutoImpl);
562+
fn visit_extern_impl(ExternImpl);
561563
fn visit_block(Block);
562564
//fn visit_nested_use_tree((UseTree, NodeId));
563565
fn visit_capture_by(CaptureBy);
@@ -847,6 +849,10 @@ macro_rules! common_visitor_and_walkers {
847849
visit_visitable!($($mut)? vis, ident, generics, variant_data),
848850
ItemKind::Impl(impl_) =>
849851
visit_visitable!($($mut)? vis, impl_),
852+
ItemKind::AutoImpl(auto_impl_) =>
853+
visit_visitable!($($mut)? vis, auto_impl_),
854+
ItemKind::ExternImpl(extern_impl_) =>
855+
visit_visitable!($($mut)? vis, extern_impl_),
850856
ItemKind::Trait(trait_) =>
851857
visit_visitable!($($mut)? vis, trait_),
852858
ItemKind::TraitAlias(box TraitAlias { constness, ident, generics, bounds}) => {
@@ -892,6 +898,10 @@ macro_rules! common_visitor_and_walkers {
892898
visit_visitable!($($mut)? vis, delegation),
893899
AssocItemKind::DelegationMac(dm) =>
894900
visit_visitable!($($mut)? vis, dm),
901+
AssocItemKind::AutoImpl(ai) =>
902+
visit_visitable!($($mut)? vis, ai),
903+
AssocItemKind::ExternImpl(ei) =>
904+
visit_visitable!($($mut)? vis, ei),
895905
}
896906
V::Result::output()
897907
}
@@ -956,6 +966,27 @@ macro_rules! common_visitor_and_walkers {
956966
V::Result::output()
957967
});
958968

969+
impl_walkable!(|&$($mut)? $($lt)? self: AutoImpl, vis: &mut V| {
970+
let AutoImpl { generics, of_trait, items, constness } = self;
971+
let TraitImplHeader { defaultness, safety, polarity, trait_ref } = &$($mut)? **of_trait;
972+
973+
try_visit!(vis.visit_generics(generics));
974+
visit_visitable!($($mut)? vis, defaultness, safety, constness, polarity, trait_ref);
975+
976+
visit_visitable_with!($($mut)? vis, items, AssocCtxt::Impl { of_trait: true });
977+
V::Result::output()
978+
});
979+
980+
impl_walkable!(|&$($mut)? $($lt)? self: ExternImpl, vis: &mut V| {
981+
let ExternImpl { generics, of_trait } = self;
982+
let TraitImplHeader { defaultness, safety, polarity, trait_ref } = &$($mut)? **of_trait;
983+
984+
try_visit!(vis.visit_generics(generics));
985+
visit_visitable!($($mut)? vis, defaultness, safety, polarity, trait_ref);
986+
987+
V::Result::output()
988+
});
989+
959990
// Special case to call `visit_method_receiver_expr`.
960991
impl_walkable!(|&$($mut)? $($lt)? self: MethodCall, vis: &mut V| {
961992
let MethodCall { seg, receiver, args, span } = self;

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_abi::ExternAbi;
22
use rustc_ast::visit::AssocCtxt;
33
use rustc_ast::*;
4-
use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
4+
use rustc_errors::{E0570, ErrorGuaranteed, FatalError, struct_span_code_err};
55
use rustc_hir::attrs::{AttributeKind, EiiImplResolution};
66
use rustc_hir::def::{DefKind, PerNS, Res};
77
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
@@ -11,6 +11,7 @@ use rustc_hir::{
1111
use rustc_index::{IndexSlice, IndexVec};
1212
use rustc_middle::span_bug;
1313
use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
14+
use rustc_session::parse::feature_err;
1415
use rustc_span::def_id::DefId;
1516
use rustc_span::edit_distance::find_best_match_for_name;
1617
use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym};
@@ -89,6 +90,12 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
8990
self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item)))
9091
}
9192
AstOwner::AssocItem(item, ctxt) => {
93+
if matches!(item.kind, AssocItemKind::ExternImpl(_)) {
94+
// We do not lower `extern unsafe? impl` items.
95+
// They just discharge the `auto impl` obligation from the current
96+
// `impl` block.
97+
return;
98+
}
9299
self.with_lctx(item.id, |lctx| lctx.lower_assoc_item(item, ctxt))
93100
}
94101
AstOwner::ForeignItem(item) => self.with_lctx(item.id, |lctx| {
@@ -216,6 +223,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
216223
| ItemKind::Trait(..)
217224
| ItemKind::TraitAlias(..)
218225
| ItemKind::Impl(..)
226+
| ItemKind::AutoImpl(..)
227+
| ItemKind::ExternImpl(..)
219228
| ItemKind::MacCall(..)
220229
| ItemKind::MacroDef(..)
221230
| ItemKind::Delegation(..)
@@ -508,6 +517,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
508517
constness,
509518
})
510519
}
520+
ItemKind::AutoImpl(..) | ItemKind::ExternImpl(..) => {
521+
feature_err(
522+
self.tcx.sess,
523+
sym::supertrait_auto_impl,
524+
span,
525+
"feature is under construction",
526+
)
527+
.emit();
528+
FatalError.raise()
529+
}
511530
ItemKind::Trait(box Trait {
512531
constness,
513532
is_auto,
@@ -1039,6 +1058,50 @@ impl<'hir> LoweringContext<'_, 'hir> {
10391058
true,
10401059
)
10411060
}
1061+
AssocItemKind::AutoImpl(ai) => {
1062+
let tcx = self.tcx;
1063+
if !tcx.features().supertrait_auto_impl() {
1064+
feature_err(
1065+
&tcx.sess,
1066+
sym::supertrait_auto_impl,
1067+
i.span,
1068+
"feature is under construction",
1069+
)
1070+
.emit();
1071+
FatalError.raise();
1072+
}
1073+
let generics = tcx.arena.alloc(hir::Generics {
1074+
has_where_clause_predicates: false,
1075+
params: &[],
1076+
predicates: &[],
1077+
where_clause_span: DUMMY_SP,
1078+
span: DUMMY_SP,
1079+
});
1080+
(
1081+
Ident::dummy(),
1082+
&*generics,
1083+
hir::TraitItemKind::AutoImpl(
1084+
tcx.arena.alloc(self.lower_poly_trait_ref_inner(
1085+
&ai.generics.params,
1086+
&TraitBoundModifiers {
1087+
constness: BoundConstness::Never,
1088+
asyncness: BoundAsyncness::Normal,
1089+
polarity: match ai.of_trait.polarity {
1090+
ImplPolarity::Positive => BoundPolarity::Positive,
1091+
ImplPolarity::Negative(span) => BoundPolarity::Negative(span),
1092+
},
1093+
},
1094+
&ai.of_trait.trait_ref,
1095+
ai.of_trait.trait_ref.path.span,
1096+
RelaxedBoundPolicy::Forbidden(RelaxedBoundForbiddenReason::SuperTrait),
1097+
ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
1098+
)),
1099+
&[],
1100+
),
1101+
false,
1102+
)
1103+
}
1104+
AssocItemKind::ExternImpl(..) => unreachable!("we should never lower ast::ExternImpl"),
10421105
AssocItemKind::Type(box TyAlias {
10431106
ident,
10441107
generics,
@@ -1264,6 +1327,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
12641327
),
12651328
)
12661329
}
1330+
AssocItemKind::AutoImpl(_) | AssocItemKind::ExternImpl(_) => {
1331+
feature_err(
1332+
&self.tcx.sess,
1333+
sym::supertrait_auto_impl,
1334+
i.span,
1335+
"feature is under construction",
1336+
)
1337+
.emit();
1338+
FatalError.raise();
1339+
}
12671340
AssocItemKind::Delegation(box delegation) => {
12681341
let delegation_results = self.lower_delegation(delegation, i.id);
12691342
(

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2118,21 +2118,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
21182118
PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ }: &PolyTraitRef,
21192119
rbp: RelaxedBoundPolicy<'_>,
21202120
itctx: ImplTraitContext,
2121+
) -> hir::PolyTraitRef<'hir> {
2122+
self.lower_poly_trait_ref_inner(
2123+
bound_generic_params,
2124+
modifiers,
2125+
trait_ref,
2126+
*span,
2127+
rbp,
2128+
itctx,
2129+
)
2130+
}
2131+
2132+
#[instrument(level = "debug", skip(self))]
2133+
fn lower_poly_trait_ref_inner(
2134+
&mut self,
2135+
bound_generic_params: &[GenericParam],
2136+
modifiers: &TraitBoundModifiers,
2137+
trait_ref: &TraitRef,
2138+
span: Span,
2139+
rbp: RelaxedBoundPolicy<'_>,
2140+
itctx: ImplTraitContext,
21212141
) -> hir::PolyTraitRef<'hir> {
21222142
let bound_generic_params =
21232143
self.lower_lifetime_binder(trait_ref.ref_id, bound_generic_params);
21242144
let trait_ref = self.lower_trait_ref(*modifiers, trait_ref, itctx);
21252145
let modifiers = self.lower_trait_bound_modifiers(*modifiers);
21262146

21272147
if let ast::BoundPolarity::Maybe(_) = modifiers.polarity {
2128-
self.validate_relaxed_bound(trait_ref, *span, rbp);
2148+
self.validate_relaxed_bound(trait_ref, span, rbp);
21292149
}
21302150

21312151
hir::PolyTraitRef {
21322152
bound_generic_params,
21332153
modifiers,
21342154
trait_ref,
2135-
span: self.lower_span(*span),
2155+
span: self.lower_span(span),
21362156
}
21372157
}
21382158

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,6 +1463,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14631463
}
14641464
visit::walk_item(self, item);
14651465
}
1466+
1467+
ItemKind::AutoImpl(..) => {
1468+
self.dcx().emit_err(errors::AutoImplOutsideTraitOrImplTrait { span: item.span });
1469+
}
1470+
14661471
_ => visit::walk_item(self, item),
14671472
}
14681473

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,13 @@ pub(crate) struct NestedImplTrait {
614614
pub inner: Span,
615615
}
616616

617+
#[derive(Diagnostic)]
618+
#[diag("`auto impl` is outside a `trait` block or trait-`impl` block")]
619+
pub(crate) struct AutoImplOutsideTraitOrImplTrait {
620+
#[primary_span]
621+
pub(crate) span: Span,
622+
}
623+
617624
#[derive(Diagnostic)]
618625
#[diag("at least one trait must be specified")]
619626
pub(crate) struct AtLeastOneTrait {

0 commit comments

Comments
 (0)