1 use rustc_data_structures
::fx
::FxHashMap
;
2 use rustc_hir
::{def_id::DefId, Movability, Mutability}
;
3 use rustc_infer
::traits
::query
::NoSolution
;
4 use rustc_middle
::ty
::{
5 self, Ty
, TyCtxt
, TypeFoldable
, TypeFolder
, TypeSuperFoldable
, TypeVisitableExt
,
8 use crate::solve
::EvalCtxt
;
10 // Calculates the constituent types of a type for `auto trait` purposes.
12 // For types with an "existential" binder, i.e. generator witnesses, we also
13 // instantiate the binder with placeholders eagerly.
14 pub(in crate::solve
) fn instantiate_constituent_tys_for_auto_trait
<'tcx
>(
15 ecx
: &EvalCtxt
<'_
, 'tcx
>,
17 ) -> Result
<Vec
<Ty
<'tcx
>>, NoSolution
> {
28 | ty
::Char
=> Ok(vec
![]),
30 // Treat `str` like it's defined as `struct str([u8]);`
31 ty
::Str
=> Ok(vec
![tcx
.mk_slice(tcx
.types
.u8)]),
36 | ty
::Alias(ty
::Projection
, ..)
40 bug
!("unexpected type `{ty}`")
43 ty
::RawPtr(ty
::TypeAndMut { ty: element_ty, .. }
) | ty
::Ref(_
, element_ty
, _
) => {
47 ty
::Array(element_ty
, _
) | ty
::Slice(element_ty
) => Ok(vec
![element_ty
]),
49 ty
::Tuple(ref tys
) => {
50 // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
51 Ok(tys
.iter().collect())
54 ty
::Closure(_
, ref substs
) => Ok(vec
![substs
.as_closure().tupled_upvars_ty()]),
56 ty
::Generator(_
, ref substs
, _
) => {
57 let generator_substs
= substs
.as_generator();
58 Ok(vec
![generator_substs
.tupled_upvars_ty(), generator_substs
.witness()])
61 ty
::GeneratorWitness(types
) => Ok(ecx
.instantiate_binder_with_placeholders(types
).to_vec()),
63 ty
::GeneratorWitnessMIR(def_id
, substs
) => Ok(ecx
65 .generator_hidden_types(def_id
)
67 ecx
.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
69 bty
.subst(tcx
, substs
),
74 // For `PhantomData<T>`, we pass `T`.
75 ty
::Adt(def
, substs
) if def
.is_phantom_data() => Ok(vec
![substs
.type_at(0)]),
77 ty
::Adt(def
, substs
) => Ok(def
.all_fields().map(|f
| f
.ty(tcx
, substs
)).collect()),
79 ty
::Alias(ty
::Opaque
, ty
::AliasTy { def_id, substs, .. }
) => {
80 // We can resolve the `impl Trait` to its concrete type,
81 // which enforces a DAG between the functions requiring
82 // the auto trait bounds in question.
83 Ok(vec
![tcx
.type_of(def_id
).subst(tcx
, substs
)])
88 pub(in crate::solve
) fn replace_erased_lifetimes_with_bound_vars
<'tcx
>(
91 ) -> ty
::Binder
<'tcx
, Ty
<'tcx
>> {
92 debug_assert
!(!ty
.has_late_bound_regions());
94 let ty
= tcx
.fold_regions(ty
, |mut r
, current_depth
| {
95 if let ty
::ReErased
= r
.kind() {
97 ty
::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None) }
;
99 r
= tcx
.mk_re_late_bound(current_depth
, br
);
103 let bound_vars
= tcx
.mk_bound_variable_kinds_from_iter(
104 (0..counter
).map(|_
| ty
::BoundVariableKind
::Region(ty
::BrAnon(None
))),
106 ty
::Binder
::bind_with_vars(ty
, bound_vars
)
109 pub(in crate::solve
) fn instantiate_constituent_tys_for_sized_trait
<'tcx
>(
110 ecx
: &EvalCtxt
<'_
, 'tcx
>,
112 ) -> Result
<Vec
<Ty
<'tcx
>>, NoSolution
> {
114 ty
::Infer(ty
::IntVar(_
) | ty
::FloatVar(_
))
125 | ty
::GeneratorWitness(..)
126 | ty
::GeneratorWitnessMIR(..)
130 | ty
::Dynamic(_
, _
, ty
::DynStar
)
131 | ty
::Error(_
) => Ok(vec
![]),
139 | ty
::Placeholder(..) => Err(NoSolution
),
142 | ty
::Infer(ty
::TyVar(_
) | ty
::FreshTy(_
) | ty
::FreshIntTy(_
) | ty
::FreshFloatTy(_
)) => {
143 bug
!("unexpected type `{ty}`")
146 ty
::Tuple(tys
) => Ok(tys
.to_vec()),
148 ty
::Adt(def
, substs
) => {
149 let sized_crit
= def
.sized_constraint(ecx
.tcx());
153 .map(|ty
| sized_crit
.rebind(*ty
).subst(ecx
.tcx(), substs
))
159 pub(in crate::solve
) fn instantiate_constituent_tys_for_copy_clone_trait
<'tcx
>(
160 ecx
: &EvalCtxt
<'_
, 'tcx
>,
162 ) -> Result
<Vec
<Ty
<'tcx
>>, NoSolution
> {
164 ty
::Infer(ty
::IntVar(_
) | ty
::FloatVar(_
))
167 | ty
::Error(_
) => Ok(vec
![]),
169 // Implementations are provided in core
177 | ty
::Ref(_
, _
, Mutability
::Not
)
178 | ty
::Array(..) => Err(NoSolution
),
183 | ty
::Generator(_
, _
, Movability
::Static
)
185 | ty
::Ref(_
, _
, Mutability
::Mut
)
189 | ty
::Placeholder(..) => Err(NoSolution
),
192 | ty
::Infer(ty
::TyVar(_
) | ty
::FreshTy(_
) | ty
::FreshIntTy(_
) | ty
::FreshFloatTy(_
)) => {
193 bug
!("unexpected type `{ty}`")
196 ty
::Tuple(tys
) => Ok(tys
.to_vec()),
198 ty
::Closure(_
, substs
) => Ok(vec
![substs
.as_closure().tupled_upvars_ty()]),
200 ty
::Generator(_
, substs
, Movability
::Movable
) => {
201 if ecx
.tcx().features().generator_clone
{
202 let generator
= substs
.as_generator();
203 Ok(vec
![generator
.tupled_upvars_ty(), generator
.witness()])
209 ty
::GeneratorWitness(types
) => Ok(ecx
.instantiate_binder_with_placeholders(types
).to_vec()),
211 ty
::GeneratorWitnessMIR(def_id
, substs
) => Ok(ecx
213 .generator_hidden_types(def_id
)
215 ecx
.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
217 bty
.subst(ecx
.tcx(), substs
),
224 // Returns a binder of the tupled inputs types and output type from a builtin callable type.
225 pub(in crate::solve
) fn extract_tupled_inputs_and_output_from_callable
<'tcx
>(
228 goal_kind
: ty
::ClosureKind
,
229 ) -> Result
<Option
<ty
::Binder
<'tcx
, (Ty
<'tcx
>, Ty
<'tcx
>)>>, NoSolution
> {
230 match *self_ty
.kind() {
231 // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
232 ty
::FnDef(def_id
, substs
) => {
233 let sig
= tcx
.fn_sig(def_id
);
234 if sig
.skip_binder().is_fn_trait_compatible()
235 && tcx
.codegen_fn_attrs(def_id
).target_features
.is_empty()
238 sig
.subst(tcx
, substs
)
239 .map_bound(|sig
| (tcx
.mk_tup(sig
.inputs()), sig
.output())),
245 // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
247 if sig
.is_fn_trait_compatible() {
248 Ok(Some(sig
.map_bound(|sig
| (tcx
.mk_tup(sig
.inputs()), sig
.output()))))
253 ty
::Closure(_
, substs
) => {
254 let closure_substs
= substs
.as_closure();
255 match closure_substs
.kind_ty().to_opt_closure_kind() {
256 // If the closure's kind doesn't extend the goal kind,
257 // then the closure doesn't implement the trait.
258 Some(closure_kind
) => {
259 if !closure_kind
.extends(goal_kind
) {
260 return Err(NoSolution
);
263 // Closure kind is not yet determined, so we return ambiguity unless
264 // the expected kind is `FnOnce` as that is always implemented.
266 if goal_kind
!= ty
::ClosureKind
::FnOnce
{
271 Ok(Some(closure_substs
.sig().map_bound(|sig
| (sig
.inputs()[0], sig
.output()))))
285 | ty
::Dynamic(_
, _
, _
)
286 | ty
::Generator(_
, _
, _
)
287 | ty
::GeneratorWitness(_
)
288 | ty
::GeneratorWitnessMIR(..)
293 | ty
::Placeholder(..)
294 | ty
::Infer(ty
::IntVar(_
) | ty
::FloatVar(_
))
295 | ty
::Error(_
) => Err(NoSolution
),
298 | ty
::Infer(ty
::TyVar(_
) | ty
::FreshTy(_
) | ty
::FreshIntTy(_
) | ty
::FreshFloatTy(_
)) => {
299 bug
!("unexpected type `{self_ty}`")
304 /// Assemble a list of predicates that would be present on a theoretical
305 /// user impl for an object type. These predicates must be checked any time
306 /// we assemble a built-in object candidate for an object type, since they
307 /// are not implied by the well-formedness of the type.
309 /// For example, given the following traits:
311 /// ```rust,ignore (theoretical code)
319 /// For the dyn type `dyn Foo<Item = Ty>`, we can imagine there being a
320 /// pair of theoretical impls:
322 /// ```rust,ignore (theoretical code)
323 /// impl Foo for dyn Foo<Item = Ty>
326 /// <Self as Foo>::Bar: Copy,
331 /// impl Baz for dyn Foo<Item = Ty> {}
334 /// However, in order to make such impls well-formed, we need to do an
335 /// additional step of eagerly folding the associated types in the where
336 /// clauses of the impl. In this example, that means replacing
337 /// `<Self as Foo>::Bar` with `Ty` in the first impl.
339 // FIXME: This is only necessary as `<Self as Trait>::Assoc: ItemBound`
340 // bounds in impls are trivially proven using the item bound candidates.
341 // This is unsound in general and once that is fixed, we don't need to
342 // normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9
344 pub(in crate::solve
) fn predicates_for_object_candidate
<'tcx
>(
345 ecx
: &EvalCtxt
<'_
, 'tcx
>,
346 param_env
: ty
::ParamEnv
<'tcx
>,
347 trait_ref
: ty
::TraitRef
<'tcx
>,
348 object_bound
: &'tcx ty
::List
<ty
::PolyExistentialPredicate
<'tcx
>>,
349 ) -> Vec
<ty
::Predicate
<'tcx
>> {
351 let mut requirements
= vec
![];
353 tcx
.super_predicates_of(trait_ref
.def_id
).instantiate(tcx
, trait_ref
.substs
).predicates
,
355 for item
in tcx
.associated_items(trait_ref
.def_id
).in_definition_order() {
356 // FIXME(associated_const_equality): Also add associated consts to
357 // the requirements here.
358 if item
.kind
== ty
::AssocKind
::Type
{
359 requirements
.extend(tcx
.item_bounds(item
.def_id
).subst(tcx
, trait_ref
.substs
));
363 let mut replace_projection_with
= FxHashMap
::default();
364 for bound
in object_bound
{
365 if let ty
::ExistentialPredicate
::Projection(proj
) = bound
.skip_binder() {
366 let proj
= proj
.with_self_ty(tcx
, trait_ref
.self_ty());
367 let old_ty
= replace_projection_with
.insert(proj
.def_id(), bound
.rebind(proj
));
371 "{} has two substitutions: {} and {}",
379 requirements
.fold_with(&mut ReplaceProjectionWith
{
382 mapping
: replace_projection_with
,
386 struct ReplaceProjectionWith
<'a
, 'tcx
> {
387 ecx
: &'a EvalCtxt
<'a
, 'tcx
>,
388 param_env
: ty
::ParamEnv
<'tcx
>,
389 mapping
: FxHashMap
<DefId
, ty
::PolyProjectionPredicate
<'tcx
>>,
392 impl<'tcx
> TypeFolder
<TyCtxt
<'tcx
>> for ReplaceProjectionWith
<'_
, 'tcx
> {
393 fn interner(&self) -> TyCtxt
<'tcx
> {
397 fn fold_ty(&mut self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
398 if let ty
::Alias(ty
::Projection
, alias_ty
) = *ty
.kind()
399 && let Some(replacement
) = self.mapping
.get(&alias_ty
.def_id
)
401 // We may have a case where our object type's projection bound is higher-ranked,
402 // but the where clauses we instantiated are not. We can solve this by instantiating
403 // the binder at the usage site.
404 let proj
= self.ecx
.instantiate_binder_with_infer(*replacement
);
405 // FIXME: Technically this folder could be fallible?
408 .eq_and_get_goals(self.param_env
, alias_ty
, proj
.projection_ty
)
409 .expect("expected to be able to unify goal projection with dyn's projection");
410 // FIXME: Technically we could register these too..
411 assert
!(nested
.is_empty(), "did not expect unification to have any nested goals");
412 proj
.term
.ty().unwrap()
414 ty
.super_fold_with(self)