2023-07-23 12:30:52 -07:00
|
|
|
//! Code which is used by built-in goals that match "structurally", such a auto
|
|
|
|
//! traits, `Copy`/`Clone`.
|
2023-02-22 01:11:57 +00:00
|
|
|
use rustc_data_structures::fx::FxHashMap;
|
2023-02-22 01:26:01 +00:00
|
|
|
use rustc_hir::{def_id::DefId, Movability, Mutability};
|
2023-02-16 02:28:10 +00:00
|
|
|
use rustc_infer::traits::query::NoSolution;
|
2023-07-26 22:29:52 +00:00
|
|
|
use rustc_middle::traits::solve::Goal;
|
2023-03-30 03:51:27 +00:00
|
|
|
use rustc_middle::ty::{
|
|
|
|
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
|
|
|
};
|
2023-01-18 14:56:44 +00:00
|
|
|
|
2023-02-16 02:28:10 +00:00
|
|
|
use crate::solve::EvalCtxt;
|
|
|
|
|
2023-01-18 14:56:44 +00:00
|
|
|
// Calculates the constituent types of a type for `auto trait` purposes.
|
|
|
|
//
|
|
|
|
// For types with an "existential" binder, i.e. generator witnesses, we also
|
|
|
|
// instantiate the binder with placeholders eagerly.
|
2023-03-30 11:49:06 +02:00
|
|
|
pub(in crate::solve) fn instantiate_constituent_tys_for_auto_trait<'tcx>(
|
2023-02-16 02:28:10 +00:00
|
|
|
ecx: &EvalCtxt<'_, 'tcx>,
|
2023-01-18 14:56:44 +00:00
|
|
|
ty: Ty<'tcx>,
|
|
|
|
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
2023-02-16 02:28:10 +00:00
|
|
|
let tcx = ecx.tcx();
|
2023-01-18 14:56:44 +00:00
|
|
|
match *ty.kind() {
|
|
|
|
ty::Uint(_)
|
|
|
|
| ty::Int(_)
|
|
|
|
| ty::Bool
|
|
|
|
| ty::Float(_)
|
|
|
|
| ty::FnDef(..)
|
|
|
|
| ty::FnPtr(_)
|
|
|
|
| ty::Error(_)
|
|
|
|
| ty::Never
|
|
|
|
| ty::Char => Ok(vec![]),
|
|
|
|
|
2023-04-03 23:24:47 +00:00
|
|
|
// Treat `str` like it's defined as `struct str([u8]);`
|
2023-07-05 20:13:26 +01:00
|
|
|
ty::Str => Ok(vec![Ty::new_slice(tcx, tcx.types.u8)]),
|
2023-02-11 23:01:22 +00:00
|
|
|
|
2023-01-25 00:38:34 +00:00
|
|
|
ty::Dynamic(..)
|
2023-01-18 14:56:44 +00:00
|
|
|
| ty::Param(..)
|
|
|
|
| ty::Foreign(..)
|
2023-03-07 12:03:11 +00:00
|
|
|
| ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
|
2023-04-03 23:24:47 +00:00
|
|
|
| ty::Placeholder(..)
|
|
|
|
| ty::Bound(..)
|
|
|
|
| ty::Infer(_) => {
|
2023-01-25 00:38:34 +00:00
|
|
|
bug!("unexpected type `{ty}`")
|
|
|
|
}
|
2023-01-18 14:56:44 +00:00
|
|
|
|
|
|
|
ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => {
|
|
|
|
Ok(vec![element_ty])
|
|
|
|
}
|
|
|
|
|
|
|
|
ty::Array(element_ty, _) | ty::Slice(element_ty) => Ok(vec![element_ty]),
|
|
|
|
|
|
|
|
ty::Tuple(ref tys) => {
|
|
|
|
// (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
|
|
|
|
Ok(tys.iter().collect())
|
|
|
|
}
|
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::Closure(_, ref args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
|
2023-01-18 14:56:44 +00:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::Generator(_, ref args, _) => {
|
|
|
|
let generator_args = args.as_generator();
|
|
|
|
Ok(vec![generator_args.tupled_upvars_ty(), generator_args.witness()])
|
2023-01-18 14:56:44 +00:00
|
|
|
}
|
|
|
|
|
2023-08-03 13:47:04 +00:00
|
|
|
ty::GeneratorWitness(def_id, args) => Ok(ecx
|
2023-03-30 03:51:27 +00:00
|
|
|
.tcx()
|
|
|
|
.generator_hidden_types(def_id)
|
|
|
|
.map(|bty| {
|
|
|
|
ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
|
|
|
|
tcx,
|
2023-07-11 22:35:29 +01:00
|
|
|
bty.instantiate(tcx, args),
|
2023-03-30 03:51:27 +00:00
|
|
|
))
|
|
|
|
})
|
|
|
|
.collect()),
|
2022-10-01 14:56:24 +02:00
|
|
|
|
2023-01-18 14:56:44 +00:00
|
|
|
// For `PhantomData<T>`, we pass `T`.
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::Adt(def, args) if def.is_phantom_data() => Ok(vec![args.type_at(0)]),
|
2023-01-18 14:56:44 +00:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::Adt(def, args) => Ok(def.all_fields().map(|f| f.ty(tcx, args)).collect()),
|
2023-01-18 14:56:44 +00:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => {
|
2023-01-18 14:56:44 +00:00
|
|
|
// We can resolve the `impl Trait` to its concrete type,
|
|
|
|
// which enforces a DAG between the functions requiring
|
|
|
|
// the auto trait bounds in question.
|
2023-07-11 22:35:29 +01:00
|
|
|
Ok(vec![tcx.type_of(def_id).instantiate(tcx, args)])
|
2023-01-18 14:56:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-30 11:49:06 +02:00
|
|
|
pub(in crate::solve) fn replace_erased_lifetimes_with_bound_vars<'tcx>(
|
2023-03-30 03:51:27 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
) -> ty::Binder<'tcx, Ty<'tcx>> {
|
|
|
|
debug_assert!(!ty.has_late_bound_regions());
|
|
|
|
let mut counter = 0;
|
2023-04-26 10:14:16 +10:00
|
|
|
let ty = tcx.fold_regions(ty, |r, current_depth| match r.kind() {
|
|
|
|
ty::ReErased => {
|
2023-08-03 15:56:56 +00:00
|
|
|
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon };
|
2023-03-30 03:51:27 +00:00
|
|
|
counter += 1;
|
2023-05-29 17:54:53 +00:00
|
|
|
ty::Region::new_late_bound(tcx, current_depth, br)
|
2023-03-30 03:51:27 +00:00
|
|
|
}
|
2023-04-26 10:14:16 +10:00
|
|
|
// All free regions should be erased here.
|
|
|
|
r => bug!("unexpected region: {r:?}"),
|
2023-03-30 03:51:27 +00:00
|
|
|
});
|
|
|
|
let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
|
2023-08-03 15:56:56 +00:00
|
|
|
(0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon)),
|
2023-03-30 03:51:27 +00:00
|
|
|
);
|
|
|
|
ty::Binder::bind_with_vars(ty, bound_vars)
|
|
|
|
}
|
|
|
|
|
2023-03-30 11:49:06 +02:00
|
|
|
pub(in crate::solve) fn instantiate_constituent_tys_for_sized_trait<'tcx>(
|
2023-02-16 02:28:10 +00:00
|
|
|
ecx: &EvalCtxt<'_, 'tcx>,
|
2023-01-18 14:56:44 +00:00
|
|
|
ty: Ty<'tcx>,
|
|
|
|
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
|
|
|
match *ty.kind() {
|
|
|
|
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
|
|
|
| ty::Uint(_)
|
|
|
|
| ty::Int(_)
|
|
|
|
| ty::Bool
|
|
|
|
| ty::Float(_)
|
|
|
|
| ty::FnDef(..)
|
|
|
|
| ty::FnPtr(_)
|
|
|
|
| ty::RawPtr(..)
|
|
|
|
| ty::Char
|
|
|
|
| ty::Ref(..)
|
|
|
|
| ty::Generator(..)
|
|
|
|
| ty::GeneratorWitness(..)
|
|
|
|
| ty::Array(..)
|
|
|
|
| ty::Closure(..)
|
|
|
|
| ty::Never
|
|
|
|
| ty::Dynamic(_, _, ty::DynStar)
|
|
|
|
| ty::Error(_) => Ok(vec![]),
|
|
|
|
|
|
|
|
ty::Str
|
|
|
|
| ty::Slice(_)
|
|
|
|
| ty::Dynamic(..)
|
|
|
|
| ty::Foreign(..)
|
|
|
|
| ty::Alias(..)
|
2023-01-19 15:24:00 +00:00
|
|
|
| ty::Param(_)
|
2023-01-25 00:38:34 +00:00
|
|
|
| ty::Placeholder(..) => Err(NoSolution),
|
2023-01-18 14:56:44 +00:00
|
|
|
|
2023-01-25 00:38:34 +00:00
|
|
|
ty::Bound(..)
|
|
|
|
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
|
|
|
bug!("unexpected type `{ty}`")
|
|
|
|
}
|
2023-01-18 14:56:44 +00:00
|
|
|
|
|
|
|
ty::Tuple(tys) => Ok(tys.to_vec()),
|
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::Adt(def, args) => {
|
2023-02-16 02:28:10 +00:00
|
|
|
let sized_crit = def.sized_constraint(ecx.tcx());
|
2023-08-01 00:52:16 +00:00
|
|
|
Ok(sized_crit.iter_instantiated(ecx.tcx(), args).collect())
|
2023-01-18 14:56:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-30 11:49:06 +02:00
|
|
|
pub(in crate::solve) fn instantiate_constituent_tys_for_copy_clone_trait<'tcx>(
|
2023-02-16 02:28:10 +00:00
|
|
|
ecx: &EvalCtxt<'_, 'tcx>,
|
2023-01-18 14:56:44 +00:00
|
|
|
ty: Ty<'tcx>,
|
|
|
|
) -> Result<Vec<Ty<'tcx>>, NoSolution> {
|
|
|
|
match *ty.kind() {
|
2023-08-11 19:08:11 +02:00
|
|
|
ty::FnDef(..) | ty::FnPtr(_) | ty::Error(_) => Ok(vec![]),
|
2023-01-18 14:56:44 +00:00
|
|
|
|
|
|
|
// Implementations are provided in core
|
|
|
|
ty::Uint(_)
|
|
|
|
| ty::Int(_)
|
2023-08-11 19:08:11 +02:00
|
|
|
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
2023-01-18 14:56:44 +00:00
|
|
|
| ty::Bool
|
|
|
|
| ty::Float(_)
|
|
|
|
| ty::Char
|
|
|
|
| ty::RawPtr(..)
|
|
|
|
| ty::Never
|
|
|
|
| ty::Ref(_, _, Mutability::Not)
|
|
|
|
| ty::Array(..) => Err(NoSolution),
|
|
|
|
|
|
|
|
ty::Dynamic(..)
|
|
|
|
| ty::Str
|
|
|
|
| ty::Slice(_)
|
|
|
|
| ty::Generator(_, _, Movability::Static)
|
|
|
|
| ty::Foreign(..)
|
|
|
|
| ty::Ref(_, _, Mutability::Mut)
|
|
|
|
| ty::Adt(_, _)
|
|
|
|
| ty::Alias(_, _)
|
2023-01-19 15:24:00 +00:00
|
|
|
| ty::Param(_)
|
2023-01-25 00:38:34 +00:00
|
|
|
| ty::Placeholder(..) => Err(NoSolution),
|
2023-01-18 14:56:44 +00:00
|
|
|
|
2023-01-25 00:38:34 +00:00
|
|
|
ty::Bound(..)
|
|
|
|
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
|
|
|
bug!("unexpected type `{ty}`")
|
|
|
|
}
|
2023-01-18 14:56:44 +00:00
|
|
|
|
|
|
|
ty::Tuple(tys) => Ok(tys.to_vec()),
|
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::Closure(_, args) => Ok(vec![args.as_closure().tupled_upvars_ty()]),
|
2023-01-18 14:56:44 +00:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::Generator(_, args, Movability::Movable) => {
|
2023-02-16 02:28:10 +00:00
|
|
|
if ecx.tcx().features().generator_clone {
|
2023-07-11 22:35:29 +01:00
|
|
|
let generator = args.as_generator();
|
2023-01-18 14:56:44 +00:00
|
|
|
Ok(vec![generator.tupled_upvars_ty(), generator.witness()])
|
|
|
|
} else {
|
|
|
|
Err(NoSolution)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-03 13:47:04 +00:00
|
|
|
ty::GeneratorWitness(def_id, args) => Ok(ecx
|
2023-03-30 03:51:27 +00:00
|
|
|
.tcx()
|
|
|
|
.generator_hidden_types(def_id)
|
|
|
|
.map(|bty| {
|
|
|
|
ecx.instantiate_binder_with_placeholders(replace_erased_lifetimes_with_bound_vars(
|
|
|
|
ecx.tcx(),
|
2023-07-11 22:35:29 +01:00
|
|
|
bty.instantiate(ecx.tcx(), args),
|
2023-03-30 03:51:27 +00:00
|
|
|
))
|
|
|
|
})
|
|
|
|
.collect()),
|
2023-01-18 14:56:44 +00:00
|
|
|
}
|
|
|
|
}
|
2023-01-19 01:20:34 +00:00
|
|
|
|
2023-01-24 23:38:20 +00:00
|
|
|
// Returns a binder of the tupled inputs types and output type from a builtin callable type.
|
2023-03-30 11:49:06 +02:00
|
|
|
pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable<'tcx>(
|
2023-01-19 01:20:34 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
self_ty: Ty<'tcx>,
|
|
|
|
goal_kind: ty::ClosureKind,
|
|
|
|
) -> Result<Option<ty::Binder<'tcx, (Ty<'tcx>, Ty<'tcx>)>>, NoSolution> {
|
|
|
|
match *self_ty.kind() {
|
2023-03-21 11:44:36 +00:00
|
|
|
// keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::FnDef(def_id, args) => {
|
2023-03-21 11:44:36 +00:00
|
|
|
let sig = tcx.fn_sig(def_id);
|
|
|
|
if sig.skip_binder().is_fn_trait_compatible()
|
|
|
|
&& tcx.codegen_fn_attrs(def_id).target_features.is_empty()
|
|
|
|
{
|
|
|
|
Ok(Some(
|
2023-07-11 22:35:29 +01:00
|
|
|
sig.instantiate(tcx, args)
|
2023-07-05 20:13:26 +01:00
|
|
|
.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs()), sig.output())),
|
2023-03-21 11:44:36 +00:00
|
|
|
))
|
|
|
|
} else {
|
|
|
|
Err(NoSolution)
|
|
|
|
}
|
|
|
|
}
|
2023-03-21 11:11:32 +00:00
|
|
|
// keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
|
|
|
|
ty::FnPtr(sig) => {
|
2023-03-21 11:38:13 +00:00
|
|
|
if sig.is_fn_trait_compatible() {
|
2023-07-05 20:13:26 +01:00
|
|
|
Ok(Some(sig.map_bound(|sig| (Ty::new_tup(tcx, sig.inputs()), sig.output()))))
|
2023-03-21 11:11:32 +00:00
|
|
|
} else {
|
|
|
|
Err(NoSolution)
|
|
|
|
}
|
|
|
|
}
|
2023-07-11 22:35:29 +01:00
|
|
|
ty::Closure(_, args) => {
|
|
|
|
let closure_args = args.as_closure();
|
|
|
|
match closure_args.kind_ty().to_opt_closure_kind() {
|
2023-03-29 23:36:27 +00:00
|
|
|
// If the closure's kind doesn't extend the goal kind,
|
|
|
|
// then the closure doesn't implement the trait.
|
|
|
|
Some(closure_kind) => {
|
|
|
|
if !closure_kind.extends(goal_kind) {
|
|
|
|
return Err(NoSolution);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Closure kind is not yet determined, so we return ambiguity unless
|
|
|
|
// the expected kind is `FnOnce` as that is always implemented.
|
|
|
|
None => {
|
|
|
|
if goal_kind != ty::ClosureKind::FnOnce {
|
|
|
|
return Ok(None);
|
|
|
|
}
|
|
|
|
}
|
2023-01-19 01:20:34 +00:00
|
|
|
}
|
2023-07-11 22:35:29 +01:00
|
|
|
Ok(Some(closure_args.sig().map_bound(|sig| (sig.inputs()[0], sig.output()))))
|
2023-01-19 01:20:34 +00:00
|
|
|
}
|
|
|
|
ty::Bool
|
|
|
|
| ty::Char
|
|
|
|
| ty::Int(_)
|
|
|
|
| ty::Uint(_)
|
|
|
|
| ty::Float(_)
|
|
|
|
| ty::Adt(_, _)
|
|
|
|
| ty::Foreign(_)
|
|
|
|
| ty::Str
|
|
|
|
| ty::Array(_, _)
|
|
|
|
| ty::Slice(_)
|
|
|
|
| ty::RawPtr(_)
|
|
|
|
| ty::Ref(_, _, _)
|
|
|
|
| ty::Dynamic(_, _, _)
|
|
|
|
| ty::Generator(_, _, _)
|
2023-08-03 13:47:04 +00:00
|
|
|
| ty::GeneratorWitness(..)
|
2023-01-19 01:20:34 +00:00
|
|
|
| ty::Never
|
|
|
|
| ty::Tuple(_)
|
|
|
|
| ty::Alias(_, _)
|
|
|
|
| ty::Param(_)
|
2023-01-25 00:38:34 +00:00
|
|
|
| ty::Placeholder(..)
|
|
|
|
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
2023-01-19 01:20:34 +00:00
|
|
|
| ty::Error(_) => Err(NoSolution),
|
2023-01-25 00:38:34 +00:00
|
|
|
|
|
|
|
ty::Bound(..)
|
|
|
|
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
|
|
|
bug!("unexpected type `{self_ty}`")
|
|
|
|
}
|
2023-01-19 01:20:34 +00:00
|
|
|
}
|
|
|
|
}
|
2023-02-22 01:11:57 +00:00
|
|
|
|
2023-02-22 01:39:41 +00:00
|
|
|
/// Assemble a list of predicates that would be present on a theoretical
|
|
|
|
/// user impl for an object type. These predicates must be checked any time
|
|
|
|
/// we assemble a built-in object candidate for an object type, since they
|
|
|
|
/// are not implied by the well-formedness of the type.
|
|
|
|
///
|
|
|
|
/// For example, given the following traits:
|
|
|
|
///
|
|
|
|
/// ```rust,ignore (theoretical code)
|
|
|
|
/// trait Foo: Baz {
|
|
|
|
/// type Bar: Copy;
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// trait Baz {}
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// For the dyn type `dyn Foo<Item = Ty>`, we can imagine there being a
|
|
|
|
/// pair of theoretical impls:
|
|
|
|
///
|
|
|
|
/// ```rust,ignore (theoretical code)
|
|
|
|
/// impl Foo for dyn Foo<Item = Ty>
|
|
|
|
/// where
|
|
|
|
/// Self: Baz,
|
|
|
|
/// <Self as Foo>::Bar: Copy,
|
|
|
|
/// {
|
|
|
|
/// type Bar = Ty;
|
|
|
|
/// }
|
|
|
|
///
|
|
|
|
/// impl Baz for dyn Foo<Item = Ty> {}
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// However, in order to make such impls well-formed, we need to do an
|
|
|
|
/// additional step of eagerly folding the associated types in the where
|
|
|
|
/// clauses of the impl. In this example, that means replacing
|
|
|
|
/// `<Self as Foo>::Bar` with `Ty` in the first impl.
|
2023-03-30 11:49:06 +02:00
|
|
|
///
|
|
|
|
// FIXME: This is only necessary as `<Self as Trait>::Assoc: ItemBound`
|
|
|
|
// bounds in impls are trivially proven using the item bound candidates.
|
|
|
|
// This is unsound in general and once that is fixed, we don't need to
|
|
|
|
// normalize eagerly here. See https://github.com/lcnr/solver-woes/issues/9
|
|
|
|
// for more details.
|
|
|
|
pub(in crate::solve) fn predicates_for_object_candidate<'tcx>(
|
2023-02-22 01:26:01 +00:00
|
|
|
ecx: &EvalCtxt<'_, 'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2023-02-22 01:11:57 +00:00
|
|
|
trait_ref: ty::TraitRef<'tcx>,
|
|
|
|
object_bound: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
2023-07-26 22:29:52 +00:00
|
|
|
) -> Vec<Goal<'tcx, ty::Predicate<'tcx>>> {
|
2023-02-22 01:26:01 +00:00
|
|
|
let tcx = ecx.tcx();
|
2023-02-22 01:11:57 +00:00
|
|
|
let mut requirements = vec![];
|
|
|
|
requirements.extend(
|
2023-07-11 22:35:29 +01:00
|
|
|
tcx.super_predicates_of(trait_ref.def_id).instantiate(tcx, trait_ref.args).predicates,
|
2023-02-22 01:11:57 +00:00
|
|
|
);
|
|
|
|
for item in tcx.associated_items(trait_ref.def_id).in_definition_order() {
|
2023-02-22 01:39:41 +00:00
|
|
|
// FIXME(associated_const_equality): Also add associated consts to
|
|
|
|
// the requirements here.
|
2023-02-22 01:11:57 +00:00
|
|
|
if item.kind == ty::AssocKind::Type {
|
2023-09-02 05:06:21 +00:00
|
|
|
// associated types that require `Self: Sized` do not show up in the built-in
|
|
|
|
// implementation of `Trait for dyn Trait`, and can be dropped here.
|
|
|
|
if tcx.generics_require_sized_self(item.def_id) {
|
2023-09-02 04:33:58 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-07-17 17:49:47 +00:00
|
|
|
requirements
|
|
|
|
.extend(tcx.item_bounds(item.def_id).iter_instantiated(tcx, trait_ref.args));
|
2023-02-22 01:11:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut replace_projection_with = FxHashMap::default();
|
|
|
|
for bound in object_bound {
|
2023-02-22 01:26:01 +00:00
|
|
|
if let ty::ExistentialPredicate::Projection(proj) = bound.skip_binder() {
|
2023-02-22 01:11:57 +00:00
|
|
|
let proj = proj.with_self_ty(tcx, trait_ref.self_ty());
|
2023-02-22 01:26:01 +00:00
|
|
|
let old_ty = replace_projection_with.insert(proj.def_id(), bound.rebind(proj));
|
2023-02-22 01:11:57 +00:00
|
|
|
assert_eq!(
|
|
|
|
old_ty,
|
|
|
|
None,
|
|
|
|
"{} has two substitutions: {} and {}",
|
|
|
|
proj.projection_ty,
|
|
|
|
proj.term,
|
|
|
|
old_ty.unwrap()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-26 22:29:52 +00:00
|
|
|
let mut folder =
|
|
|
|
ReplaceProjectionWith { ecx, param_env, mapping: replace_projection_with, nested: vec![] };
|
|
|
|
let folded_requirements = requirements.fold_with(&mut folder);
|
|
|
|
|
|
|
|
folder
|
|
|
|
.nested
|
|
|
|
.into_iter()
|
|
|
|
.chain(folded_requirements.into_iter().map(|clause| Goal::new(tcx, param_env, clause)))
|
|
|
|
.collect()
|
2023-02-22 01:11:57 +00:00
|
|
|
}
|
|
|
|
|
2023-02-22 01:26:01 +00:00
|
|
|
struct ReplaceProjectionWith<'a, 'tcx> {
|
|
|
|
ecx: &'a EvalCtxt<'a, 'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
|
|
|
mapping: FxHashMap<DefId, ty::PolyProjectionPredicate<'tcx>>,
|
2023-07-26 22:29:52 +00:00
|
|
|
nested: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
|
2023-02-22 01:11:57 +00:00
|
|
|
}
|
|
|
|
|
2023-02-22 01:26:01 +00:00
|
|
|
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceProjectionWith<'_, 'tcx> {
|
2023-02-22 01:11:57 +00:00
|
|
|
fn interner(&self) -> TyCtxt<'tcx> {
|
2023-02-22 01:26:01 +00:00
|
|
|
self.ecx.tcx()
|
2023-02-22 01:11:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
|
|
|
if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
|
2023-02-22 01:26:01 +00:00
|
|
|
&& let Some(replacement) = self.mapping.get(&alias_ty.def_id)
|
2023-02-22 01:11:57 +00:00
|
|
|
{
|
2023-02-22 01:39:41 +00:00
|
|
|
// We may have a case where our object type's projection bound is higher-ranked,
|
|
|
|
// but the where clauses we instantiated are not. We can solve this by instantiating
|
|
|
|
// the binder at the usage site.
|
2023-02-22 01:26:01 +00:00
|
|
|
let proj = self.ecx.instantiate_binder_with_infer(*replacement);
|
2023-07-26 22:29:52 +00:00
|
|
|
// FIXME: Technically this equate could be fallible...
|
|
|
|
self.nested.extend(
|
|
|
|
self.ecx
|
|
|
|
.eq_and_get_goals(self.param_env, alias_ty, proj.projection_ty)
|
|
|
|
.expect("expected to be able to unify goal projection with dyn's projection"),
|
|
|
|
);
|
2023-02-22 01:26:01 +00:00
|
|
|
proj.term.ty().unwrap()
|
2023-02-22 01:11:57 +00:00
|
|
|
} else {
|
|
|
|
ty.super_fold_with(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|