Skip to content

Commit 3b0e1c1

Browse files
committed
trait_sel: {Meta,Pointee}Sized on ?Sized types
Expand the automatic implementation of `MetaSized` and `PointeeSized` so that it is also implemented on non-`Sized` types, just not `ty::Foreign` (extern type).
1 parent d43da6f commit 3b0e1c1

File tree

22 files changed

+907
-220
lines changed

22 files changed

+907
-220
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,11 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
12581258
debug!(?item.owner_id);
12591259

12601260
let def_id = item.owner_id.def_id;
1261+
if tcx.is_lang_item(def_id.into(), LangItem::PointeeSized) {
1262+
// `PointeeSized` is removed during lowering.
1263+
return Ok(());
1264+
}
1265+
12611266
let trait_def = tcx.trait_def(def_id);
12621267
if trait_def.is_marker
12631268
|| matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker)

compiler/rustc_middle/src/query/keys.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,14 @@ impl Key for (DefId, SimplifiedType) {
328328
}
329329
}
330330

331+
impl Key for (DefId, ty::SizedTraitKind) {
332+
type Cache<V> = DefaultCache<Self, V>;
333+
334+
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
335+
self.0.default_span(tcx)
336+
}
337+
}
338+
331339
impl<'tcx> Key for GenericArgsRef<'tcx> {
332340
type Cache<V> = DefaultCache<Self, V>;
333341

compiler/rustc_middle/src/query/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ use crate::ty::layout::ValidityRequirement;
8181
use crate::ty::print::{PrintTraitRefExt, describe_as_module};
8282
use crate::ty::util::AlwaysRequiresDrop;
8383
use crate::ty::{
84-
self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, Ty, TyCtxt,
85-
TyCtxtFeed,
84+
self, CrateInherentImpls, GenericArg, GenericArgsRef, PseudoCanonicalInput, SizedTraitKind, Ty,
85+
TyCtxt, TyCtxtFeed,
8686
};
8787
use crate::{dep_graph, mir, thir};
8888

@@ -854,9 +854,10 @@ rustc_queries! {
854854
cache_on_disk_if { key.is_local() }
855855
separate_provide_extern
856856
}
857-
858-
query adt_sized_constraint(key: DefId) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
859-
desc { |tcx| "computing the `Sized` constraint for `{}`", tcx.def_path_str(key) }
857+
query adt_sizedness_constraint(
858+
key: (DefId, SizedTraitKind)
859+
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
860+
desc { |tcx| "computing the sizedness constraint for `{}`", tcx.def_path_str(key.0) }
860861
}
861862

862863
query adt_dtorck_constraint(

compiler/rustc_middle/src/ty/adt.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,12 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
229229
)
230230
}
231231

232-
fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
233-
self.sized_constraint(tcx)
232+
fn sizedness_constraint(
233+
self,
234+
tcx: TyCtxt<'tcx>,
235+
sizedness: ty::SizedTraitKind,
236+
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
237+
self.sizedness_constraint(tcx, sizedness)
234238
}
235239

236240
fn is_fundamental(self) -> bool {
@@ -634,10 +638,15 @@ impl<'tcx> AdtDef<'tcx> {
634638
tcx.adt_async_destructor(self.did())
635639
}
636640

637-
/// Returns a type such that `Self: Sized` if and only if that type is `Sized`,
638-
/// or `None` if the type is always sized.
639-
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
640-
if self.is_struct() { tcx.adt_sized_constraint(self.did()) } else { None }
641+
/// If this ADT is a struct, returns a type such that `Self: {Meta,Pointee,}Sized` if and only
642+
/// if that type is `{Meta,Pointee,}Sized`, or `None` if this ADT is always
643+
/// `{Meta,Pointee,}Sized`.
644+
pub fn sizedness_constraint(
645+
self,
646+
tcx: TyCtxt<'tcx>,
647+
sizedness: ty::SizedTraitKind,
648+
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
649+
if self.is_struct() { tcx.adt_sizedness_constraint((self.did(), sizedness)) } else { None }
641650
}
642651
}
643652

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub use rustc_type_ir::fast_reject::DeepRejectCtxt;
6060
)]
6161
use rustc_type_ir::inherent;
6262
pub use rustc_type_ir::relate::VarianceDiagInfo;
63+
pub use rustc_type_ir::solve::SizedTraitKind;
6364
pub use rustc_type_ir::*;
6465
#[allow(hidden_glob_reexports, unused_imports)]
6566
use rustc_type_ir::{InferCtxtLike, Interner};

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1816,7 +1816,7 @@ impl<'tcx> Ty<'tcx> {
18161816
ty::Tuple(tys) => tys.last().is_none_or(|ty| ty.is_trivially_sized(tcx)),
18171817

18181818
ty::Adt(def, args) => def
1819-
.sized_constraint(tcx)
1819+
.sizedness_constraint(tcx, ty::SizedTraitKind::Sized)
18201820
.is_none_or(|ty| ty.instantiate(tcx, args).is_trivially_sized(tcx)),
18211821

18221822
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false,

compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::ops::ControlFlow;
88
use derive_where::derive_where;
99
use rustc_type_ir::inherent::*;
1010
use rustc_type_ir::lang_items::TraitSolverLangItem;
11+
use rustc_type_ir::solve::SizedTraitKind;
1112
use rustc_type_ir::{
1213
self as ty, Interner, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt as _,
1314
TypeVisitor, TypingMode, Upcast as _, elaborate,
@@ -203,31 +204,15 @@ where
203204
goal: Goal<I, Self>,
204205
) -> Result<Candidate<I>, NoSolution>;
205206

206-
/// A type is `Sized` if its tail component is `Sized`.
207+
/// A type is `Sized` if its tail component is `Sized` and a type is `MetaSized` if its tail
208+
/// component is `MetaSized`.
207209
///
208210
/// These components are given by built-in rules from
209-
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
210-
fn consider_builtin_sized_candidate(
211-
ecx: &mut EvalCtxt<'_, D>,
212-
goal: Goal<I, Self>,
213-
) -> Result<Candidate<I>, NoSolution>;
214-
215-
/// A type is `MetaSized` if its tail component is `MetaSized`.
216-
///
217-
/// These components are given by built-in rules from
218-
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
219-
fn consider_builtin_meta_sized_candidate(
220-
ecx: &mut EvalCtxt<'_, D>,
221-
goal: Goal<I, Self>,
222-
) -> Result<Candidate<I>, NoSolution>;
223-
224-
/// A type is `PointeeSized` if its tail component is `PointeeSized`.
225-
///
226-
/// These components are given by built-in rules from
227-
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
228-
fn consider_builtin_pointee_sized_candidate(
211+
/// [`structural_traits::instantiate_constituent_tys_for_sizedness_trait`].
212+
fn consider_builtin_sizedness_candidates(
229213
ecx: &mut EvalCtxt<'_, D>,
230214
goal: Goal<I, Self>,
215+
sizedness: SizedTraitKind,
231216
) -> Result<Candidate<I>, NoSolution>;
232217

233218
/// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
@@ -484,12 +469,14 @@ where
484469
G::consider_trait_alias_candidate(self, goal)
485470
} else {
486471
match cx.as_lang_item(trait_def_id) {
487-
Some(TraitSolverLangItem::Sized) => G::consider_builtin_sized_candidate(self, goal),
472+
Some(TraitSolverLangItem::Sized) => {
473+
G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::Sized)
474+
}
488475
Some(TraitSolverLangItem::MetaSized) => {
489-
G::consider_builtin_meta_sized_candidate(self, goal)
476+
G::consider_builtin_sizedness_candidates(self, goal, SizedTraitKind::MetaSized)
490477
}
491478
Some(TraitSolverLangItem::PointeeSized) => {
492-
G::consider_builtin_pointee_sized_candidate(self, goal)
479+
unreachable!("`PointeeSized` is removed during lowering");
493480
}
494481
Some(TraitSolverLangItem::Copy | TraitSolverLangItem::Clone) => {
495482
G::consider_builtin_copy_clone_candidate(self, goal)

compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use derive_where::derive_where;
55
use rustc_type_ir::data_structures::HashMap;
66
use rustc_type_ir::inherent::*;
77
use rustc_type_ir::lang_items::TraitSolverLangItem;
8+
use rustc_type_ir::solve::SizedTraitKind;
89
use rustc_type_ir::solve::inspect::ProbeKind;
910
use rustc_type_ir::{
1011
self as ty, FallibleTypeFolder, Interner, Movability, Mutability, TypeFoldable,
@@ -104,17 +105,19 @@ where
104105
}
105106

106107
#[instrument(level = "trace", skip(ecx), ret)]
107-
pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<D, I>(
108+
pub(in crate::solve) fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
108109
ecx: &EvalCtxt<'_, D>,
110+
sizedness: SizedTraitKind,
109111
ty: I::Ty,
110112
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
111113
where
112114
D: SolverDelegate<Interner = I>,
113115
I: Interner,
114116
{
115117
match ty.kind() {
116-
// impl Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char, &mut? T, [T; N], dyn* Trait, !
117-
// impl Sized for Coroutine, CoroutineWitness, Closure, CoroutineClosure
118+
// impl {Meta,}Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char
119+
// impl {Meta,}Sized for &mut? T, [T; N], dyn* Trait, !, Coroutine, CoroutineWitness
120+
// impl {Meta,}Sized for Closure, CoroutineClosure
118121
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
119122
| ty::Uint(_)
120123
| ty::Int(_)
@@ -135,13 +138,16 @@ where
135138
| ty::Dynamic(_, _, ty::DynStar)
136139
| ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
137140

138-
ty::Str
139-
| ty::Slice(_)
140-
| ty::Dynamic(..)
141-
| ty::Foreign(..)
142-
| ty::Alias(..)
143-
| ty::Param(_)
144-
| ty::Placeholder(..) => Err(NoSolution),
141+
// impl {Meta,}Sized for str, [T], dyn Trait
142+
ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
143+
SizedTraitKind::Sized => Err(NoSolution),
144+
SizedTraitKind::MetaSized => Ok(ty::Binder::dummy(vec![])),
145+
},
146+
147+
// impl {} for extern type
148+
ty::Foreign(..) => Err(NoSolution),
149+
150+
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
145151

146152
ty::Bound(..)
147153
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
@@ -150,22 +156,27 @@ where
150156

151157
ty::UnsafeBinder(bound_ty) => Ok(bound_ty.map_bound(|ty| vec![ty])),
152158

153-
// impl Sized for ()
154-
// impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1
159+
// impl {Meta,}Sized for ()
160+
// impl {Meta,}Sized for (T1, T2, .., Tn) where Tn: {Meta,}Sized if n >= 1
155161
ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
156162

157-
// impl Sized for Adt<Args...> where sized_constraint(Adt)<Args...>: Sized
158-
// `sized_constraint(Adt)` is the deepest struct trail that can be determined
159-
// by the definition of `Adt`, independent of the generic args.
160-
// impl Sized for Adt<Args...> if sized_constraint(Adt) == None
161-
// As a performance optimization, `sized_constraint(Adt)` can return `None`
162-
// if the ADTs definition implies that it is sized by for all possible args.
163+
// impl {Meta,}Sized for Adt<Args...>
164+
// where {meta,pointee,}sized_constraint(Adt)<Args...>: {Meta,}Sized
165+
//
166+
// `{meta,pointee,}sized_constraint(Adt)` is the deepest struct trail that can be
167+
// determined by the definition of `Adt`, independent of the generic args.
168+
//
169+
// impl {Meta,}Sized for Adt<Args...>
170+
// if {meta,pointee,}sized_constraint(Adt) == None
171+
//
172+
// As a performance optimization, `{meta,pointee,}sized_constraint(Adt)` can return `None`
173+
// if the ADTs definition implies that it is {meta,}sized by for all possible args.
163174
// In this case, the builtin impl will have no nested subgoals. This is a
164-
// "best effort" optimization and `sized_constraint` may return `Some`, even
165-
// if the ADT is sized for all possible args.
175+
// "best effort" optimization and `{meta,pointee,}sized_constraint` may return `Some`,
176+
// even if the ADT is {meta,pointee,}sized for all possible args.
166177
ty::Adt(def, args) => {
167-
if let Some(sized_crit) = def.sized_constraint(ecx.cx()) {
168-
Ok(ty::Binder::dummy(vec![sized_crit.instantiate(ecx.cx(), args)]))
178+
if let Some(crit) = def.sizedness_constraint(ecx.cx(), sizedness) {
179+
Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args)]))
169180
} else {
170181
Ok(ty::Binder::dummy(vec![]))
171182
}

compiler/rustc_next_trait_solver/src/solve/effect_goals.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use rustc_type_ir::fast_reject::DeepRejectCtxt;
55
use rustc_type_ir::inherent::*;
66
use rustc_type_ir::lang_items::TraitSolverLangItem;
7+
use rustc_type_ir::solve::SizedTraitKind;
78
use rustc_type_ir::solve::inspect::ProbeKind;
89
use rustc_type_ir::{self as ty, Interner, elaborate};
910
use tracing::instrument;
@@ -198,25 +199,12 @@ where
198199
unreachable!("trait aliases are never const")
199200
}
200201

201-
fn consider_builtin_sized_candidate(
202+
fn consider_builtin_sizedness_candidates(
202203
_ecx: &mut EvalCtxt<'_, D>,
203204
_goal: Goal<I, Self>,
205+
_sizedness: SizedTraitKind,
204206
) -> Result<Candidate<I>, NoSolution> {
205-
unreachable!("Sized is never const")
206-
}
207-
208-
fn consider_builtin_meta_sized_candidate(
209-
_ecx: &mut EvalCtxt<'_, D>,
210-
_goal: Goal<I, Self>,
211-
) -> Result<Candidate<I>, NoSolution> {
212-
unreachable!("MetaSized is never const")
213-
}
214-
215-
fn consider_builtin_pointee_sized_candidate(
216-
_ecx: &mut EvalCtxt<'_, D>,
217-
_goal: Goal<I, Self>,
218-
) -> Result<Candidate<I>, NoSolution> {
219-
unreachable!("PointeeSized is never const")
207+
unreachable!("Sized/MetaSized is never const")
220208
}
221209

222210
fn consider_builtin_copy_clone_candidate(

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mod opaque_types;
66
use rustc_type_ir::fast_reject::DeepRejectCtxt;
77
use rustc_type_ir::inherent::*;
88
use rustc_type_ir::lang_items::TraitSolverLangItem;
9+
use rustc_type_ir::solve::SizedTraitKind;
910
use rustc_type_ir::{self as ty, Interner, NormalizesTo, PredicateKind, Upcast as _};
1011
use tracing::instrument;
1112

@@ -413,25 +414,12 @@ where
413414
panic!("trait aliases do not have associated types: {:?}", goal);
414415
}
415416

416-
fn consider_builtin_sized_candidate(
417+
fn consider_builtin_sizedness_candidates(
417418
_ecx: &mut EvalCtxt<'_, D>,
418419
goal: Goal<I, Self>,
420+
_sizedness: SizedTraitKind,
419421
) -> Result<Candidate<I>, NoSolution> {
420-
panic!("`Sized` does not have an associated type: {:?}", goal);
421-
}
422-
423-
fn consider_builtin_meta_sized_candidate(
424-
_ecx: &mut EvalCtxt<'_, D>,
425-
goal: Goal<I, Self>,
426-
) -> Result<Candidate<I>, NoSolution> {
427-
panic!("`MetaSized` does not have an associated type: {:?}", goal);
428-
}
429-
430-
fn consider_builtin_pointee_sized_candidate(
431-
_ecx: &mut EvalCtxt<'_, D>,
432-
goal: Goal<I, Self>,
433-
) -> Result<Candidate<I>, NoSolution> {
434-
panic!("`PointeeSized` does not have an associated type: {:?}", goal);
422+
panic!("`Sized`/`MetaSized` does not have an associated type: {:?}", goal);
435423
}
436424

437425
fn consider_builtin_copy_clone_candidate(

0 commit comments

Comments
 (0)