Skip to content

Commit a6b0ca7

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 7a8e667 commit a6b0ca7

File tree

18 files changed

+1031
-240
lines changed

18 files changed

+1031
-240
lines changed

compiler/rustc_middle/src/query/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,12 @@ rustc_queries! {
813813
query adt_sized_constraint(key: DefId) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
814814
desc { |tcx| "computing the `Sized` constraint for `{}`", tcx.def_path_str(key) }
815815
}
816+
query adt_metasized_constraint(key: DefId) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
817+
desc { |tcx| "computing the `MetaSized` constraint for `{}`", tcx.def_path_str(key) }
818+
}
819+
query adt_pointeesized_constraint(key: DefId) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
820+
desc { |tcx| "computing the `PointeeSized` constraint for `{}`", tcx.def_path_str(key) }
821+
}
816822

817823
query adt_dtorck_constraint(
818824
key: DefId

compiler/rustc_middle/src/ty/adt.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,14 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
233233
self.sized_constraint(tcx)
234234
}
235235

236+
fn metasized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
237+
self.metasized_constraint(tcx)
238+
}
239+
240+
fn pointeesized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
241+
self.pointeesized_constraint(tcx)
242+
}
243+
236244
fn is_fundamental(self) -> bool {
237245
self.is_fundamental()
238246
}
@@ -625,6 +633,24 @@ impl<'tcx> AdtDef<'tcx> {
625633
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
626634
if self.is_struct() { tcx.adt_sized_constraint(self.did()) } else { None }
627635
}
636+
637+
/// Returns a type such that `Self: MetaSized` if and only if that type is `MetaSized`,
638+
/// or `None` if the type is always metasized.
639+
pub fn metasized_constraint(
640+
self,
641+
tcx: TyCtxt<'tcx>,
642+
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
643+
if self.is_struct() { tcx.adt_metasized_constraint(self.did()) } else { None }
644+
}
645+
646+
/// Returns a type such that `Self: PointeeSized` if and only if that type is `PointeeSized`,
647+
/// or `None` if the type is always pointeesized.
648+
pub fn pointeesized_constraint(
649+
self,
650+
tcx: TyCtxt<'tcx>,
651+
) -> Option<ty::EarlyBinder<'tcx, Ty<'tcx>>> {
652+
if self.is_struct() { tcx.adt_pointeesized_constraint(self.did()) } else { None }
653+
}
628654
}
629655

630656
#[derive(Clone, Copy, Debug, HashStable)]

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

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use derive_where::derive_where;
66
use rustc_type_ir::fold::TypeFoldable;
77
use rustc_type_ir::inherent::*;
88
use rustc_type_ir::lang_items::TraitSolverLangItem;
9+
use rustc_type_ir::solve::Sizedness;
910
use rustc_type_ir::visit::TypeVisitableExt as _;
1011
use rustc_type_ir::{self as ty, Interner, TypingMode, Upcast as _, elaborate};
1112
use tracing::{debug, instrument};
@@ -146,31 +147,18 @@ where
146147
goal: Goal<I, Self>,
147148
) -> Result<Candidate<I>, NoSolution>;
148149

149-
/// A type is `Sized` if its tail component is `Sized`.
150+
/// A type is `Sized` if its tail component is `Sized`, a type is `MetaSized` if its tail
151+
/// component is `MetaSized` and a type is `PointeeSized` if its tail component is
152+
/// `PointeeSized`.
150153
///
151154
/// These components are given by built-in rules from
152-
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
153-
fn consider_builtin_sized_candidate(
154-
ecx: &mut EvalCtxt<'_, D>,
155-
goal: Goal<I, Self>,
156-
) -> Result<Candidate<I>, NoSolution>;
157-
158-
/// A type is `MetaSized` if its tail component is `MetaSized`.
159-
///
160-
/// These components are given by built-in rules from
161-
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
162-
fn consider_builtin_metasized_candidate(
163-
ecx: &mut EvalCtxt<'_, D>,
164-
goal: Goal<I, Self>,
165-
) -> Result<Candidate<I>, NoSolution>;
166-
167-
/// A type is `PointeeSized` if its tail component is `PointeeSized`.
168-
///
169-
/// These components are given by built-in rules from
170-
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`].
171-
fn consider_builtin_pointeesized_candidate(
155+
/// [`structural_traits::instantiate_constituent_tys_for_sized_trait`],
156+
/// [`structural_traits::instantiate_constituent_tys_for_metasized_trait`] and
157+
/// [`structural_traits::instantiate_constituent_tys_for_pointeesized_trait`].
158+
fn consider_builtin_sizedness_candidates(
172159
ecx: &mut EvalCtxt<'_, D>,
173160
goal: Goal<I, Self>,
161+
sizedness: Sizedness,
174162
) -> Result<Candidate<I>, NoSolution>;
175163

176164
/// A type is `Copy` or `Clone` if its components are `Copy` or `Clone`.
@@ -414,12 +402,14 @@ where
414402
G::consider_trait_alias_candidate(self, goal)
415403
} else {
416404
match cx.as_lang_item(trait_def_id) {
417-
Some(TraitSolverLangItem::Sized) => G::consider_builtin_sized_candidate(self, goal),
405+
Some(TraitSolverLangItem::Sized) => {
406+
G::consider_builtin_sizedness_candidates(self, goal, Sizedness::Sized)
407+
}
418408
Some(TraitSolverLangItem::MetaSized) => {
419-
G::consider_builtin_metasized_candidate(self, goal)
409+
G::consider_builtin_sizedness_candidates(self, goal, Sizedness::MetaSized)
420410
}
421411
Some(TraitSolverLangItem::PointeeSized) => {
422-
G::consider_builtin_pointeesized_candidate(self, goal)
412+
G::consider_builtin_sizedness_candidates(self, goal, Sizedness::PointeeSized)
423413
}
424414
Some(TraitSolverLangItem::Copy | TraitSolverLangItem::Clone) => {
425415
G::consider_builtin_copy_clone_candidate(self, goal)

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

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_type_ir::data_structures::HashMap;
66
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
77
use rustc_type_ir::inherent::*;
88
use rustc_type_ir::lang_items::TraitSolverLangItem;
9+
use rustc_type_ir::solve::Sizedness;
910
use rustc_type_ir::{self as ty, Interner, Movability, Mutability, Upcast as _, elaborate};
1011
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
1112
use tracing::instrument;
@@ -101,13 +102,51 @@ pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<D, I>(
101102
ecx: &EvalCtxt<'_, D>,
102103
ty: I::Ty,
103104
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
105+
where
106+
D: SolverDelegate<Interner = I>,
107+
I: Interner,
108+
{
109+
instantiate_constituent_tys_for_sizedness_trait(ecx, Sizedness::Sized, ty)
110+
}
111+
112+
#[instrument(level = "trace", skip(ecx), ret)]
113+
pub(in crate::solve) fn instantiate_constituent_tys_for_metasized_trait<D, I>(
114+
ecx: &EvalCtxt<'_, D>,
115+
ty: I::Ty,
116+
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
117+
where
118+
D: SolverDelegate<Interner = I>,
119+
I: Interner,
120+
{
121+
instantiate_constituent_tys_for_sizedness_trait(ecx, Sizedness::MetaSized, ty)
122+
}
123+
124+
#[instrument(level = "trace", skip(ecx), ret)]
125+
pub(in crate::solve) fn instantiate_constituent_tys_for_pointeesized_trait<D, I>(
126+
ecx: &EvalCtxt<'_, D>,
127+
ty: I::Ty,
128+
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
129+
where
130+
D: SolverDelegate<Interner = I>,
131+
I: Interner,
132+
{
133+
instantiate_constituent_tys_for_sizedness_trait(ecx, Sizedness::PointeeSized, ty)
134+
}
135+
136+
#[instrument(level = "trace", skip(ecx), ret)]
137+
fn instantiate_constituent_tys_for_sizedness_trait<D, I>(
138+
ecx: &EvalCtxt<'_, D>,
139+
sizedness: Sizedness,
140+
ty: I::Ty,
141+
) -> Result<ty::Binder<I, Vec<I::Ty>>, NoSolution>
104142
where
105143
D: SolverDelegate<Interner = I>,
106144
I: Interner,
107145
{
108146
match ty.kind() {
109-
// impl Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char, &mut? T, [T; N], dyn* Trait, !
110-
// impl Sized for Coroutine, CoroutineWitness, Closure, CoroutineClosure
147+
// impl {Meta,Pointee,}Sized for u*, i*, bool, f*, FnDef, FnPtr, *(const/mut) T, char
148+
// impl {Meta,Pointee,}Sized for &mut? T, [T; N], dyn* Trait, !, Coroutine, CoroutineWitness
149+
// impl {Meta,Pointee,}Sized for Closure, CoroutineClosure
111150
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
112151
| ty::Uint(_)
113152
| ty::Int(_)
@@ -128,13 +167,19 @@ where
128167
| ty::Dynamic(_, _, ty::DynStar)
129168
| ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
130169

131-
ty::Str
132-
| ty::Slice(_)
133-
| ty::Dynamic(..)
134-
| ty::Foreign(..)
135-
| ty::Alias(..)
136-
| ty::Param(_)
137-
| ty::Placeholder(..) => Err(NoSolution),
170+
// impl {Meta,Pointee,}Sized for str, [T], dyn Trait
171+
ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
172+
Sizedness::Sized => Err(NoSolution),
173+
Sizedness::MetaSized | Sizedness::PointeeSized => Ok(ty::Binder::dummy(vec![])),
174+
},
175+
176+
// impl PointeeSized for extern type
177+
ty::Foreign(..) => match sizedness {
178+
Sizedness::Sized | Sizedness::MetaSized => Err(NoSolution),
179+
Sizedness::PointeeSized => Ok(ty::Binder::dummy(vec![])),
180+
},
181+
182+
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution),
138183

139184
ty::Bound(..)
140185
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
@@ -143,22 +188,27 @@ where
143188

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

146-
// impl Sized for ()
147-
// impl Sized for (T1, T2, .., Tn) where Tn: Sized if n >= 1
191+
// impl {Meta,}Sized for ()
192+
// impl {Meta,}Sized for (T1, T2, .., Tn) where Tn: {Meta,}Sized if n >= 1
148193
ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.last().map_or_else(Vec::new, |ty| vec![ty]))),
149194

150-
// impl Sized for Adt<Args...> where sized_constraint(Adt)<Args...>: Sized
151-
// `sized_constraint(Adt)` is the deepest struct trail that can be determined
195+
// impl {Meta,}Sized for Adt<Args...> where {meta,}sized_constraint(Adt)<Args...>: {Meta,}Sized
196+
// `{meta,}sized_constraint(Adt)` is the deepest struct trail that can be determined
152197
// by the definition of `Adt`, independent of the generic args.
153-
// impl Sized for Adt<Args...> if sized_constraint(Adt) == None
154-
// As a performance optimization, `sized_constraint(Adt)` can return `None`
155-
// if the ADTs definition implies that it is sized by for all possible args.
198+
// impl {Meta,}Sized for Adt<Args...> if {meta,}sized_constraint(Adt) == None
199+
// As a performance optimization, `{meta,}sized_constraint(Adt)` can return `None`
200+
// if the ADTs definition implies that it is {meta,}sized by for all possible args.
156201
// In this case, the builtin impl will have no nested subgoals. This is a
157-
// "best effort" optimization and `sized_constraint` may return `Some`, even
158-
// if the ADT is sized for all possible args.
202+
// "best effort" optimization and `{meta,}sized_constraint` may return `Some`, even
203+
// if the ADT is {meta,}sized for all possible args.
159204
ty::Adt(def, args) => {
160-
if let Some(sized_crit) = def.sized_constraint(ecx.cx()) {
161-
Ok(ty::Binder::dummy(vec![sized_crit.instantiate(ecx.cx(), args)]))
205+
let crit = match sizedness {
206+
Sizedness::Sized => def.sized_constraint(ecx.cx()),
207+
Sizedness::MetaSized => def.metasized_constraint(ecx.cx()),
208+
Sizedness::PointeeSized => def.pointeesized_constraint(ecx.cx()),
209+
};
210+
if let Some(crit) = crit {
211+
Ok(ty::Binder::dummy(vec![crit.instantiate(ecx.cx(), args)]))
162212
} else {
163213
Ok(ty::Binder::dummy(vec![]))
164214
}

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::Sizedness;
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: Sizedness,
204206
) -> Result<Candidate<I>, NoSolution> {
205-
unreachable!("Sized is never const")
206-
}
207-
208-
fn consider_builtin_metasized_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_pointeesized_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/PointeeSized 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 weak_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::Sizedness;
910
use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
1011
use tracing::instrument;
1112

@@ -312,25 +313,12 @@ where
312313
panic!("trait aliases do not have associated types: {:?}", goal);
313314
}
314315

315-
fn consider_builtin_sized_candidate(
316+
fn consider_builtin_sizedness_candidates(
316317
_ecx: &mut EvalCtxt<'_, D>,
317318
goal: Goal<I, Self>,
319+
_sizedness: Sizedness,
318320
) -> Result<Candidate<I>, NoSolution> {
319-
panic!("`Sized` does not have an associated type: {:?}", goal);
320-
}
321-
322-
fn consider_builtin_metasized_candidate(
323-
_ecx: &mut EvalCtxt<'_, D>,
324-
goal: Goal<I, Self>,
325-
) -> Result<Candidate<I>, NoSolution> {
326-
panic!("`MetaSized` does not have an associated type: {:?}", goal);
327-
}
328-
329-
fn consider_builtin_pointeesized_candidate(
330-
_ecx: &mut EvalCtxt<'_, D>,
331-
goal: Goal<I, Self>,
332-
) -> Result<Candidate<I>, NoSolution> {
333-
panic!("`PointeeSized` does not have an associated type: {:?}", goal);
321+
panic!("`Sized`/`MetaSized`/`PointeeSized` does not have an associated type: {:?}", goal);
334322
}
335323

336324
fn consider_builtin_copy_clone_candidate(

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_type_ir::data_structures::IndexSet;
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::CanonicalResponse;
7+
use rustc_type_ir::solve::{CanonicalResponse, Sizedness};
88
use rustc_type_ir::visit::TypeVisitableExt as _;
99
use rustc_type_ir::{
1010
self as ty, Interner, Movability, TraitPredicate, TypingMode, Upcast as _, elaborate,
@@ -217,9 +217,10 @@ where
217217
})
218218
}
219219

220-
fn consider_builtin_sized_candidate(
220+
fn consider_builtin_sizedness_candidates(
221221
ecx: &mut EvalCtxt<'_, D>,
222222
goal: Goal<I, Self>,
223+
sizedness: Sizedness,
223224
) -> Result<Candidate<I>, NoSolution> {
224225
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
225226
return Err(NoSolution);
@@ -228,37 +229,15 @@ where
228229
ecx.probe_and_evaluate_goal_for_constituent_tys(
229230
CandidateSource::BuiltinImpl(BuiltinImplSource::Trivial),
230231
goal,
231-
structural_traits::instantiate_constituent_tys_for_sized_trait,
232-
)
233-
}
234-
235-
fn consider_builtin_metasized_candidate(
236-
ecx: &mut EvalCtxt<'_, D>,
237-
goal: Goal<I, Self>,
238-
) -> Result<Candidate<I>, NoSolution> {
239-
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
240-
return Err(NoSolution);
241-
}
242-
243-
ecx.probe_and_evaluate_goal_for_constituent_tys(
244-
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
245-
goal,
246-
structural_traits::instantiate_constituent_tys_for_sized_trait,
247-
)
248-
}
249-
250-
fn consider_builtin_pointeesized_candidate(
251-
ecx: &mut EvalCtxt<'_, D>,
252-
goal: Goal<I, Self>,
253-
) -> Result<Candidate<I>, NoSolution> {
254-
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
255-
return Err(NoSolution);
256-
}
257-
258-
ecx.probe_and_evaluate_goal_for_constituent_tys(
259-
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
260-
goal,
261-
structural_traits::instantiate_constituent_tys_for_sized_trait,
232+
match sizedness {
233+
Sizedness::Sized => structural_traits::instantiate_constituent_tys_for_sized_trait,
234+
Sizedness::MetaSized => {
235+
structural_traits::instantiate_constituent_tys_for_metasized_trait
236+
}
237+
Sizedness::PointeeSized => {
238+
structural_traits::instantiate_constituent_tys_for_pointeesized_trait
239+
}
240+
},
262241
)
263242
}
264243

0 commit comments

Comments
 (0)