Finish uplifting all of structural_traits
This commit is contained in:
parent
b79360ad16
commit
e82db89b4d
14 changed files with 386 additions and 206 deletions
|
@ -225,6 +225,50 @@ impl<'a, 'tcx> At<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Used in the new solver since we don't care about tracking an `ObligationCause`.
|
||||||
|
pub fn relate_no_trace<T>(
|
||||||
|
self,
|
||||||
|
expected: T,
|
||||||
|
variance: ty::Variance,
|
||||||
|
actual: T,
|
||||||
|
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>
|
||||||
|
where
|
||||||
|
T: Relate<TyCtxt<'tcx>>,
|
||||||
|
{
|
||||||
|
let mut fields = CombineFields::new(
|
||||||
|
self.infcx,
|
||||||
|
TypeTrace::dummy(self.cause),
|
||||||
|
self.param_env,
|
||||||
|
DefineOpaqueTypes::Yes,
|
||||||
|
);
|
||||||
|
fields.sub().relate_with_variance(
|
||||||
|
variance,
|
||||||
|
ty::VarianceDiagInfo::default(),
|
||||||
|
expected,
|
||||||
|
actual,
|
||||||
|
)?;
|
||||||
|
Ok(fields.goals)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used in the new solver since we don't care about tracking an `ObligationCause`.
|
||||||
|
pub fn eq_structurally_relating_aliases_no_trace<T>(
|
||||||
|
self,
|
||||||
|
expected: T,
|
||||||
|
actual: T,
|
||||||
|
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution>
|
||||||
|
where
|
||||||
|
T: Relate<TyCtxt<'tcx>>,
|
||||||
|
{
|
||||||
|
let mut fields = CombineFields::new(
|
||||||
|
self.infcx,
|
||||||
|
TypeTrace::dummy(self.cause),
|
||||||
|
self.param_env,
|
||||||
|
DefineOpaqueTypes::Yes,
|
||||||
|
);
|
||||||
|
fields.equate(StructurallyRelateAliases::Yes).relate(expected, actual)?;
|
||||||
|
Ok(fields.goals)
|
||||||
|
}
|
||||||
|
|
||||||
/// Computes the least-upper-bound, or mutual supertype, of two
|
/// Computes the least-upper-bound, or mutual supertype, of two
|
||||||
/// values. The order of the arguments doesn't matter, but since
|
/// values. The order of the arguments doesn't matter, but since
|
||||||
/// this can result in an error (e.g., if asked to compute LUB of
|
/// this can result in an error (e.g., if asked to compute LUB of
|
||||||
|
|
|
@ -1707,6 +1707,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
ValuePairs::ExistentialProjection(_) => {
|
ValuePairs::ExistentialProjection(_) => {
|
||||||
(false, Mismatch::Fixed("existential projection"))
|
(false, Mismatch::Fixed("existential projection"))
|
||||||
}
|
}
|
||||||
|
infer::DummyPair => (false, Mismatch::Fixed("values")),
|
||||||
};
|
};
|
||||||
let Some(vals) = self.values_str(values) else {
|
let Some(vals) = self.values_str(values) else {
|
||||||
// Derived error. Cancel the emitter.
|
// Derived error. Cancel the emitter.
|
||||||
|
@ -2275,6 +2276,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||||
let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found);
|
let (exp, fnd) = self.cmp_fn_sig(&exp_found.expected, &exp_found.found);
|
||||||
Some((exp, fnd, None))
|
Some((exp, fnd, None))
|
||||||
}
|
}
|
||||||
|
infer::DummyPair => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ pub use RegionVariableOrigin::*;
|
||||||
pub use SubregionOrigin::*;
|
pub use SubregionOrigin::*;
|
||||||
pub use ValuePairs::*;
|
pub use ValuePairs::*;
|
||||||
|
|
||||||
use crate::infer::relate::RelateResult;
|
use crate::infer::relate::{Relate, RelateResult};
|
||||||
use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine};
|
use crate::traits::{self, ObligationCause, ObligationInspector, PredicateObligation, TraitEngine};
|
||||||
use error_reporting::TypeErrCtxt;
|
use error_reporting::TypeErrCtxt;
|
||||||
use free_regions::RegionRelations;
|
use free_regions::RegionRelations;
|
||||||
|
@ -35,6 +35,7 @@ use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey};
|
||||||
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
|
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
|
||||||
use rustc_middle::mir::ConstraintCategory;
|
use rustc_middle::mir::ConstraintCategory;
|
||||||
use rustc_middle::traits::select;
|
use rustc_middle::traits::select;
|
||||||
|
use rustc_middle::traits::solve::{Goal, NoSolution};
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
|
use rustc_middle::ty::fold::BoundVarReplacerDelegate;
|
||||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||||
|
@ -352,14 +353,6 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn universe_of_ct(&self, ct: ConstVid) -> Option<ty::UniverseIndex> {
|
|
||||||
// Same issue as with `universe_of_ty`
|
|
||||||
match self.probe_const_var(ct) {
|
|
||||||
Err(universe) => Some(universe),
|
|
||||||
Ok(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
|
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
|
||||||
match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
|
match self.inner.borrow_mut().unwrap_region_constraints().probe_value(lt) {
|
||||||
Err(universe) => Some(universe),
|
Err(universe) => Some(universe),
|
||||||
|
@ -367,12 +360,12 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
|
fn universe_of_ct(&self, ct: ConstVid) -> Option<ty::UniverseIndex> {
|
||||||
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
|
// Same issue as with `universe_of_ty`
|
||||||
}
|
match self.probe_const_var(ct) {
|
||||||
|
Err(universe) => Some(universe),
|
||||||
fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
|
Ok(_) => None,
|
||||||
self.defining_opaque_types
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> Ty<'tcx> {
|
fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> Ty<'tcx> {
|
||||||
|
@ -406,6 +399,26 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn opportunistic_resolve_lt_var(&self, vid: ty::RegionVid) -> ty::Region<'tcx> {
|
||||||
|
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn defining_opaque_types(&self) -> &'tcx ty::List<LocalDefId> {
|
||||||
|
self.defining_opaque_types
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_ty_infer(&self) -> Ty<'tcx> {
|
||||||
|
self.next_ty_var(DUMMY_SP)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_const_infer(&self) -> ty::Const<'tcx> {
|
||||||
|
self.next_const_var(DUMMY_SP)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fresh_args_for_item(&self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
|
||||||
|
self.fresh_args_for_item(DUMMY_SP, def_id)
|
||||||
|
}
|
||||||
|
|
||||||
fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
|
fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
|
||||||
&self,
|
&self,
|
||||||
value: ty::Binder<'tcx, T>,
|
value: ty::Binder<'tcx, T>,
|
||||||
|
@ -417,13 +430,40 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enter_forall<T: TypeFoldable<Self::Interner> + Copy, U>(
|
fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>(
|
||||||
&self,
|
&self,
|
||||||
value: ty::Binder<'tcx, T>,
|
value: ty::Binder<'tcx, T>,
|
||||||
f: impl FnOnce(T) -> U,
|
f: impl FnOnce(T) -> U,
|
||||||
) -> U {
|
) -> U {
|
||||||
self.enter_forall(value, f)
|
self.enter_forall(value, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn relate<T: Relate<TyCtxt<'tcx>>>(
|
||||||
|
&self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
lhs: T,
|
||||||
|
variance: ty::Variance,
|
||||||
|
rhs: T,
|
||||||
|
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
|
||||||
|
self.at(&ObligationCause::dummy(), param_env).relate_no_trace(lhs, variance, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eq_structurally_relating_aliases<T: Relate<TyCtxt<'tcx>>>(
|
||||||
|
&self,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
lhs: T,
|
||||||
|
rhs: T,
|
||||||
|
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
|
||||||
|
self.at(&ObligationCause::dummy(), param_env)
|
||||||
|
.eq_structurally_relating_aliases_no_trace(lhs, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_vars_if_possible<T>(&self, value: T) -> T
|
||||||
|
where
|
||||||
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||||
|
{
|
||||||
|
self.resolve_vars_if_possible(value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See the `error_reporting` module for more details.
|
/// See the `error_reporting` module for more details.
|
||||||
|
@ -436,6 +476,7 @@ pub enum ValuePairs<'tcx> {
|
||||||
PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
|
PolySigs(ExpectedFound<ty::PolyFnSig<'tcx>>),
|
||||||
ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
|
ExistentialTraitRef(ExpectedFound<ty::PolyExistentialTraitRef<'tcx>>),
|
||||||
ExistentialProjection(ExpectedFound<ty::PolyExistentialProjection<'tcx>>),
|
ExistentialProjection(ExpectedFound<ty::PolyExistentialProjection<'tcx>>),
|
||||||
|
DummyPair,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ValuePairs<'tcx> {
|
impl<'tcx> ValuePairs<'tcx> {
|
||||||
|
@ -1858,6 +1899,10 @@ impl<'tcx> TypeTrace<'tcx> {
|
||||||
values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
values: Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dummy(cause: &ObligationCause<'tcx>) -> TypeTrace<'tcx> {
|
||||||
|
TypeTrace { cause: cause.clone(), values: ValuePairs::DummyPair }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> SubregionOrigin<'tcx> {
|
impl<'tcx> SubregionOrigin<'tcx> {
|
||||||
|
|
|
@ -70,9 +70,9 @@ use rustc_span::{Span, DUMMY_SP};
|
||||||
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
|
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use rustc_type_ir::fold::TypeFoldable;
|
use rustc_type_ir::fold::TypeFoldable;
|
||||||
|
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||||
use rustc_type_ir::TyKind::*;
|
use rustc_type_ir::TyKind::*;
|
||||||
use rustc_type_ir::WithCachedTypeInfo;
|
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo};
|
||||||
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags};
|
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
use std::assert_matches::assert_matches;
|
use std::assert_matches::assert_matches;
|
||||||
|
@ -302,6 +302,25 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
fn has_target_features(self, def_id: DefId) -> bool {
|
fn has_target_features(self, def_id: DefId) -> bool {
|
||||||
!self.codegen_fn_attrs(def_id).target_features.is_empty()
|
!self.codegen_fn_attrs(def_id).target_features.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn require_lang_item(self, lang_item: TraitSolverLangItem) -> DefId {
|
||||||
|
self.require_lang_item(
|
||||||
|
match lang_item {
|
||||||
|
TraitSolverLangItem::Future => hir::LangItem::Future,
|
||||||
|
TraitSolverLangItem::FutureOutput => hir::LangItem::FutureOutput,
|
||||||
|
TraitSolverLangItem::AsyncFnKindHelper => hir::LangItem::AsyncFnKindHelper,
|
||||||
|
TraitSolverLangItem::AsyncFnKindUpvars => hir::LangItem::AsyncFnKindUpvars,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn associated_type_def_ids(self, def_id: DefId) -> impl Iterator<Item = DefId> {
|
||||||
|
self.associated_items(def_id)
|
||||||
|
.in_definition_order()
|
||||||
|
.filter(|assoc_item| matches!(assoc_item.kind, ty::AssocKind::Type))
|
||||||
|
.map(|assoc_item| assoc_item.def_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
|
impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
|
||||||
|
|
|
@ -51,6 +51,14 @@ impl<'tcx> rustc_type_ir::inherent::Predicate<TyCtxt<'tcx>> for Predicate<'tcx>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> rustc_type_ir::inherent::IntoKind for Predicate<'tcx> {
|
||||||
|
type Kind = ty::Binder<'tcx, ty::PredicateKind<'tcx>>;
|
||||||
|
|
||||||
|
fn kind(self) -> Self::Kind {
|
||||||
|
self.kind()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> rustc_type_ir::visit::Flags for Predicate<'tcx> {
|
impl<'tcx> rustc_type_ir::visit::Flags for Predicate<'tcx> {
|
||||||
fn flags(&self) -> TypeFlags {
|
fn flags(&self) -> TypeFlags {
|
||||||
self.0.flags
|
self.0.flags
|
||||||
|
@ -120,6 +128,7 @@ impl<'tcx> Predicate<'tcx> {
|
||||||
/// unsoundly accept some programs. See #91068.
|
/// unsoundly accept some programs. See #91068.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn allow_normalization(self) -> bool {
|
pub fn allow_normalization(self) -> bool {
|
||||||
|
// Keep this in sync with the one in `rustc_type_ir::inherent`!
|
||||||
match self.kind().skip_binder() {
|
match self.kind().skip_binder() {
|
||||||
PredicateKind::Clause(ClauseKind::WellFormed(_))
|
PredicateKind::Clause(ClauseKind::WellFormed(_))
|
||||||
| PredicateKind::AliasRelate(..)
|
| PredicateKind::AliasRelate(..)
|
||||||
|
|
|
@ -6,6 +6,7 @@ use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_next_trait_solver::solve::{Goal, NoSolution};
|
use rustc_next_trait_solver::solve::{Goal, NoSolution};
|
||||||
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_type_ir::inherent::*;
|
use rustc_type_ir::inherent::*;
|
||||||
|
use rustc_type_ir::lang_items::TraitSolverLangItem;
|
||||||
use rustc_type_ir::{self as ty, InferCtxtLike, Interner, Upcast};
|
use rustc_type_ir::{self as ty, InferCtxtLike, Interner, Upcast};
|
||||||
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
|
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
|
||||||
|
|
||||||
|
@ -428,7 +429,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
||||||
nested.push(
|
nested.push(
|
||||||
ty::TraitRef::new(
|
ty::TraitRef::new(
|
||||||
tcx,
|
tcx,
|
||||||
tcx.require_lang_item(LangItem::AsyncFnKindHelper, None),
|
tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper),
|
||||||
[kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
|
[kind_ty, Ty::from_closure_kind(tcx, goal_kind)],
|
||||||
)
|
)
|
||||||
.upcast(tcx),
|
.upcast(tcx),
|
||||||
|
@ -452,7 +453,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
||||||
ty::FnDef(..) | ty::FnPtr(..) => {
|
ty::FnDef(..) | ty::FnPtr(..) => {
|
||||||
let bound_sig = self_ty.fn_sig(tcx);
|
let bound_sig = self_ty.fn_sig(tcx);
|
||||||
let sig = bound_sig.skip_binder();
|
let sig = bound_sig.skip_binder();
|
||||||
let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
|
let future_trait_def_id = tcx.require_lang_item(TraitSolverLangItem::Future);
|
||||||
// `FnDef` and `FnPtr` only implement `AsyncFn*` when their
|
// `FnDef` and `FnPtr` only implement `AsyncFn*` when their
|
||||||
// return type implements `Future`.
|
// return type implements `Future`.
|
||||||
let nested = vec![
|
let nested = vec![
|
||||||
|
@ -460,7 +461,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
||||||
.rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()]))
|
.rebind(ty::TraitRef::new(tcx, future_trait_def_id, [sig.output()]))
|
||||||
.upcast(tcx),
|
.upcast(tcx),
|
||||||
];
|
];
|
||||||
let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
|
let future_output_def_id = tcx.require_lang_item(TraitSolverLangItem::FutureOutput);
|
||||||
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
||||||
Ok((
|
Ok((
|
||||||
bound_sig.rebind(AsyncCallableRelevantTypes {
|
bound_sig.rebind(AsyncCallableRelevantTypes {
|
||||||
|
@ -475,7 +476,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
||||||
let args = args.as_closure();
|
let args = args.as_closure();
|
||||||
let bound_sig = args.sig();
|
let bound_sig = args.sig();
|
||||||
let sig = bound_sig.skip_binder();
|
let sig = bound_sig.skip_binder();
|
||||||
let future_trait_def_id = tcx.require_lang_item(LangItem::Future, None);
|
let future_trait_def_id = tcx.require_lang_item(TraitSolverLangItem::Future);
|
||||||
// `Closure`s only implement `AsyncFn*` when their return type
|
// `Closure`s only implement `AsyncFn*` when their return type
|
||||||
// implements `Future`.
|
// implements `Future`.
|
||||||
let mut nested = vec![
|
let mut nested = vec![
|
||||||
|
@ -493,7 +494,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let async_fn_kind_trait_def_id =
|
let async_fn_kind_trait_def_id =
|
||||||
tcx.require_lang_item(LangItem::AsyncFnKindHelper, None);
|
tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindHelper);
|
||||||
// When we don't know the closure kind (and therefore also the closure's upvars,
|
// When we don't know the closure kind (and therefore also the closure's upvars,
|
||||||
// which are computed at the same time), we must delay the computation of the
|
// which are computed at the same time), we must delay the computation of the
|
||||||
// generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
|
// generator's upvars. We do this using the `AsyncFnKindHelper`, which as a trait
|
||||||
|
@ -511,7 +512,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable<I:
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, None);
|
let future_output_def_id = tcx.require_lang_item(TraitSolverLangItem::FutureOutput);
|
||||||
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
let future_output_ty = Ty::new_projection(tcx, future_output_def_id, [sig.output()]);
|
||||||
Ok((
|
Ok((
|
||||||
bound_sig.rebind(AsyncCallableRelevantTypes {
|
bound_sig.rebind(AsyncCallableRelevantTypes {
|
||||||
|
@ -588,7 +589,7 @@ fn coroutine_closure_to_ambiguous_coroutine<I: Interner>(
|
||||||
args: ty::CoroutineClosureArgs<I>,
|
args: ty::CoroutineClosureArgs<I>,
|
||||||
sig: ty::CoroutineClosureSignature<I>,
|
sig: ty::CoroutineClosureSignature<I>,
|
||||||
) -> I::Ty {
|
) -> I::Ty {
|
||||||
let upvars_projection_def_id = tcx.require_lang_item(LangItem::AsyncFnKindUpvars, None);
|
let upvars_projection_def_id = tcx.require_lang_item(TraitSolverLangItem::AsyncFnKindUpvars);
|
||||||
let tupled_upvars_ty = Ty::new_projection(
|
let tupled_upvars_ty = Ty::new_projection(
|
||||||
tcx,
|
tcx,
|
||||||
upvars_projection_def_id,
|
upvars_projection_def_id,
|
||||||
|
@ -663,19 +664,19 @@ pub(in crate::solve) fn predicates_for_object_candidate<
|
||||||
let mut requirements = vec![];
|
let mut requirements = vec![];
|
||||||
requirements
|
requirements
|
||||||
.extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, &trait_ref.args));
|
.extend(tcx.super_predicates_of(trait_ref.def_id).iter_instantiated(tcx, &trait_ref.args));
|
||||||
for item in tcx.associated_items(trait_ref.def_id).in_definition_order() {
|
|
||||||
// FIXME(associated_const_equality): Also add associated consts to
|
|
||||||
// the requirements here.
|
|
||||||
if item.kind == ty::AssocKind::Type {
|
|
||||||
// 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) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
requirements
|
// FIXME(associated_const_equality): Also add associated consts to
|
||||||
.extend(tcx.item_bounds(item.def_id).iter_instantiated(tcx, &trait_ref.args));
|
// the requirements here.
|
||||||
|
for associated_type_def_id in tcx.associated_type_def_ids(trait_ref.def_id) {
|
||||||
|
// 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(associated_type_def_id) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requirements.extend(
|
||||||
|
tcx.item_bounds(associated_type_def_id).iter_instantiated(tcx, &trait_ref.args),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut replace_projection_with = FxHashMap::default();
|
let mut replace_projection_with = FxHashMap::default();
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::at::ToTrace;
|
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
||||||
use rustc_infer::infer::{
|
|
||||||
BoundRegionConversionTime, DefineOpaqueTypes, InferCtxt, InferOk, TyCtxtInferExt,
|
|
||||||
};
|
|
||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals};
|
use rustc_infer::traits::solve::{MaybeCause, NestedNormalizationGoals};
|
||||||
use rustc_infer::traits::ObligationCause;
|
use rustc_infer::traits::ObligationCause;
|
||||||
|
@ -15,11 +12,12 @@ use rustc_middle::traits::solve::{
|
||||||
use rustc_middle::ty::AliasRelationDirection;
|
use rustc_middle::ty::AliasRelationDirection;
|
||||||
use rustc_middle::ty::TypeFolder;
|
use rustc_middle::ty::TypeFolder;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
|
self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeVisitableExt,
|
||||||
TypeVisitable, TypeVisitableExt, TypeVisitor,
|
|
||||||
};
|
};
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
use rustc_type_ir::fold::TypeSuperFoldable;
|
use rustc_type_ir::fold::TypeSuperFoldable;
|
||||||
|
use rustc_type_ir::inherent::*;
|
||||||
|
use rustc_type_ir::relate::Relate;
|
||||||
use rustc_type_ir::{self as ir, CanonicalVarValues, Interner};
|
use rustc_type_ir::{self as ir, CanonicalVarValues, Interner};
|
||||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
@ -456,28 +454,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self))]
|
|
||||||
pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal<'tcx, ty::NormalizesTo<'tcx>>) {
|
|
||||||
goal.predicate = goal
|
|
||||||
.predicate
|
|
||||||
.fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env });
|
|
||||||
self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal);
|
|
||||||
self.nested_goals.normalizes_to_goals.push(goal);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
|
||||||
pub(super) fn add_goal(
|
|
||||||
&mut self,
|
|
||||||
source: GoalSource,
|
|
||||||
mut goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
|
||||||
) {
|
|
||||||
goal.predicate = goal
|
|
||||||
.predicate
|
|
||||||
.fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env });
|
|
||||||
self.inspect.add_goal(self.infcx, self.max_input_universe, source, goal);
|
|
||||||
self.nested_goals.goals.push((source, goal));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning
|
// Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning
|
||||||
// the certainty of all the goals.
|
// the certainty of all the goals.
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
|
@ -600,30 +576,65 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> EvalCtxt<'_, Infcx> {
|
||||||
pub(super) fn interner(&self) -> I {
|
pub(super) fn interner(&self) -> I {
|
||||||
self.infcx.interner()
|
self.infcx.interner()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
#[instrument(level = "trace", skip(self))]
|
||||||
pub(super) fn next_ty_infer(&mut self) -> Ty<'tcx> {
|
pub(super) fn add_normalizes_to_goal(
|
||||||
let ty = self.infcx.next_ty_var(DUMMY_SP);
|
&mut self,
|
||||||
|
mut goal: ir::solve::Goal<I, ir::NormalizesTo<I>>,
|
||||||
|
) {
|
||||||
|
goal.predicate = goal
|
||||||
|
.predicate
|
||||||
|
.fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env });
|
||||||
|
self.inspect.add_normalizes_to_goal(self.infcx, self.max_input_universe, goal);
|
||||||
|
self.nested_goals.normalizes_to_goals.push(goal);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
|
pub(super) fn add_goal(
|
||||||
|
&mut self,
|
||||||
|
source: GoalSource,
|
||||||
|
mut goal: ir::solve::Goal<I, I::Predicate>,
|
||||||
|
) {
|
||||||
|
goal.predicate = goal
|
||||||
|
.predicate
|
||||||
|
.fold_with(&mut ReplaceAliasWithInfer { ecx: self, param_env: goal.param_env });
|
||||||
|
self.inspect.add_goal(self.infcx, self.max_input_universe, source, goal);
|
||||||
|
self.nested_goals.goals.push((source, goal));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "trace", skip(self, goals))]
|
||||||
|
pub(super) fn add_goals(
|
||||||
|
&mut self,
|
||||||
|
source: GoalSource,
|
||||||
|
goals: impl IntoIterator<Item = ir::solve::Goal<I, I::Predicate>>,
|
||||||
|
) {
|
||||||
|
for goal in goals {
|
||||||
|
self.add_goal(source, goal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn next_ty_infer(&mut self) -> I::Ty {
|
||||||
|
let ty = self.infcx.next_ty_infer();
|
||||||
self.inspect.add_var_value(ty);
|
self.inspect.add_var_value(ty);
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn next_const_infer(&mut self) -> ty::Const<'tcx> {
|
pub(super) fn next_const_infer(&mut self) -> I::Const {
|
||||||
let ct = self.infcx.next_const_var(DUMMY_SP);
|
let ct = self.infcx.next_const_infer();
|
||||||
self.inspect.add_var_value(ct);
|
self.inspect.add_var_value(ct);
|
||||||
ct
|
ct
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a ty infer or a const infer depending on whether `kind` is a `Ty` or `Const`.
|
/// Returns a ty infer or a const infer depending on whether `kind` is a `Ty` or `Const`.
|
||||||
/// If `kind` is an integer inference variable this will still return a ty infer var.
|
/// If `kind` is an integer inference variable this will still return a ty infer var.
|
||||||
pub(super) fn next_term_infer_of_kind(&mut self, kind: ty::Term<'tcx>) -> ty::Term<'tcx> {
|
pub(super) fn next_term_infer_of_kind(&mut self, kind: I::Term) -> I::Term {
|
||||||
match kind.unpack() {
|
match kind.kind() {
|
||||||
ty::TermKind::Ty(_) => self.next_ty_infer().into(),
|
ir::TermKind::Ty(_) => self.next_ty_infer().into(),
|
||||||
ty::TermKind::Const(_) => self.next_const_infer().into(),
|
ir::TermKind::Const(_) => self.next_const_infer().into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
/// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
|
/// Is the projection predicate is of the form `exists<T> <Ty as Trait>::Assoc = T`.
|
||||||
///
|
///
|
||||||
/// This is the case if the `term` does not occur in any other part of the predicate
|
/// This is the case if the `term` does not occur in any other part of the predicate
|
||||||
|
@ -631,18 +642,18 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
#[instrument(level = "trace", skip(self), ret)]
|
#[instrument(level = "trace", skip(self), ret)]
|
||||||
pub(super) fn term_is_fully_unconstrained(
|
pub(super) fn term_is_fully_unconstrained(
|
||||||
&self,
|
&self,
|
||||||
goal: Goal<'tcx, ty::NormalizesTo<'tcx>>,
|
goal: ir::solve::Goal<I, ir::NormalizesTo<I>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let universe_of_term = match goal.predicate.term.unpack() {
|
let universe_of_term = match goal.predicate.term.kind() {
|
||||||
ty::TermKind::Ty(ty) => {
|
ir::TermKind::Ty(ty) => {
|
||||||
if let &ty::Infer(ty::TyVar(vid)) = ty.kind() {
|
if let ir::Infer(ir::TyVar(vid)) = ty.kind() {
|
||||||
self.infcx.universe_of_ty(vid).unwrap()
|
self.infcx.universe_of_ty(vid).unwrap()
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::TermKind::Const(ct) => {
|
ir::TermKind::Const(ct) => {
|
||||||
if let ty::ConstKind::Infer(ty::InferConst::Var(vid)) = ct.kind() {
|
if let ir::ConstKind::Infer(ir::InferConst::Var(vid)) = ct.kind() {
|
||||||
self.infcx.universe_of_ct(vid).unwrap()
|
self.infcx.universe_of_ct(vid).unwrap()
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -650,14 +661,14 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ContainsTermOrNotNameable<'a, 'tcx> {
|
struct ContainsTermOrNotNameable<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> {
|
||||||
term: ty::Term<'tcx>,
|
term: I::Term,
|
||||||
universe_of_term: ty::UniverseIndex,
|
universe_of_term: ir::UniverseIndex,
|
||||||
infcx: &'a InferCtxt<'tcx>,
|
infcx: &'a Infcx,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> ContainsTermOrNotNameable<'a, 'tcx> {
|
impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> ContainsTermOrNotNameable<'_, Infcx, I> {
|
||||||
fn check_nameable(&self, universe: ty::UniverseIndex) -> ControlFlow<()> {
|
fn check_nameable(&self, universe: ir::UniverseIndex) -> ControlFlow<()> {
|
||||||
if self.universe_of_term.can_name(universe) {
|
if self.universe_of_term.can_name(universe) {
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -666,12 +677,14 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ContainsTermOrNotNameable<'_, 'tcx> {
|
impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeVisitor<I>
|
||||||
|
for ContainsTermOrNotNameable<'_, Infcx, I>
|
||||||
|
{
|
||||||
type Result = ControlFlow<()>;
|
type Result = ControlFlow<()>;
|
||||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
|
fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
|
||||||
match *t.kind() {
|
match t.kind() {
|
||||||
ty::Infer(ty::TyVar(vid)) => {
|
ir::Infer(ir::TyVar(vid)) => {
|
||||||
if let ty::TermKind::Ty(term) = self.term.unpack()
|
if let ir::TermKind::Ty(term) = self.term.kind()
|
||||||
&& let Some(term_vid) = term.ty_vid()
|
&& let Some(term_vid) = term.ty_vid()
|
||||||
&& self.infcx.root_var(vid) == self.infcx.root_var(term_vid)
|
&& self.infcx.root_var(vid) == self.infcx.root_var(term_vid)
|
||||||
{
|
{
|
||||||
|
@ -680,7 +693,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
self.check_nameable(self.infcx.universe_of_ty(vid).unwrap())
|
self.check_nameable(self.infcx.universe_of_ty(vid).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Placeholder(p) => self.check_nameable(p.universe),
|
ir::Placeholder(p) => self.check_nameable(p.universe()),
|
||||||
_ => {
|
_ => {
|
||||||
if t.has_non_region_infer() || t.has_placeholders() {
|
if t.has_non_region_infer() || t.has_placeholders() {
|
||||||
t.super_visit_with(self)
|
t.super_visit_with(self)
|
||||||
|
@ -691,11 +704,11 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
|
fn visit_const(&mut self, c: I::Const) -> Self::Result {
|
||||||
match c.kind() {
|
match c.kind() {
|
||||||
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
ir::ConstKind::Infer(ir::InferConst::Var(vid)) => {
|
||||||
if let ty::TermKind::Const(term) = self.term.unpack()
|
if let ir::TermKind::Const(term) = self.term.kind()
|
||||||
&& let ty::ConstKind::Infer(ty::InferConst::Var(term_vid)) = term.kind()
|
&& let ir::ConstKind::Infer(ir::InferConst::Var(term_vid)) = term.kind()
|
||||||
&& self.infcx.root_const_var(vid) == self.infcx.root_const_var(term_vid)
|
&& self.infcx.root_const_var(vid) == self.infcx.root_const_var(term_vid)
|
||||||
{
|
{
|
||||||
ControlFlow::Break(())
|
ControlFlow::Break(())
|
||||||
|
@ -703,7 +716,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
self.check_nameable(self.infcx.universe_of_ct(vid).unwrap())
|
self.check_nameable(self.infcx.universe_of_ct(vid).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::ConstKind::Placeholder(p) => self.check_nameable(p.universe),
|
ir::ConstKind::Placeholder(p) => self.check_nameable(p.universe()),
|
||||||
_ => {
|
_ => {
|
||||||
if c.has_non_region_infer() || c.has_placeholders() {
|
if c.has_non_region_infer() || c.has_placeholders() {
|
||||||
c.super_visit_with(self)
|
c.super_visit_with(self)
|
||||||
|
@ -723,25 +736,16 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
goal.predicate.alias.visit_with(&mut visitor).is_continue()
|
goal.predicate.alias.visit_with(&mut visitor).is_continue()
|
||||||
&& goal.param_env.visit_with(&mut visitor).is_continue()
|
&& goal.param_env.visit_with(&mut visitor).is_continue()
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, param_env), ret)]
|
#[instrument(level = "trace", skip(self, param_env), ret)]
|
||||||
pub(super) fn eq<T: ToTrace<'tcx>>(
|
pub(super) fn eq<T: Relate<I>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: I::ParamEnv,
|
||||||
lhs: T,
|
lhs: T,
|
||||||
rhs: T,
|
rhs: T,
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
self.infcx
|
self.relate(param_env, lhs, ir::Variance::Invariant, rhs)
|
||||||
.at(&ObligationCause::dummy(), param_env)
|
|
||||||
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
|
|
||||||
.eq(DefineOpaqueTypes::Yes, lhs, rhs)
|
|
||||||
.map(|InferOk { value: (), obligations }| {
|
|
||||||
self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
|
|
||||||
})
|
|
||||||
.map_err(|e| {
|
|
||||||
trace!(?e, "failed to equate");
|
|
||||||
NoSolution
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This should be used when relating a rigid alias with another type.
|
/// This should be used when relating a rigid alias with another type.
|
||||||
|
@ -752,10 +756,10 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
#[instrument(level = "trace", skip(self, param_env), ret)]
|
#[instrument(level = "trace", skip(self, param_env), ret)]
|
||||||
pub(super) fn relate_rigid_alias_non_alias(
|
pub(super) fn relate_rigid_alias_non_alias(
|
||||||
&mut self,
|
&mut self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: I::ParamEnv,
|
||||||
alias: ty::AliasTerm<'tcx>,
|
alias: ir::AliasTerm<I>,
|
||||||
variance: ty::Variance,
|
variance: ir::Variance,
|
||||||
term: ty::Term<'tcx>,
|
term: I::Term,
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
// NOTE: this check is purely an optimization, the structural eq would
|
// NOTE: this check is purely an optimization, the structural eq would
|
||||||
// always fail if the term is not an inference variable.
|
// always fail if the term is not an inference variable.
|
||||||
|
@ -770,12 +774,10 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
// Alternatively we could modify `Equate` for this case by adding another
|
// Alternatively we could modify `Equate` for this case by adding another
|
||||||
// variant to `StructurallyRelateAliases`.
|
// variant to `StructurallyRelateAliases`.
|
||||||
let identity_args = self.fresh_args_for_item(alias.def_id);
|
let identity_args = self.fresh_args_for_item(alias.def_id);
|
||||||
let rigid_ctor = ty::AliasTerm::new(tcx, alias.def_id, identity_args);
|
let rigid_ctor = ir::AliasTerm::new(tcx, alias.def_id, identity_args);
|
||||||
let ctor_term = rigid_ctor.to_term(tcx);
|
let ctor_term = rigid_ctor.to_term(tcx);
|
||||||
let InferOk { value: (), obligations } = self
|
let obligations =
|
||||||
.infcx
|
self.infcx.eq_structurally_relating_aliases(param_env, term, ctor_term)?;
|
||||||
.at(&ObligationCause::dummy(), param_env)
|
|
||||||
.eq_structurally_relating_aliases(term, ctor_term)?;
|
|
||||||
debug_assert!(obligations.is_empty());
|
debug_assert!(obligations.is_empty());
|
||||||
self.relate(param_env, alias, variance, rigid_ctor)
|
self.relate(param_env, alias, variance, rigid_ctor)
|
||||||
} else {
|
} else {
|
||||||
|
@ -787,58 +789,38 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
/// unconstrained "return value" or when we're sure that all aliases in
|
/// unconstrained "return value" or when we're sure that all aliases in
|
||||||
/// the types are rigid.
|
/// the types are rigid.
|
||||||
#[instrument(level = "trace", skip(self, param_env), ret)]
|
#[instrument(level = "trace", skip(self, param_env), ret)]
|
||||||
pub(super) fn eq_structurally_relating_aliases<T: ToTrace<'tcx>>(
|
pub(super) fn eq_structurally_relating_aliases<T: Relate<I>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: I::ParamEnv,
|
||||||
lhs: T,
|
lhs: T,
|
||||||
rhs: T,
|
rhs: T,
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
let cause = ObligationCause::dummy();
|
let result = self.infcx.eq_structurally_relating_aliases(param_env, lhs, rhs)?;
|
||||||
let InferOk { value: (), obligations } =
|
assert_eq!(result, vec![]);
|
||||||
self.infcx.at(&cause, param_env).eq_structurally_relating_aliases(lhs, rhs)?;
|
|
||||||
assert!(obligations.is_empty());
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, param_env), ret)]
|
#[instrument(level = "trace", skip(self, param_env), ret)]
|
||||||
pub(super) fn sub<T: ToTrace<'tcx>>(
|
pub(super) fn sub<T: Relate<I>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: I::ParamEnv,
|
||||||
sub: T,
|
sub: T,
|
||||||
sup: T,
|
sup: T,
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
self.infcx
|
self.relate(param_env, sub, ir::Variance::Covariant, sup)
|
||||||
.at(&ObligationCause::dummy(), param_env)
|
|
||||||
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
|
|
||||||
.sub(DefineOpaqueTypes::Yes, sub, sup)
|
|
||||||
.map(|InferOk { value: (), obligations }| {
|
|
||||||
self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
|
|
||||||
})
|
|
||||||
.map_err(|e| {
|
|
||||||
trace!(?e, "failed to subtype");
|
|
||||||
NoSolution
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(self, param_env), ret)]
|
#[instrument(level = "trace", skip(self, param_env), ret)]
|
||||||
pub(super) fn relate<T: ToTrace<'tcx>>(
|
pub(super) fn relate<T: Relate<I>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: I::ParamEnv,
|
||||||
lhs: T,
|
lhs: T,
|
||||||
variance: ty::Variance,
|
variance: ir::Variance,
|
||||||
rhs: T,
|
rhs: T,
|
||||||
) -> Result<(), NoSolution> {
|
) -> Result<(), NoSolution> {
|
||||||
self.infcx
|
let goals = self.infcx.relate(param_env, lhs, variance, rhs)?;
|
||||||
.at(&ObligationCause::dummy(), param_env)
|
self.add_goals(GoalSource::Misc, goals);
|
||||||
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
|
Ok(())
|
||||||
.relate(DefineOpaqueTypes::Yes, lhs, variance, rhs)
|
|
||||||
.map(|InferOk { value: (), obligations }| {
|
|
||||||
self.add_goals(GoalSource::Misc, obligations.into_iter().map(|o| o.into()));
|
|
||||||
})
|
|
||||||
.map_err(|e| {
|
|
||||||
trace!(?e, "failed to relate");
|
|
||||||
NoSolution
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equates two values returning the nested goals without adding them
|
/// Equates two values returning the nested goals without adding them
|
||||||
|
@ -847,58 +829,47 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
/// If possible, try using `eq` instead which automatically handles nested
|
/// If possible, try using `eq` instead which automatically handles nested
|
||||||
/// goals correctly.
|
/// goals correctly.
|
||||||
#[instrument(level = "trace", skip(self, param_env), ret)]
|
#[instrument(level = "trace", skip(self, param_env), ret)]
|
||||||
pub(super) fn eq_and_get_goals<T: ToTrace<'tcx>>(
|
pub(super) fn eq_and_get_goals<T: Relate<I>>(
|
||||||
&self,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: I::ParamEnv,
|
||||||
lhs: T,
|
lhs: T,
|
||||||
rhs: T,
|
rhs: T,
|
||||||
) -> Result<Vec<Goal<'tcx, ty::Predicate<'tcx>>>, NoSolution> {
|
) -> Result<Vec<ir::solve::Goal<I, I::Predicate>>, NoSolution> {
|
||||||
self.infcx
|
self.infcx.relate(param_env, lhs, ir::Variance::Invariant, rhs)
|
||||||
.at(&ObligationCause::dummy(), param_env)
|
|
||||||
// New solver ignores DefineOpaqueTypes, so choose Yes for consistency
|
|
||||||
.eq(DefineOpaqueTypes::Yes, lhs, rhs)
|
|
||||||
.map(|InferOk { value: (), obligations }| {
|
|
||||||
obligations.into_iter().map(|o| o.into()).collect()
|
|
||||||
})
|
|
||||||
.map_err(|e| {
|
|
||||||
trace!(?e, "failed to equate");
|
|
||||||
NoSolution
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<TyCtxt<'tcx>> + Copy>(
|
pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(
|
||||||
&self,
|
&self,
|
||||||
value: ty::Binder<'tcx, T>,
|
value: ir::Binder<I, T>,
|
||||||
) -> T {
|
) -> T {
|
||||||
self.infcx.instantiate_binder_with_fresh_vars(
|
self.infcx.instantiate_binder_with_infer(value)
|
||||||
DUMMY_SP,
|
|
||||||
BoundRegionConversionTime::HigherRankedType,
|
|
||||||
value,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn enter_forall<T: TypeFoldable<TyCtxt<'tcx>> + Copy, U>(
|
pub(super) fn enter_forall<T: TypeFoldable<I> + Copy, U>(
|
||||||
&self,
|
&self,
|
||||||
value: ty::Binder<'tcx, T>,
|
value: ir::Binder<I, T>,
|
||||||
f: impl FnOnce(T) -> U,
|
f: impl FnOnce(T) -> U,
|
||||||
) -> U {
|
) -> U {
|
||||||
self.infcx.enter_forall(value, f)
|
self.infcx.enter_forall(value, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
|
pub(super) fn resolve_vars_if_possible<T>(&self, value: T) -> T
|
||||||
where
|
where
|
||||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
T: TypeFoldable<I>,
|
||||||
{
|
{
|
||||||
self.infcx.resolve_vars_if_possible(value)
|
self.infcx.resolve_vars_if_possible(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn fresh_args_for_item(&mut self, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
|
pub(super) fn fresh_args_for_item(&mut self, def_id: I::DefId) -> I::GenericArgs {
|
||||||
let args = self.infcx.fresh_args_for_item(DUMMY_SP, def_id);
|
let args = self.infcx.fresh_args_for_item(def_id);
|
||||||
for arg in args {
|
for arg in args {
|
||||||
self.inspect.add_var_value(arg);
|
self.inspect.add_var_value(arg);
|
||||||
}
|
}
|
||||||
args
|
args
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: ty::Region<'tcx>) {
|
pub(super) fn register_ty_outlives(&self, ty: Ty<'tcx>, lt: ty::Region<'tcx>) {
|
||||||
self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy());
|
self.infcx.register_region_obligation_with_cause(ty, lt, &ObligationCause::dummy());
|
||||||
}
|
}
|
||||||
|
@ -1096,28 +1067,36 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
///
|
///
|
||||||
/// This is a performance optimization to more eagerly detect cycles during trait
|
/// This is a performance optimization to more eagerly detect cycles during trait
|
||||||
/// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs.
|
/// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs.
|
||||||
struct ReplaceAliasWithInfer<'me, 'a, 'tcx> {
|
struct ReplaceAliasWithInfer<'me, 'a, Infcx, I>
|
||||||
ecx: &'me mut EvalCtxt<'a, InferCtxt<'tcx>>,
|
where
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
Infcx: InferCtxtLike<Interner = I>,
|
||||||
|
I: Interner,
|
||||||
|
{
|
||||||
|
ecx: &'me mut EvalCtxt<'a, Infcx>,
|
||||||
|
param_env: I::ParamEnv,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceAliasWithInfer<'_, '_, 'tcx> {
|
impl<Infcx, I> TypeFolder<I> for ReplaceAliasWithInfer<'_, '_, Infcx, I>
|
||||||
fn interner(&self) -> TyCtxt<'tcx> {
|
where
|
||||||
|
Infcx: InferCtxtLike<Interner = I>,
|
||||||
|
I: Interner,
|
||||||
|
{
|
||||||
|
fn interner(&self) -> I {
|
||||||
self.ecx.interner()
|
self.ecx.interner()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
|
||||||
match *ty.kind() {
|
match ty.kind() {
|
||||||
ty::Alias(..) if !ty.has_escaping_bound_vars() => {
|
ir::Alias(..) if !ty.has_escaping_bound_vars() => {
|
||||||
let infer_ty = self.ecx.next_ty_infer();
|
let infer_ty = self.ecx.next_ty_infer();
|
||||||
let normalizes_to = ty::PredicateKind::AliasRelate(
|
let normalizes_to = ir::PredicateKind::AliasRelate(
|
||||||
ty.into(),
|
ty.into(),
|
||||||
infer_ty.into(),
|
infer_ty.into(),
|
||||||
AliasRelationDirection::Equate,
|
AliasRelationDirection::Equate,
|
||||||
);
|
);
|
||||||
self.ecx.add_goal(
|
self.ecx.add_goal(
|
||||||
GoalSource::Misc,
|
GoalSource::Misc,
|
||||||
Goal::new(self.interner(), self.param_env, normalizes_to),
|
ir::solve::Goal::new(self.interner(), self.param_env, normalizes_to),
|
||||||
);
|
);
|
||||||
infer_ty
|
infer_ty
|
||||||
}
|
}
|
||||||
|
@ -1125,18 +1104,18 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceAliasWithInfer<'_, '_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
fn fold_const(&mut self, ct: I::Const) -> I::Const {
|
||||||
match ct.kind() {
|
match ct.kind() {
|
||||||
ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => {
|
ir::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => {
|
||||||
let infer_ct = self.ecx.next_const_infer();
|
let infer_ct = self.ecx.next_const_infer();
|
||||||
let normalizes_to = ty::PredicateKind::AliasRelate(
|
let normalizes_to = ir::PredicateKind::AliasRelate(
|
||||||
ct.into(),
|
ct.into(),
|
||||||
infer_ct.into(),
|
infer_ct.into(),
|
||||||
AliasRelationDirection::Equate,
|
AliasRelationDirection::Equate,
|
||||||
);
|
);
|
||||||
self.ecx.add_goal(
|
self.ecx.add_goal(
|
||||||
GoalSource::Misc,
|
GoalSource::Misc,
|
||||||
Goal::new(self.interner(), self.param_env, normalizes_to),
|
ir::solve::Goal::new(self.interner(), self.param_env, normalizes_to),
|
||||||
);
|
);
|
||||||
infer_ct
|
infer_ct
|
||||||
}
|
}
|
||||||
|
@ -1144,7 +1123,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceAliasWithInfer<'_, '_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
|
fn fold_predicate(&mut self, predicate: I::Predicate) -> I::Predicate {
|
||||||
if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate }
|
if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,17 +235,6 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
#[instrument(level = "trace", skip(self, goals))]
|
|
||||||
fn add_goals(
|
|
||||||
&mut self,
|
|
||||||
source: GoalSource,
|
|
||||||
goals: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>,
|
|
||||||
) {
|
|
||||||
for goal in goals {
|
|
||||||
self.add_goal(source, goal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Try to merge multiple possible ways to prove a goal, if that is not possible returns `None`.
|
/// Try to merge multiple possible ways to prove a goal, if that is not possible returns `None`.
|
||||||
///
|
///
|
||||||
/// In this case we tend to flounder and return ambiguity by calling `[EvalCtxt::flounder]`.
|
/// In this case we tend to flounder and return ambiguity by calling `[EvalCtxt::flounder]`.
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
||||||
goal: Goal<'tcx, NormalizesTo<'tcx>>,
|
goal: Goal<'tcx, NormalizesTo<'tcx>>,
|
||||||
) -> QueryResult<'tcx> {
|
) -> QueryResult<'tcx> {
|
||||||
self.set_is_normalizes_to_goal();
|
self.set_is_normalizes_to_goal();
|
||||||
debug_assert!(self.term_is_fully_unconstrained(goal));
|
// debug_assert!(self.term_is_fully_unconstrained(goal)); TODO:
|
||||||
let normalize_result = self
|
let normalize_result = self
|
||||||
.probe(|&result| ProbeKind::TryNormalizeNonRigid { result })
|
.probe(|&result| ProbeKind::TryNormalizeNonRigid { result })
|
||||||
.enter(|this| this.normalize_at_least_one_step(goal));
|
.enter(|this| this.normalize_at_least_one_step(goal));
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
use crate::fold::TypeFoldable;
|
use crate::fold::TypeFoldable;
|
||||||
|
use crate::relate::Relate;
|
||||||
|
use crate::solve::{Goal, NoSolution};
|
||||||
use crate::{self as ty, Interner};
|
use crate::{self as ty, Interner};
|
||||||
|
|
||||||
pub trait InferCtxtLike {
|
pub trait InferCtxtLike: Sized {
|
||||||
type Interner: Interner;
|
type Interner: Interner;
|
||||||
|
|
||||||
fn interner(&self) -> Self::Interner;
|
fn interner(&self) -> Self::Interner;
|
||||||
|
@ -31,6 +33,13 @@ pub trait InferCtxtLike {
|
||||||
|
|
||||||
fn defining_opaque_types(&self) -> <Self::Interner as Interner>::DefiningOpaqueTypes;
|
fn defining_opaque_types(&self) -> <Self::Interner as Interner>::DefiningOpaqueTypes;
|
||||||
|
|
||||||
|
fn next_ty_infer(&self) -> <Self::Interner as Interner>::Ty;
|
||||||
|
fn next_const_infer(&self) -> <Self::Interner as Interner>::Const;
|
||||||
|
fn fresh_args_for_item(
|
||||||
|
&self,
|
||||||
|
def_id: <Self::Interner as Interner>::DefId,
|
||||||
|
) -> <Self::Interner as Interner>::GenericArgs;
|
||||||
|
|
||||||
fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
|
fn instantiate_binder_with_infer<T: TypeFoldable<Self::Interner> + Copy>(
|
||||||
&self,
|
&self,
|
||||||
value: ty::Binder<Self::Interner, T>,
|
value: ty::Binder<Self::Interner, T>,
|
||||||
|
@ -41,4 +50,23 @@ pub trait InferCtxtLike {
|
||||||
value: ty::Binder<Self::Interner, T>,
|
value: ty::Binder<Self::Interner, T>,
|
||||||
f: impl FnOnce(T) -> U,
|
f: impl FnOnce(T) -> U,
|
||||||
) -> U;
|
) -> U;
|
||||||
|
|
||||||
|
fn relate<T: Relate<Self::Interner>>(
|
||||||
|
&self,
|
||||||
|
param_env: <Self::Interner as Interner>::ParamEnv,
|
||||||
|
lhs: T,
|
||||||
|
variance: ty::Variance,
|
||||||
|
rhs: T,
|
||||||
|
) -> Result<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, NoSolution>;
|
||||||
|
|
||||||
|
fn eq_structurally_relating_aliases<T: Relate<Self::Interner>>(
|
||||||
|
&self,
|
||||||
|
param_env: <Self::Interner as Interner>::ParamEnv,
|
||||||
|
lhs: T,
|
||||||
|
rhs: T,
|
||||||
|
) -> Result<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>, NoSolution>;
|
||||||
|
|
||||||
|
fn resolve_vars_if_possible<T>(&self, value: T) -> T
|
||||||
|
where
|
||||||
|
T: TypeFoldable<Self::Interner>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,6 +183,10 @@ pub trait Const<I: Interner<Const = Self>>:
|
||||||
fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
|
fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
|
||||||
|
|
||||||
fn new_expr(interner: I, expr: I::ExprConst) -> Self;
|
fn new_expr(interner: I, expr: I::ExprConst) -> Self;
|
||||||
|
|
||||||
|
fn is_ct_var(self) -> bool {
|
||||||
|
matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
|
pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
|
||||||
|
@ -206,6 +210,28 @@ pub trait GenericArg<I: Interner<GenericArg = Self>>:
|
||||||
pub trait Term<I: Interner<Term = Self>>:
|
pub trait Term<I: Interner<Term = Self>>:
|
||||||
Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<I>> + TypeFoldable<I> + Relate<I>
|
Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<I>> + TypeFoldable<I> + Relate<I>
|
||||||
{
|
{
|
||||||
|
fn as_type(&self) -> Option<I::Ty> {
|
||||||
|
if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expect_type(&self) -> I::Ty {
|
||||||
|
self.as_type().expect("expected a type, but found a const")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_const(&self) -> Option<I::Const> {
|
||||||
|
if let ty::TermKind::Const(c) = self.kind() { Some(c) } else { None }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expect_const(&self) -> I::Const {
|
||||||
|
self.as_const().expect("expected a const, but found a type")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_infer(self) -> bool {
|
||||||
|
match self.kind() {
|
||||||
|
ty::TermKind::Ty(ty) => ty.is_ty_var(),
|
||||||
|
ty::TermKind::Const(ct) => ct.is_ct_var(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
|
pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
|
||||||
|
@ -251,12 +277,36 @@ pub trait Predicate<I: Interner<Predicate = Self>>:
|
||||||
+ TypeSuperVisitable<I>
|
+ TypeSuperVisitable<I>
|
||||||
+ TypeSuperFoldable<I>
|
+ TypeSuperFoldable<I>
|
||||||
+ Flags
|
+ Flags
|
||||||
|
+ UpcastFrom<I, ty::PredicateKind<I>>
|
||||||
|
+ UpcastFrom<I, ty::Binder<I, ty::PredicateKind<I>>>
|
||||||
|
+ UpcastFrom<I, ty::ClauseKind<I>>
|
||||||
|
+ UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
|
||||||
+ UpcastFrom<I, I::Clause>
|
+ UpcastFrom<I, I::Clause>
|
||||||
+ UpcastFrom<I, ty::NormalizesTo<I>>
|
+ UpcastFrom<I, ty::NormalizesTo<I>>
|
||||||
+ UpcastFrom<I, ty::TraitRef<I>>
|
+ UpcastFrom<I, ty::TraitRef<I>>
|
||||||
+ UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
|
+ UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
|
||||||
|
+ IntoKind<Kind = ty::Binder<I, ty::PredicateKind<I>>>
|
||||||
{
|
{
|
||||||
fn is_coinductive(self, interner: I) -> bool;
|
fn is_coinductive(self, interner: I) -> bool;
|
||||||
|
|
||||||
|
fn allow_normalization(self) -> bool {
|
||||||
|
match self.kind().skip_binder() {
|
||||||
|
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
|
||||||
|
| ty::PredicateKind::AliasRelate(..)
|
||||||
|
| ty::PredicateKind::NormalizesTo(..) => false,
|
||||||
|
ty::PredicateKind::Clause(ty::ClauseKind::Trait(_))
|
||||||
|
| ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))
|
||||||
|
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_))
|
||||||
|
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(_))
|
||||||
|
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
|
||||||
|
| ty::PredicateKind::ObjectSafe(_)
|
||||||
|
| ty::PredicateKind::Subtype(_)
|
||||||
|
| ty::PredicateKind::Coerce(_)
|
||||||
|
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(_))
|
||||||
|
| ty::PredicateKind::ConstEquate(_, _)
|
||||||
|
| ty::PredicateKind::Ambiguous => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Clause<I: Interner<Clause = Self>>:
|
pub trait Clause<I: Interner<Clause = Self>>:
|
||||||
|
|
|
@ -7,6 +7,7 @@ use std::ops::Deref;
|
||||||
use crate::fold::TypeFoldable;
|
use crate::fold::TypeFoldable;
|
||||||
use crate::inherent::*;
|
use crate::inherent::*;
|
||||||
use crate::ir_print::IrPrint;
|
use crate::ir_print::IrPrint;
|
||||||
|
use crate::lang_items::TraitSolverLangItem;
|
||||||
use crate::relate::Relate;
|
use crate::relate::Relate;
|
||||||
use crate::solve::inspect::CanonicalGoalEvaluationStep;
|
use crate::solve::inspect::CanonicalGoalEvaluationStep;
|
||||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
||||||
|
@ -175,6 +176,10 @@ pub trait Interner:
|
||||||
) -> ty::EarlyBinder<Self, impl Iterator<Item = Self::Clause>>;
|
) -> ty::EarlyBinder<Self, impl Iterator<Item = Self::Clause>>;
|
||||||
|
|
||||||
fn has_target_features(self, def_id: Self::DefId) -> bool;
|
fn has_target_features(self, def_id: Self::DefId) -> bool;
|
||||||
|
|
||||||
|
fn require_lang_item(self, lang_item: TraitSolverLangItem) -> Self::DefId;
|
||||||
|
|
||||||
|
fn associated_type_def_ids(self, def_id: Self::DefId) -> impl Iterator<Item = Self::DefId>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
|
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
|
||||||
|
|
8
compiler/rustc_type_ir/src/lang_items.rs
Normal file
8
compiler/rustc_type_ir/src/lang_items.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/// Lang items used by the new trait solver. This can be mapped to whatever internal
|
||||||
|
/// representation of `LangItem`s used in the underlying compiler implementation.
|
||||||
|
pub enum TraitSolverLangItem {
|
||||||
|
Future,
|
||||||
|
FutureOutput,
|
||||||
|
AsyncFnKindHelper,
|
||||||
|
AsyncFnKindUpvars,
|
||||||
|
}
|
|
@ -32,6 +32,7 @@ pub mod error;
|
||||||
pub mod fold;
|
pub mod fold;
|
||||||
pub mod inherent;
|
pub mod inherent;
|
||||||
pub mod ir_print;
|
pub mod ir_print;
|
||||||
|
pub mod lang_items;
|
||||||
pub mod lift;
|
pub mod lift;
|
||||||
pub mod relate;
|
pub mod relate;
|
||||||
pub mod solve;
|
pub mod solve;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue