Skip to content

Commit a20b86f

Browse files
authored
Rollup merge of #107282 - BoxyUwU:erica_builtin_pointee_impls, r=compiler-errors
erica solver: implement builtin `Pointee` trait impl candidates r? ```@compiler-errors```
2 parents f268c7b + a418e39 commit a20b86f

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed

Diff for: compiler/rustc_trait_selection/src/solve/assembly.rs

+7
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy + Eq {
133133
ecx: &mut EvalCtxt<'_, 'tcx>,
134134
goal: Goal<'tcx, Self>,
135135
) -> QueryResult<'tcx>;
136+
137+
fn consider_builtin_pointee_candidate(
138+
ecx: &mut EvalCtxt<'_, 'tcx>,
139+
goal: Goal<'tcx, Self>,
140+
) -> QueryResult<'tcx>;
136141
}
137142

138143
impl<'tcx> EvalCtxt<'_, 'tcx> {
@@ -259,6 +264,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
259264
G::consider_builtin_fn_trait_candidates(self, goal, kind)
260265
} else if lang_items.tuple_trait() == Some(trait_def_id) {
261266
G::consider_builtin_tuple_candidate(self, goal)
267+
} else if lang_items.pointee_trait() == Some(trait_def_id) {
268+
G::consider_builtin_pointee_candidate(self, goal)
262269
} else {
263270
Err(NoSolution)
264271
};

Diff for: compiler/rustc_trait_selection/src/solve/project_goals.rs

+91
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use super::{Certainty, EvalCtxt, Goal, QueryResult};
77
use rustc_errors::ErrorGuaranteed;
88
use rustc_hir::def::DefKind;
99
use rustc_hir::def_id::DefId;
10+
use rustc_hir::LangItem;
1011
use rustc_infer::infer::InferCtxt;
1112
use rustc_infer::traits::query::NoSolution;
1213
use rustc_infer::traits::specialization_graph::LeafDef;
@@ -391,6 +392,96 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
391392
) -> QueryResult<'tcx> {
392393
bug!("`Tuple` does not have an associated type: {:?}", goal);
393394
}
395+
396+
fn consider_builtin_pointee_candidate(
397+
ecx: &mut EvalCtxt<'_, 'tcx>,
398+
goal: Goal<'tcx, Self>,
399+
) -> QueryResult<'tcx> {
400+
let tcx = ecx.tcx();
401+
ecx.infcx.probe(|_| {
402+
let metadata_ty = match goal.predicate.self_ty().kind() {
403+
ty::Bool
404+
| ty::Char
405+
| ty::Int(..)
406+
| ty::Uint(..)
407+
| ty::Float(..)
408+
| ty::Array(..)
409+
| ty::RawPtr(..)
410+
| ty::Ref(..)
411+
| ty::FnDef(..)
412+
| ty::FnPtr(..)
413+
| ty::Closure(..)
414+
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
415+
| ty::Generator(..)
416+
| ty::GeneratorWitness(..)
417+
| ty::Never
418+
| ty::Foreign(..) => tcx.types.unit,
419+
420+
ty::Error(e) => tcx.ty_error_with_guaranteed(*e),
421+
422+
ty::Str | ty::Slice(_) => tcx.types.usize,
423+
424+
ty::Dynamic(_, _, _) => {
425+
let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
426+
tcx.bound_type_of(dyn_metadata)
427+
.subst(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())])
428+
}
429+
430+
ty::Infer(ty::TyVar(..)) | ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => {
431+
// FIXME(ptr_metadata): It would also be possible to return a `Ok(Ambig)` with no constraints.
432+
let sized_predicate = ty::Binder::dummy(tcx.at(DUMMY_SP).mk_trait_ref(
433+
LangItem::Sized,
434+
[ty::GenericArg::from(goal.predicate.self_ty())],
435+
));
436+
437+
let mut nested_goals = ecx.infcx.eq(
438+
goal.param_env,
439+
goal.predicate.term.ty().unwrap(),
440+
tcx.types.unit,
441+
)?;
442+
nested_goals.push(goal.with(tcx, sized_predicate));
443+
444+
return ecx.evaluate_all_and_make_canonical_response(nested_goals);
445+
}
446+
447+
ty::Adt(def, substs) if def.is_struct() => {
448+
match def.non_enum_variant().fields.last() {
449+
None => tcx.types.unit,
450+
Some(field_def) => {
451+
let self_ty = field_def.ty(tcx, substs);
452+
let new_goal = goal.with(
453+
tcx,
454+
ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
455+
);
456+
return ecx.evaluate_all_and_make_canonical_response(vec![new_goal]);
457+
}
458+
}
459+
}
460+
ty::Adt(_, _) => tcx.types.unit,
461+
462+
ty::Tuple(elements) => match elements.last() {
463+
None => tcx.types.unit,
464+
Some(&self_ty) => {
465+
let new_goal = goal.with(
466+
tcx,
467+
ty::Binder::dummy(goal.predicate.with_self_ty(tcx, self_ty)),
468+
);
469+
return ecx.evaluate_all_and_make_canonical_response(vec![new_goal]);
470+
}
471+
},
472+
473+
ty::Infer(ty::FreshTy(..) | ty::FreshIntTy(..) | ty::FreshFloatTy(..))
474+
| ty::Bound(..) => bug!(
475+
"unexpected self ty `{:?}` when normalizing `<T as Pointee>::Metadata`",
476+
goal.predicate.self_ty()
477+
),
478+
};
479+
480+
let nested_goals =
481+
ecx.infcx.eq(goal.param_env, goal.predicate.term.ty().unwrap(), metadata_ty)?;
482+
ecx.evaluate_all_and_make_canonical_response(nested_goals)
483+
})
484+
}
394485
}
395486

396487
/// This behavior is also implemented in `rustc_ty_utils` and in the old `project` code.

Diff for: compiler/rustc_trait_selection/src/solve/trait_goals.rs

+7
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
185185
Err(NoSolution)
186186
}
187187
}
188+
189+
fn consider_builtin_pointee_candidate(
190+
ecx: &mut EvalCtxt<'_, 'tcx>,
191+
_goal: Goal<'tcx, Self>,
192+
) -> QueryResult<'tcx> {
193+
ecx.make_canonical_response(Certainty::Yes)
194+
}
188195
}
189196

190197
impl<'tcx> EvalCtxt<'_, 'tcx> {

Diff for: tests/ui/traits/new-solver/pointee.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// compile-flags: -Ztrait-solver=next
2+
// check-pass
3+
#![feature(ptr_metadata)]
4+
5+
use std::ptr::{DynMetadata, Pointee};
6+
7+
trait Trait<U> {}
8+
struct MyDst<T: ?Sized>(T);
9+
10+
fn works<T>() {
11+
let _: <T as Pointee>::Metadata = ();
12+
let _: <[T] as Pointee>::Metadata = 1_usize;
13+
let _: <str as Pointee>::Metadata = 1_usize;
14+
let _: <dyn Trait<T> as Pointee>::Metadata = give::<DynMetadata<dyn Trait<T>>>();
15+
let _: <MyDst<T> as Pointee>::Metadata = ();
16+
let _: <((((([u8],),),),),) as Pointee>::Metadata = 1_usize;
17+
}
18+
19+
fn give<U>() -> U {
20+
loop {}
21+
}
22+
23+
fn main() {}

0 commit comments

Comments
 (0)