Instantiate binder for Copy/Clone/Sized eagerly
This commit is contained in:
@@ -19,7 +19,7 @@ use rustc_middle::{bug, span_bug};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use super::SelectionCandidate::*;
|
||||
use super::{BuiltinImplConditions, SelectionCandidateSet, SelectionContext, TraitObligationStack};
|
||||
use super::{SelectionCandidateSet, SelectionContext, TraitObligationStack};
|
||||
use crate::traits::util;
|
||||
|
||||
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
@@ -75,8 +75,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
self.assemble_candidates_from_impls(obligation, &mut candidates);
|
||||
|
||||
// For other types, we'll use the builtin rules.
|
||||
let copy_conditions = self.copy_clone_conditions(obligation);
|
||||
self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates);
|
||||
self.assemble_builtin_copy_clone_candidate(
|
||||
obligation.predicate.self_ty().skip_binder(),
|
||||
&mut candidates,
|
||||
);
|
||||
}
|
||||
Some(LangItem::DiscriminantKind) => {
|
||||
// `DiscriminantKind` is automatically implemented for every type.
|
||||
@@ -88,14 +90,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
Some(LangItem::Sized) => {
|
||||
self.assemble_builtin_sized_candidate(
|
||||
obligation,
|
||||
obligation.predicate.self_ty().skip_binder(),
|
||||
&mut candidates,
|
||||
SizedTraitKind::Sized,
|
||||
);
|
||||
}
|
||||
Some(LangItem::MetaSized) => {
|
||||
self.assemble_builtin_sized_candidate(
|
||||
obligation,
|
||||
obligation.predicate.self_ty().skip_binder(),
|
||||
&mut candidates,
|
||||
SizedTraitKind::MetaSized,
|
||||
);
|
||||
@@ -357,14 +359,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
candidates: &mut SelectionCandidateSet<'tcx>,
|
||||
) {
|
||||
let self_ty = obligation.self_ty().skip_binder();
|
||||
// gen constructs get lowered to a special kind of coroutine that
|
||||
// should directly `impl FusedIterator`.
|
||||
if let ty::Coroutine(did, ..) = self_ty.kind()
|
||||
&& self.tcx().coroutine_is_gen(*did)
|
||||
{
|
||||
debug!(?self_ty, ?obligation, "assemble_fused_iterator_candidates",);
|
||||
|
||||
if self.coroutine_is_gen(obligation.self_ty().skip_binder()) {
|
||||
candidates.vec.push(BuiltinCandidate);
|
||||
}
|
||||
}
|
||||
@@ -1113,41 +1108,164 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Assembles the `Sized` and `MetaSized` traits which are built-in to the language itself.
|
||||
/// Assembles `Copy` and `Clone` candidates for built-in types with no libcore-defined
|
||||
/// `Copy` or `Clone` impls.
|
||||
#[instrument(level = "debug", skip(self, candidates))]
|
||||
fn assemble_builtin_sized_candidate(
|
||||
fn assemble_builtin_copy_clone_candidate(
|
||||
&mut self,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
candidates: &mut SelectionCandidateSet<'tcx>,
|
||||
sizedness: SizedTraitKind,
|
||||
) {
|
||||
match self.sizedness_conditions(obligation, sizedness) {
|
||||
BuiltinImplConditions::Where(_nested) => {
|
||||
candidates.vec.push(SizedCandidate);
|
||||
match *self_ty.kind() {
|
||||
// These impls are built-in because we cannot express sufficiently
|
||||
// generic impls in libcore.
|
||||
ty::FnDef(..)
|
||||
| ty::FnPtr(..)
|
||||
| ty::Error(_)
|
||||
| ty::Tuple(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Pat(..) => {
|
||||
candidates.vec.push(BuiltinCandidate);
|
||||
}
|
||||
BuiltinImplConditions::None => {}
|
||||
BuiltinImplConditions::Ambiguous => {
|
||||
|
||||
// Implementations provided in libcore.
|
||||
ty::Uint(_)
|
||||
| ty::Int(_)
|
||||
| ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Bool
|
||||
| ty::Float(_)
|
||||
| ty::Char
|
||||
| ty::RawPtr(..)
|
||||
| ty::Never
|
||||
| ty::Ref(_, _, hir::Mutability::Not)
|
||||
| ty::Array(..) => {}
|
||||
|
||||
// FIXME(unsafe_binder): Should we conditionally
|
||||
// (i.e. universally) implement copy/clone?
|
||||
ty::UnsafeBinder(_) => {}
|
||||
|
||||
// Not `Sized`, which is a supertrait of `Copy`/`Clone`.
|
||||
ty::Dynamic(..) | ty::Str | ty::Slice(..) | ty::Foreign(..) => {}
|
||||
|
||||
// Not `Copy` or `Clone` by design.
|
||||
ty::Ref(_, _, hir::Mutability::Mut) => {}
|
||||
|
||||
ty::Coroutine(coroutine_def_id, args) => {
|
||||
match self.tcx().coroutine_movability(coroutine_def_id) {
|
||||
hir::Movability::Static => {}
|
||||
hir::Movability::Movable => {
|
||||
if self.tcx().features().coroutine_clone() {
|
||||
let resolved_upvars =
|
||||
self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
|
||||
let resolved_witness =
|
||||
self.infcx.shallow_resolve(args.as_coroutine().witness());
|
||||
if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() {
|
||||
// Not yet resolved.
|
||||
candidates.ambiguous = true;
|
||||
} else {
|
||||
candidates.vec.push(BuiltinCandidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::Closure(_, args) => {
|
||||
let resolved_upvars =
|
||||
self.infcx.shallow_resolve(args.as_closure().tupled_upvars_ty());
|
||||
if resolved_upvars.is_ty_var() {
|
||||
// Not yet resolved.
|
||||
candidates.ambiguous = true;
|
||||
} else {
|
||||
candidates.vec.push(BuiltinCandidate);
|
||||
}
|
||||
}
|
||||
|
||||
ty::CoroutineClosure(_, args) => {
|
||||
let resolved_upvars =
|
||||
self.infcx.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty());
|
||||
if resolved_upvars.is_ty_var() {
|
||||
// Not yet resolved.
|
||||
candidates.ambiguous = true;
|
||||
} else {
|
||||
candidates.vec.push(BuiltinCandidate);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to whatever user-defined impls or param-env clauses exist in this case.
|
||||
ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => {}
|
||||
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
candidates.ambiguous = true;
|
||||
}
|
||||
|
||||
// Only appears when assembling higher-ranked `for<T> T: Clone`.
|
||||
ty::Bound(..) => {}
|
||||
|
||||
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Assembles the trait which are built-in to the language itself:
|
||||
/// e.g. `Copy` and `Clone`.
|
||||
/// Assembles the `Sized` and `MetaSized` traits which are built-in to the language itself.
|
||||
#[instrument(level = "debug", skip(self, candidates))]
|
||||
fn assemble_builtin_bound_candidates(
|
||||
fn assemble_builtin_sized_candidate(
|
||||
&mut self,
|
||||
conditions: BuiltinImplConditions<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
candidates: &mut SelectionCandidateSet<'tcx>,
|
||||
sizedness: SizedTraitKind,
|
||||
) {
|
||||
match conditions {
|
||||
BuiltinImplConditions::Where(_) => {
|
||||
candidates.vec.push(BuiltinCandidate);
|
||||
match *self_ty.kind() {
|
||||
// Always sized.
|
||||
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::Coroutine(..)
|
||||
| ty::CoroutineWitness(..)
|
||||
| ty::Array(..)
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Never
|
||||
| ty::Error(_) => {
|
||||
candidates.vec.push(SizedCandidate);
|
||||
}
|
||||
BuiltinImplConditions::None => {}
|
||||
BuiltinImplConditions::Ambiguous => {
|
||||
|
||||
// Conditionally `Sized`.
|
||||
ty::Tuple(..) | ty::Pat(..) | ty::Adt(..) | ty::UnsafeBinder(_) => {
|
||||
candidates.vec.push(SizedCandidate);
|
||||
}
|
||||
|
||||
// `MetaSized` but not `Sized`.
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
|
||||
SizedTraitKind::Sized => {}
|
||||
SizedTraitKind::MetaSized => {
|
||||
candidates.vec.push(SizedCandidate);
|
||||
}
|
||||
},
|
||||
|
||||
// Not `MetaSized` or `Sized`.
|
||||
ty::Foreign(..) => {}
|
||||
|
||||
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => {}
|
||||
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
candidates.ambiguous = true;
|
||||
}
|
||||
|
||||
// Only appears when assembling higher-ranked `for<T> T: Sized`.
|
||||
ty::Bound(..) => {}
|
||||
|
||||
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ use thin_vec::thin_vec;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use super::SelectionCandidate::{self, *};
|
||||
use super::{BuiltinImplConditions, PredicateObligations, SelectionContext};
|
||||
use super::{PredicateObligations, SelectionContext};
|
||||
use crate::traits::normalize::{normalize_with_depth, normalize_with_depth_to};
|
||||
use crate::traits::util::{self, closure_trait_ref_and_return_type};
|
||||
use crate::traits::{
|
||||
@@ -257,16 +257,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
debug!(?obligation, "confirm_builtin_candidate");
|
||||
let tcx = self.tcx();
|
||||
let trait_def = obligation.predicate.def_id();
|
||||
let conditions = match tcx.as_lang_item(trait_def) {
|
||||
Some(LangItem::Sized) => self.sizedness_conditions(obligation, SizedTraitKind::Sized),
|
||||
let self_ty = self.infcx.shallow_resolve(
|
||||
self.infcx.enter_forall_and_leak_universe(obligation.predicate.self_ty()),
|
||||
);
|
||||
let types = match tcx.as_lang_item(trait_def) {
|
||||
Some(LangItem::Sized) => self.sizedness_conditions(self_ty, SizedTraitKind::Sized),
|
||||
Some(LangItem::MetaSized) => {
|
||||
self.sizedness_conditions(obligation, SizedTraitKind::MetaSized)
|
||||
self.sizedness_conditions(self_ty, SizedTraitKind::MetaSized)
|
||||
}
|
||||
Some(LangItem::PointeeSized) => {
|
||||
bug!("`PointeeSized` is removing during lowering");
|
||||
}
|
||||
Some(LangItem::Copy | LangItem::Clone) => self.copy_clone_conditions(obligation),
|
||||
Some(LangItem::FusedIterator) => self.fused_iterator_conditions(obligation),
|
||||
Some(LangItem::Copy | LangItem::Clone) => self.copy_clone_conditions(self_ty),
|
||||
Some(LangItem::FusedIterator) => {
|
||||
if self.coroutine_is_gen(self_ty) {
|
||||
ty::Binder::dummy(vec![])
|
||||
} else {
|
||||
unreachable!("tried to assemble `FusedIterator` for non-gen coroutine");
|
||||
}
|
||||
}
|
||||
Some(
|
||||
LangItem::Destruct
|
||||
| LangItem::DiscriminantKind
|
||||
@@ -274,12 +283,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
| LangItem::PointeeTrait
|
||||
| LangItem::Tuple
|
||||
| LangItem::Unpin,
|
||||
) => BuiltinImplConditions::Where(ty::Binder::dummy(vec![])),
|
||||
) => ty::Binder::dummy(vec![]),
|
||||
other => bug!("unexpected builtin trait {trait_def:?} ({other:?})"),
|
||||
};
|
||||
let BuiltinImplConditions::Where(types) = conditions else {
|
||||
bug!("obligation {:?} had matched a builtin impl but now doesn't", obligation);
|
||||
};
|
||||
let types = self.infcx.enter_forall_and_leak_universe(types);
|
||||
|
||||
let cause = obligation.derived_cause(ObligationCauseCode::BuiltinDerived);
|
||||
|
||||
@@ -188,18 +188,6 @@ struct EvaluatedCandidate<'tcx> {
|
||||
evaluation: EvaluationResult,
|
||||
}
|
||||
|
||||
/// When does the builtin impl for `T: Trait` apply?
|
||||
#[derive(Debug)]
|
||||
enum BuiltinImplConditions<'tcx> {
|
||||
/// The impl is conditional on `T1, T2, ...: Trait`.
|
||||
Where(ty::Binder<'tcx, Vec<Ty<'tcx>>>),
|
||||
/// There is no built-in impl. There may be some other
|
||||
/// candidate (a where-clause or user-defined impl).
|
||||
None,
|
||||
/// It is unknown whether there is an impl.
|
||||
Ambiguous,
|
||||
}
|
||||
|
||||
impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> {
|
||||
SelectionContext {
|
||||
@@ -2104,14 +2092,9 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
fn sizedness_conditions(
|
||||
&mut self,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
sizedness: SizedTraitKind,
|
||||
) -> BuiltinImplConditions<'tcx> {
|
||||
use self::BuiltinImplConditions::{Ambiguous, None, Where};
|
||||
|
||||
// NOTE: binder moved to (*)
|
||||
let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
|
||||
|
||||
) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
|
||||
match self_ty.kind() {
|
||||
ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
|
||||
| ty::Uint(_)
|
||||
@@ -2129,59 +2112,44 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
| ty::Closure(..)
|
||||
| ty::CoroutineClosure(..)
|
||||
| ty::Never
|
||||
| ty::Error(_) => {
|
||||
// safe for everything
|
||||
Where(ty::Binder::dummy(Vec::new()))
|
||||
}
|
||||
| ty::Error(_) => ty::Binder::dummy(vec![]),
|
||||
|
||||
ty::Str | ty::Slice(_) | ty::Dynamic(..) => match sizedness {
|
||||
SizedTraitKind::Sized => None,
|
||||
SizedTraitKind::MetaSized => Where(ty::Binder::dummy(Vec::new())),
|
||||
SizedTraitKind::Sized => unreachable!("tried to assemble `Sized` for unsized type"),
|
||||
SizedTraitKind::MetaSized => ty::Binder::dummy(vec![]),
|
||||
},
|
||||
|
||||
ty::Foreign(..) => None,
|
||||
ty::Foreign(..) => unreachable!("tried to assemble `Sized` for unsized type"),
|
||||
|
||||
ty::Tuple(tys) => Where(
|
||||
obligation.predicate.rebind(tys.last().map_or_else(Vec::new, |&last| vec![last])),
|
||||
),
|
||||
ty::Tuple(tys) => {
|
||||
ty::Binder::dummy(tys.last().map_or_else(Vec::new, |&last| vec![last]))
|
||||
}
|
||||
|
||||
ty::Pat(ty, _) => Where(obligation.predicate.rebind(vec![*ty])),
|
||||
ty::Pat(ty, _) => ty::Binder::dummy(vec![*ty]),
|
||||
|
||||
ty::Adt(def, args) => {
|
||||
if let Some(crit) = def.sizedness_constraint(self.tcx(), sizedness) {
|
||||
// (*) binder moved here
|
||||
Where(obligation.predicate.rebind(vec![crit.instantiate(self.tcx(), args)]))
|
||||
ty::Binder::dummy(vec![crit.instantiate(self.tcx(), args)])
|
||||
} else {
|
||||
Where(ty::Binder::dummy(Vec::new()))
|
||||
ty::Binder::dummy(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(unsafe_binders): This binder needs to be squashed
|
||||
ty::UnsafeBinder(binder_ty) => Where(binder_ty.map_bound(|ty| vec![ty])),
|
||||
ty::UnsafeBinder(binder_ty) => binder_ty.map_bound(|ty| vec![ty]),
|
||||
|
||||
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => None,
|
||||
ty::Infer(ty::TyVar(_)) => Ambiguous,
|
||||
|
||||
// We can make this an ICE if/once we actually instantiate the trait obligation eagerly.
|
||||
ty::Bound(..) => None,
|
||||
|
||||
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
|
||||
ty::Alias(..)
|
||||
| ty::Param(_)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
|
||||
| ty::Bound(..) => {
|
||||
bug!("asked to assemble `Sized` of unexpected type: {:?}", self_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_clone_conditions(
|
||||
&mut self,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
) -> BuiltinImplConditions<'tcx> {
|
||||
// NOTE: binder moved to (*)
|
||||
let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
|
||||
|
||||
use self::BuiltinImplConditions::{Ambiguous, None, Where};
|
||||
|
||||
fn copy_clone_conditions(&mut self, self_ty: Ty<'tcx>) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
|
||||
match *self_ty.kind() {
|
||||
ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => Where(ty::Binder::dummy(Vec::new())),
|
||||
ty::FnDef(..) | ty::FnPtr(..) | ty::Error(_) => ty::Binder::dummy(vec![]),
|
||||
|
||||
ty::Uint(_)
|
||||
| ty::Int(_)
|
||||
@@ -2193,127 +2161,78 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
| ty::Never
|
||||
| ty::Ref(_, _, hir::Mutability::Not)
|
||||
| ty::Array(..) => {
|
||||
// Implementations provided in libcore
|
||||
None
|
||||
unreachable!("tried to assemble `Sized` for type with libcore-provided impl")
|
||||
}
|
||||
|
||||
// FIXME(unsafe_binder): Should we conditionally
|
||||
// (i.e. universally) implement copy/clone?
|
||||
ty::UnsafeBinder(_) => None,
|
||||
|
||||
ty::Dynamic(..)
|
||||
| ty::Str
|
||||
| ty::Slice(..)
|
||||
| ty::Foreign(..)
|
||||
| ty::Ref(_, _, hir::Mutability::Mut) => None,
|
||||
ty::UnsafeBinder(_) => unreachable!("tried to assemble `Sized` for unsafe binder"),
|
||||
|
||||
ty::Tuple(tys) => {
|
||||
// (*) binder moved here
|
||||
Where(obligation.predicate.rebind(tys.iter().collect()))
|
||||
ty::Binder::dummy(tys.iter().collect())
|
||||
}
|
||||
|
||||
ty::Pat(ty, _) => {
|
||||
// (*) binder moved here
|
||||
Where(obligation.predicate.rebind(vec![ty]))
|
||||
ty::Binder::dummy(vec![ty])
|
||||
}
|
||||
|
||||
ty::Coroutine(coroutine_def_id, args) => {
|
||||
match self.tcx().coroutine_movability(coroutine_def_id) {
|
||||
hir::Movability::Static => None,
|
||||
hir::Movability::Static => {
|
||||
unreachable!("tried to assemble `Sized` for static coroutine")
|
||||
}
|
||||
hir::Movability::Movable => {
|
||||
if self.tcx().features().coroutine_clone() {
|
||||
let resolved_upvars =
|
||||
self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
|
||||
let resolved_witness =
|
||||
self.infcx.shallow_resolve(args.as_coroutine().witness());
|
||||
if resolved_upvars.is_ty_var() || resolved_witness.is_ty_var() {
|
||||
// Not yet resolved.
|
||||
Ambiguous
|
||||
} else {
|
||||
let all = args
|
||||
.as_coroutine()
|
||||
ty::Binder::dummy(
|
||||
args.as_coroutine()
|
||||
.upvar_tys()
|
||||
.iter()
|
||||
.chain([args.as_coroutine().witness()])
|
||||
.collect::<Vec<_>>();
|
||||
Where(obligation.predicate.rebind(all))
|
||||
}
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
unreachable!(
|
||||
"tried to assemble `Sized` for coroutine without enabled feature"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::CoroutineWitness(def_id, args) => {
|
||||
let hidden_types = rebind_coroutine_witness_types(
|
||||
self.infcx.tcx,
|
||||
def_id,
|
||||
args,
|
||||
obligation.predicate.bound_vars(),
|
||||
);
|
||||
Where(hidden_types)
|
||||
}
|
||||
ty::CoroutineWitness(def_id, args) => self
|
||||
.infcx
|
||||
.tcx
|
||||
.coroutine_hidden_types(def_id)
|
||||
.instantiate(self.infcx.tcx, args)
|
||||
.map_bound(|witness| witness.types.to_vec()),
|
||||
|
||||
ty::Closure(_, args) => {
|
||||
// (*) binder moved here
|
||||
let ty = self.infcx.shallow_resolve(args.as_closure().tupled_upvars_ty());
|
||||
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
|
||||
// Not yet resolved.
|
||||
Ambiguous
|
||||
} else {
|
||||
Where(obligation.predicate.rebind(args.as_closure().upvar_tys().to_vec()))
|
||||
}
|
||||
}
|
||||
ty::Closure(_, args) => ty::Binder::dummy(args.as_closure().upvar_tys().to_vec()),
|
||||
|
||||
ty::CoroutineClosure(_, args) => {
|
||||
// (*) binder moved here
|
||||
let ty = self.infcx.shallow_resolve(args.as_coroutine_closure().tupled_upvars_ty());
|
||||
if let ty::Infer(ty::TyVar(_)) = ty.kind() {
|
||||
// Not yet resolved.
|
||||
Ambiguous
|
||||
} else {
|
||||
Where(
|
||||
obligation
|
||||
.predicate
|
||||
.rebind(args.as_coroutine_closure().upvar_tys().to_vec()),
|
||||
)
|
||||
}
|
||||
ty::Binder::dummy(args.as_coroutine_closure().upvar_tys().to_vec())
|
||||
}
|
||||
|
||||
ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => {
|
||||
// Fallback to whatever user-defined impls exist in this case.
|
||||
None
|
||||
}
|
||||
|
||||
ty::Infer(ty::TyVar(_)) => {
|
||||
// Unbound type variable. Might or might not have
|
||||
// applicable impls and so forth, depending on what
|
||||
// those type variables wind up being bound to.
|
||||
Ambiguous
|
||||
}
|
||||
|
||||
// We can make this an ICE if/once we actually instantiate the trait obligation eagerly.
|
||||
ty::Bound(..) => None,
|
||||
|
||||
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
ty::Foreign(..)
|
||||
| ty::Str
|
||||
| ty::Slice(_)
|
||||
| ty::Dynamic(..)
|
||||
| ty::Adt(..)
|
||||
| ty::Alias(..)
|
||||
| ty::Param(..)
|
||||
| ty::Placeholder(..)
|
||||
| ty::Bound(..)
|
||||
| ty::Ref(_, _, ty::Mutability::Mut)
|
||||
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
||||
bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn fused_iterator_conditions(
|
||||
&mut self,
|
||||
obligation: &PolyTraitObligation<'tcx>,
|
||||
) -> BuiltinImplConditions<'tcx> {
|
||||
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
|
||||
if let ty::Coroutine(did, ..) = *self_ty.kind()
|
||||
&& self.tcx().coroutine_is_gen(did)
|
||||
{
|
||||
BuiltinImplConditions::Where(ty::Binder::dummy(Vec::new()))
|
||||
} else {
|
||||
BuiltinImplConditions::None
|
||||
}
|
||||
fn coroutine_is_gen(&mut self, self_ty: Ty<'tcx>) -> bool {
|
||||
matches!(*self_ty.kind(), ty::Coroutine(did, ..)
|
||||
if self.tcx().coroutine_is_gen(did))
|
||||
}
|
||||
|
||||
/// For default impls, we need to break apart a type into its
|
||||
@@ -2886,23 +2805,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn rebind_coroutine_witness_types<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
args: ty::GenericArgsRef<'tcx>,
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
|
||||
let bound_coroutine_types = tcx.coroutine_hidden_types(def_id).skip_binder();
|
||||
let shifted_coroutine_types =
|
||||
tcx.shift_bound_var_indices(bound_vars.len(), bound_coroutine_types.skip_binder());
|
||||
ty::Binder::bind_with_vars(
|
||||
ty::EarlyBinder::bind(shifted_coroutine_types.types.to_vec()).instantiate(tcx, args),
|
||||
tcx.mk_bound_variable_kinds_from_iter(
|
||||
bound_vars.iter().chain(bound_coroutine_types.bound_vars()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
|
||||
fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> {
|
||||
TraitObligationStackList::with(self)
|
||||
|
||||
Reference in New Issue
Block a user