Skip to content

Commit e8af725

Browse files
draft for supertrait item in subtrait impls
1 parent e804cd4 commit e8af725

File tree

42 files changed

+467
-61
lines changed

Some content is hidden

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

42 files changed

+467
-61
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::{cmp, fmt};
2323

2424
pub use GenericArgs::*;
2525
pub use UnsafeSource::*;
26-
pub use rustc_ast_ir::{Movability, Mutability, Pinnedness};
26+
pub use rustc_ast_ir::{Movability, Mutability, Pinnedness, TraitRefSource};
2727
use rustc_data_structures::packed::Pu128;
2828
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
2929
use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -1386,6 +1386,7 @@ impl Expr {
13861386
ThinVec::new(),
13871387
path.clone(),
13881388
TraitBoundModifiers::NONE,
1389+
TraitRefSource::Any,
13891390
self.span,
13901391
Parens::No,
13911392
))),
@@ -3382,25 +3383,38 @@ pub struct PolyTraitRef {
33823383
/// The `Foo<&'a T>` in `<'a> Foo<&'a T>`.
33833384
pub trait_ref: TraitRef,
33843385

3386+
/// The source of this trait ref
3387+
/// and whether this trait ref should be regarded as
3388+
/// a nominal subtrait-supertrait relation.
3389+
pub source: TraitRefSource,
3390+
33853391
pub span: Span,
33863392

33873393
/// When `Yes`, the first and last character of `span` are an opening
33883394
/// and a closing paren respectively.
33893395
pub parens: Parens,
33903396
}
33913397

3398+
impl PolyTraitRef {
3399+
pub fn is_supertrait(&self) -> bool {
3400+
matches!(self.source, TraitRefSource::Supertrait)
3401+
}
3402+
}
3403+
33923404
impl PolyTraitRef {
33933405
pub fn new(
33943406
generic_params: ThinVec<GenericParam>,
33953407
path: Path,
33963408
modifiers: TraitBoundModifiers,
3409+
source: TraitRefSource,
33973410
span: Span,
33983411
parens: Parens,
33993412
) -> Self {
34003413
PolyTraitRef {
34013414
bound_generic_params: generic_params,
34023415
modifiers,
34033416
trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID },
3417+
source,
34043418
span,
34053419
parens,
34063420
}

compiler/rustc_ast/src/visit.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
1616
pub use rustc_ast_ir::visit::VisitorResult;
1717
pub use rustc_ast_ir::{try_visit, visit_opt, walk_list, walk_visitable_list};
18+
use rustc_span::def_id::LocalDefId;
1819
use rustc_span::source_map::Spanned;
1920
use rustc_span::{Ident, Span};
2021
use thin_vec::ThinVec;
@@ -52,15 +53,15 @@ pub enum BoundKind {
5253

5354
/// Super traits of a trait.
5455
/// E.g., `trait A: B`
55-
SuperTraits,
56+
SuperTraits { subtrait: LocalDefId },
5657
}
5758
impl BoundKind {
5859
pub fn descr(self) -> &'static str {
5960
match self {
6061
BoundKind::Bound => "bounds",
6162
BoundKind::Impl => "`impl Trait`",
6263
BoundKind::TraitObject => "`dyn` trait object bounds",
63-
BoundKind::SuperTraits => "supertrait bounds",
64+
BoundKind::SuperTraits { .. } => "supertrait bounds",
6465
}
6566
}
6667
}
@@ -266,8 +267,8 @@ macro_rules! common_visitor_and_walkers {
266267
walk_trait_ref(self, t)
267268
}
268269

269-
fn visit_param_bound(&mut self, bounds: &$($lt)? $($mut)? GenericBound, _ctxt: BoundKind) -> Self::Result {
270-
walk_param_bound(self, bounds)
270+
fn visit_param_bound(&mut self, bound: &$($lt)? $($mut)? GenericBound, _ctxt: BoundKind) -> Self::Result {
271+
walk_param_bound(self, bound)
271272
}
272273

273274
fn visit_precise_capturing_arg(&mut self, arg: &$($lt)? $($mut)? PreciseCapturingArg) -> Self::Result {
@@ -1142,7 +1143,7 @@ macro_rules! common_visitor_and_walkers {
11421143
vis: &mut V,
11431144
p: &$($lt)? $($mut)? PolyTraitRef,
11441145
) -> V::Result {
1145-
let PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ } = p;
1146+
let PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, .. } = p;
11461147
try_visit!(visit_modifiers(vis, modifiers));
11471148
try_visit!(visit_generic_params(vis, bound_generic_params));
11481149
try_visit!(vis.visit_trait_ref(trait_ref));

compiler/rustc_ast_ir/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,21 @@ pub enum Pinnedness {
101101
Not,
102102
Pinned,
103103
}
104+
105+
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
106+
#[cfg_attr(
107+
feature = "nightly",
108+
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
109+
)]
110+
pub enum TraitRefSource {
111+
/// This source excludes all of the other relationships
112+
Any,
113+
/// The trait ref source establishes a subtrait-supertrait
114+
/// relationship
115+
Supertrait,
116+
/// The trait ref source establishes a subtrait-supertrait
117+
/// relationship and we are obliged to assert that the supertrait
118+
/// is a marker trait and generate an automatic `impl` for this
119+
/// marker trait
120+
SupertraitAutoImpl,
121+
}

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12081208
bound_generic_params: ThinVec::new(),
12091209
modifiers: TraitBoundModifiers::NONE,
12101210
trait_ref: TraitRef { path: path.clone(), ref_id: t.id },
1211+
source: TraitRefSource::Any,
12111212
span: t.span,
12121213
parens: ast::Parens::No,
12131214
},
@@ -2018,7 +2019,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
20182019
let bound_generic_params =
20192020
self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params);
20202021
let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx);
2021-
let modifiers = self.lower_trait_bound_modifiers(p.modifiers);
2022+
let modifiers = self.lower_trait_bound_modifiers(p.modifiers, p.source);
20222023
hir::PolyTraitRef {
20232024
bound_generic_params,
20242025
modifiers,
@@ -2253,8 +2254,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22532254
fn lower_trait_bound_modifiers(
22542255
&mut self,
22552256
modifiers: TraitBoundModifiers,
2257+
source: TraitRefSource,
22562258
) -> hir::TraitBoundModifiers {
2257-
hir::TraitBoundModifiers { constness: modifiers.constness, polarity: modifiers.polarity }
2259+
hir::TraitBoundModifiers {
2260+
constness: modifiers.constness,
2261+
polarity: modifiers.polarity,
2262+
source,
2263+
}
22582264
}
22592265

22602266
// Helper methods for building HIR.

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use rustc_session::lint::builtin::{
3636
PATTERNS_IN_FNS_WITHOUT_BODY,
3737
};
3838
use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
39+
use rustc_span::def_id::{DefIndex, LocalDefId};
3940
use rustc_span::{Ident, Span, kw, sym};
4041
use rustc_target::spec::{AbiMap, AbiMapping};
4142
use thin_vec::thin_vec;
@@ -1149,7 +1150,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11491150
is_const_trait.is_none().then(|| TildeConstReason::Trait { span: item.span });
11501151
self.with_tilde_const(disallowed, |this| {
11511152
this.visit_generics(generics);
1152-
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
1153+
walk_list!(
1154+
this,
1155+
visit_param_bound,
1156+
bounds,
1157+
BoundKind::SuperTraits {
1158+
subtrait: LocalDefId { local_def_index: DefIndex::ZERO }
1159+
}
1160+
)
11531161
});
11541162
self.with_in_trait(item.span, is_const_trait, |this| {
11551163
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
@@ -1373,9 +1381,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13731381
match bound {
13741382
GenericBound::Trait(trait_ref) => {
13751383
match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
1376-
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
1377-
if !self.features.more_maybe_bounds() =>
1378-
{
1384+
(
1385+
BoundKind::SuperTraits { .. },
1386+
BoundConstness::Never,
1387+
BoundPolarity::Maybe(_),
1388+
) if !self.features.more_maybe_bounds() => {
13791389
self.sess
13801390
.create_feature_err(
13811391
errors::OptionalTraitSupertrait {
@@ -1438,7 +1448,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14381448
GenericBound::Outlives(_) => {}
14391449
GenericBound::Use(_, span) => match ctxt {
14401450
BoundKind::Impl => {}
1441-
BoundKind::Bound | BoundKind::TraitObject | BoundKind::SuperTraits => {
1451+
BoundKind::Bound | BoundKind::TraitObject | BoundKind::SuperTraits { .. } => {
14421452
self.dcx().emit_err(errors::PreciseCapturingNotAllowedHere {
14431453
loc: ctxt.descr(),
14441454
span: *span,

compiler/rustc_expand/src/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ impl<'a> ExtCtxt<'a> {
194194
asyncness: ast::BoundAsyncness::Normal,
195195
},
196196
trait_ref: self.trait_ref(path),
197+
source: ast::TraitRefSource::Any,
197198
span,
198199
parens: ast::Parens::No,
199200
}

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,6 +1260,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
12601260
TEST, pattern_complexity_limit, CrateLevel, template!(NameValueStr: "N"),
12611261
ErrorFollowing, EncodeCrossCrate::No,
12621262
),
1263+
rustc_attr!(
1264+
TEST, rustc_supertrait_in_subtrait_impl, Normal, template!(Word),
1265+
WarnFollowing, EncodeCrossCrate::Yes,
1266+
),
12631267
];
12641268

12651269
pub fn is_builtin_attr_name(name: Symbol) -> bool {

compiler/rustc_hir/src/hir.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_ast::{
1212
pub use rustc_ast::{
1313
AssignOp, AssignOpKind, AttrId, AttrStyle, BinOp, BinOpKind, BindingMode, BorrowKind,
1414
BoundConstness, BoundPolarity, ByRef, CaptureBy, DelimArgs, ImplPolarity, IsAuto,
15-
MetaItemInner, MetaItemLit, Movability, Mutability, UnOp,
15+
MetaItemInner, MetaItemLit, Movability, Mutability, TraitRefSource, UnOp,
1616
};
1717
use rustc_attr_data_structures::AttributeKind;
1818
use rustc_data_structures::fingerprint::Fingerprint;
@@ -707,11 +707,15 @@ pub enum GenericArgsParentheses {
707707
pub struct TraitBoundModifiers {
708708
pub constness: BoundConstness,
709709
pub polarity: BoundPolarity,
710+
pub source: TraitRefSource,
710711
}
711712

712713
impl TraitBoundModifiers {
713-
pub const NONE: Self =
714-
TraitBoundModifiers { constness: BoundConstness::Never, polarity: BoundPolarity::Positive };
714+
pub const NONE: Self = TraitBoundModifiers {
715+
constness: BoundConstness::Never,
716+
polarity: BoundPolarity::Positive,
717+
source: TraitRefSource::Any,
718+
};
715719
}
716720

717721
#[derive(Clone, Copy, Debug, HashStable_Generic)]
@@ -4966,7 +4970,7 @@ mod size_asserts {
49664970
static_assert_size!(ForeignItem<'_>, 96);
49674971
static_assert_size!(ForeignItemKind<'_>, 56);
49684972
static_assert_size!(GenericArg<'_>, 16);
4969-
static_assert_size!(GenericBound<'_>, 64);
4973+
static_assert_size!(GenericBound<'_>, 72);
49704974
static_assert_size!(Generics<'_>, 56);
49714975
static_assert_size!(Impl<'_>, 80);
49724976
static_assert_size!(ImplItem<'_>, 88);

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ pub(crate) fn provide(providers: &mut Providers) {
7979
predicates_of: predicates_of::predicates_of,
8080
explicit_predicates_of: predicates_of::explicit_predicates_of,
8181
explicit_super_predicates_of: predicates_of::explicit_super_predicates_of,
82+
supertrait_auto_impls: predicates_of::supertrait_auto_impls,
8283
explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of,
8384
explicit_supertraits_containing_assoc_item:
8485
predicates_of::explicit_supertraits_containing_assoc_item,

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,33 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
713713
ty::EarlyBinder::bind(implied_bounds)
714714
}
715715

716+
/// This query collects supertraits that should be implicitly `impl`ed
717+
/// within the context of a subtrait `impl`.
718+
/// In doing so, this subtrait may authorise the compiler to generate `impl`s
719+
/// on marker supertraits.
720+
/// This query also reports the authorisation.
721+
pub(super) fn supertrait_auto_impls<'tcx>(
722+
tcx: TyCtxt<'tcx>,
723+
trait_def_id: LocalDefId,
724+
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, hir::TraitRefSource)]> {
725+
let Node::Item(item) = tcx.hir_node_by_def_id(trait_def_id) else {
726+
bug!("trait_def_id {trait_def_id:?} is not an item");
727+
};
728+
729+
let superbounds = match item.kind {
730+
hir::ItemKind::Trait(_, _, _, _, supertraits, _)
731+
| hir::ItemKind::TraitAlias(_, _, supertraits) => supertraits,
732+
_ => span_bug!(item.span, "supertrait_auto_impls invoked on non-trait"),
733+
};
734+
735+
let icx = ItemCtxt::new(tcx, trait_def_id);
736+
737+
let self_param_ty = tcx.types.self_param;
738+
let mut bounds = vec![];
739+
icx.lowerer().lower_supertrait_auto_impls(self_param_ty, superbounds, &mut bounds);
740+
ty::EarlyBinder::bind(&*tcx.arena.alloc_from_iter(bounds))
741+
}
742+
716743
// Make sure when elaborating supertraits, probing for associated types, etc.,
717744
// we really truly are elaborating clauses that have `ty` as their self type.
718745
// This is very important since downstream code relies on this being correct.

0 commit comments

Comments
 (0)