summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/select
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/select')
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs62
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs253
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs214
3 files changed, 281 insertions, 248 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 8bc82b9f5..d5f6aaa7f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -10,7 +10,7 @@ use hir::def_id::DefId;
use hir::LangItem;
use rustc_hir as hir;
use rustc_infer::traits::ObligationCause;
-use rustc_infer::traits::{Obligation, SelectionError, TraitObligation};
+use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
@@ -137,13 +137,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self, candidates))]
fn assemble_candidates_from_projected_tys(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Before we go into the whole placeholder thing, just
// quickly check if the self-type is a projection at all.
match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
- // Excluding IATs here as they don't have meaningful item bounds.
+ // Excluding IATs and type aliases here as they don't have meaningful item bounds.
ty::Alias(ty::Projection | ty::Opaque, _) => {}
ty::Infer(ty::TyVar(_)) => {
span_bug!(
@@ -181,7 +181,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.caller_bounds()
.iter()
.filter(|p| !p.references_error())
- .filter_map(|p| p.to_opt_poly_trait_pred());
+ .filter_map(|p| p.as_trait_clause());
// Micro-optimization: filter out predicates relating to different traits.
let matching_bounds =
@@ -206,7 +206,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn assemble_generator_candidates(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Okay to skip binder because the substs on generator types never
@@ -231,7 +231,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn assemble_future_candidates(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let self_ty = obligation.self_ty().skip_binder();
@@ -254,7 +254,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// unified during the confirmation step.
fn assemble_closure_candidates(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let Some(kind) = self.tcx().fn_trait_kind_from_def_id(obligation.predicate.def_id()) else {
@@ -292,7 +292,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Implements one of the `Fn()` family for a fn pointer.
fn assemble_fn_pointer_candidates(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// We provide impl of all fn traits for fn pointers.
@@ -334,7 +334,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self, candidates))]
fn assemble_candidates_from_impls(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Essentially any user-written impl will match with an error type,
@@ -360,7 +360,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// consider a "quick reject". This avoids creating more types
// and so forth that we need to.
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
- if !drcx.substs_refs_may_unify(obligation_substs, impl_trait_ref.0.substs) {
+ if !drcx
+ .substs_refs_may_unify(obligation_substs, impl_trait_ref.skip_binder().substs)
+ {
return;
}
if self.reject_fn_ptr_impls(
@@ -386,9 +388,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// `FnPtr`, when we wanted to report that it doesn't implement `Trait`.
#[instrument(level = "trace", skip(self), ret)]
fn reject_fn_ptr_impls(
- &self,
+ &mut self,
impl_def_id: DefId,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
impl_self_ty: Ty<'tcx>,
) -> bool {
// Let `impl<T: FnPtr> Trait for Vec<T>` go through the normal rejection path.
@@ -400,7 +402,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
};
for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates {
- let ty::PredicateKind::Clause(ty::Clause::Trait(pred))
+ let ty::ClauseKind::Trait(pred)
= predicate.kind().skip_binder() else { continue };
if fn_ptr_trait != pred.trait_ref.def_id {
continue;
@@ -415,17 +417,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Fast path to avoid evaluating an obligation that trivially holds.
// There may be more bounds, but these are checked by the regular path.
ty::FnPtr(..) => return false,
+
// These may potentially implement `FnPtr`
ty::Placeholder(..)
| ty::Dynamic(_, _, _)
| ty::Alias(_, _)
| ty::Infer(_)
- | ty::Param(..) => {}
+ | ty::Param(..)
+ | ty::Bound(_, _) => {}
- ty::Bound(_, _) => span_bug!(
- obligation.cause.span(),
- "cannot have escaping bound var in self type of {obligation:#?}"
- ),
// These can't possibly implement `FnPtr` as they are concrete types
// and not `FnPtr`
ty::Bool
@@ -461,10 +461,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.tcx().mk_predicate(obligation.predicate.map_bound(|mut pred| {
pred.trait_ref =
ty::TraitRef::new(self.tcx(), fn_ptr_trait, [pred.trait_ref.self_ty()]);
- ty::PredicateKind::Clause(ty::Clause::Trait(pred))
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred))
})),
);
- if let Ok(r) = self.infcx.evaluate_obligation(&obligation) {
+ if let Ok(r) = self.evaluate_root_obligation(&obligation) {
if !r.may_apply() {
return true;
}
@@ -475,7 +475,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn assemble_candidates_from_auto_impls(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Okay to skip binder here because the tests we do below do not involve bound regions.
@@ -544,7 +544,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Searches for impls that might apply to `obligation`.
fn assemble_candidates_from_object_ty(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
debug!(
@@ -552,6 +552,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
"assemble_candidates_from_object_ty",
);
+ if !self.tcx().trait_def(obligation.predicate.def_id()).implement_via_object {
+ return;
+ }
+
self.infcx.probe(|_snapshot| {
if obligation.has_non_region_late_bound() {
return;
@@ -664,7 +668,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Searches for unsizing that might apply to `obligation`.
fn assemble_candidates_for_unsizing(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// We currently never consider higher-ranked obligations e.g.
@@ -778,7 +782,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self, obligation, candidates))]
fn assemble_candidates_for_transmutability(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
if obligation.predicate.has_non_region_param() {
@@ -796,7 +800,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self, obligation, candidates))]
fn assemble_candidates_for_trait_alias(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// Okay to skip binder here because the tests we do below do not involve bound regions.
@@ -833,7 +837,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn assemble_const_destruct_candidates(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// If the predicate is `~const Destruct` in a non-const environment, we don't actually need
@@ -920,7 +924,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn assemble_candidate_for_tuple(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
@@ -962,7 +966,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn assemble_candidate_for_pointer_like(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
// The regions of a type don't affect the size of the type
@@ -987,7 +991,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn assemble_candidates_for_fn_ptr_trait(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidates: &mut SelectionCandidateSet<'tcx>,
) {
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 0d9f55d4c..7adc29bbb 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -6,6 +6,7 @@
//!
//! [rustc dev guide]:
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
+use rustc_ast::Mutability;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
@@ -13,9 +14,8 @@ use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
use rustc_middle::traits::SelectionOutputTypeParameterMismatch;
use rustc_middle::ty::{
self, Binder, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate,
- TraitRef, Ty, TyCtxt, TypeVisitableExt,
+ TraitPredicate, TraitRef, Ty, TyCtxt, TypeVisitableExt,
};
-use rustc_session::config::TraitSolver;
use rustc_span::def_id::DefId;
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
@@ -26,12 +26,9 @@ use crate::traits::vtable::{
};
use crate::traits::{
BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
- ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
- ImplSourceConstDestructData, ImplSourceFnPointerData, ImplSourceFutureData,
- ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData,
- ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, Obligation,
- ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection, SelectionError,
- TraitNotObjectSafe, TraitObligation, Unimplemented,
+ ImplSourceObjectData, ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized,
+ Obligation, ObligationCause, OutputTypeParameterMismatch, PolyTraitObligation,
+ PredicateObligation, Selection, SelectionError, TraitNotObjectSafe, Unimplemented,
};
use super::BuiltinImplConditions;
@@ -45,7 +42,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self))]
pub(super) fn confirm_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
candidate: SelectionCandidate<'tcx>,
) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
let mut impl_src = match candidate {
@@ -70,8 +67,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
AutoImplCandidate => {
- let data = self.confirm_auto_impl_candidate(obligation);
- ImplSource::AutoImpl(data)
+ let data = self.confirm_auto_impl_candidate(obligation)?;
+ ImplSource::Builtin(data)
}
ProjectionCandidate(idx, constness) => {
@@ -86,34 +83,34 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ClosureCandidate { .. } => {
let vtable_closure = self.confirm_closure_candidate(obligation)?;
- ImplSource::Closure(vtable_closure)
+ ImplSource::Builtin(vtable_closure)
}
GeneratorCandidate => {
let vtable_generator = self.confirm_generator_candidate(obligation)?;
- ImplSource::Generator(vtable_generator)
+ ImplSource::Builtin(vtable_generator)
}
FutureCandidate => {
let vtable_future = self.confirm_future_candidate(obligation)?;
- ImplSource::Future(vtable_future)
+ ImplSource::Builtin(vtable_future)
}
FnPointerCandidate { is_const } => {
let data = self.confirm_fn_pointer_candidate(obligation, is_const)?;
- ImplSource::FnPointer(data)
+ ImplSource::Builtin(data)
}
TraitAliasCandidate => {
let data = self.confirm_trait_alias_candidate(obligation);
- ImplSource::TraitAlias(data)
+ ImplSource::Builtin(data)
}
BuiltinObjectCandidate => {
// This indicates something like `Trait + Send: Send`. In this case, we know that
// this holds because that's what the object type is telling us, and there's really
// no additional obligations to prove and no types in particular to unify, etc.
- ImplSource::Param(Vec::new(), ty::BoundConstness::NotConst)
+ ImplSource::Builtin(Vec::new())
}
BuiltinUnsizeCandidate => {
@@ -128,7 +125,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ConstDestructCandidate(def_id) => {
let data = self.confirm_const_destruct_candidate(obligation, def_id)?;
- ImplSource::ConstDestruct(data)
+ ImplSource::Builtin(data)
}
};
@@ -151,7 +148,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_projection_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
idx: usize,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();
@@ -162,7 +159,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let placeholder_self_ty = placeholder_trait_predicate.self_ty();
let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
let (def_id, substs) = match *placeholder_self_ty.kind() {
- // Excluding IATs here as they don't have meaningful item bounds.
+ // Excluding IATs and type aliases here as they don't have meaningful item bounds.
ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
(def_id, substs)
}
@@ -171,7 +168,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let candidate_predicate = tcx.item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs);
let candidate = candidate_predicate
- .to_opt_poly_trait_pred()
+ .as_trait_clause()
.expect("projection candidate is not a trait predicate")
.map_bound(|t| t.trait_ref);
let mut obligations = Vec::new();
@@ -218,7 +215,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_param_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
param: ty::PolyTraitRef<'tcx>,
) -> Vec<PredicateObligation<'tcx>> {
debug!(?obligation, ?param, "confirm_param_candidate");
@@ -241,9 +238,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_builtin_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
has_nested: bool,
- ) -> ImplSourceBuiltinData<PredicateObligation<'tcx>> {
+ ) -> Vec<PredicateObligation<'tcx>> {
debug!(?obligation, ?has_nested, "confirm_builtin_candidate");
let lang_items = self.tcx().lang_items();
@@ -276,14 +273,63 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?obligations);
- ImplSourceBuiltinData { nested: obligations }
+ obligations
}
+ #[instrument(level = "debug", skip(self))]
fn confirm_transmutability_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
- ) -> Result<ImplSourceBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
- debug!(?obligation, "confirm_transmutability_candidate");
+ obligation: &PolyTraitObligation<'tcx>,
+ ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ use rustc_transmute::{Answer, Condition};
+ #[instrument(level = "debug", skip(tcx, obligation, predicate))]
+ fn flatten_answer_tree<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
+ predicate: TraitPredicate<'tcx>,
+ cond: Condition<rustc_transmute::layout::rustc::Ref<'tcx>>,
+ ) -> Vec<PredicateObligation<'tcx>> {
+ match cond {
+ // FIXME(bryangarza): Add separate `IfAny` case, instead of treating as `IfAll`
+ // Not possible until the trait solver supports disjunctions of obligations
+ Condition::IfAll(conds) | Condition::IfAny(conds) => conds
+ .into_iter()
+ .flat_map(|cond| flatten_answer_tree(tcx, obligation, predicate, cond))
+ .collect(),
+ Condition::IfTransmutable { src, dst } => {
+ let trait_def_id = obligation.predicate.def_id();
+ let scope = predicate.trait_ref.substs.type_at(2);
+ let assume_const = predicate.trait_ref.substs.const_at(3);
+ let make_obl = |from_ty, to_ty| {
+ let trait_ref1 = ty::TraitRef::new(
+ tcx,
+ trait_def_id,
+ [
+ ty::GenericArg::from(to_ty),
+ ty::GenericArg::from(from_ty),
+ ty::GenericArg::from(scope),
+ ty::GenericArg::from(assume_const),
+ ],
+ );
+ Obligation::with_depth(
+ tcx,
+ obligation.cause.clone(),
+ obligation.recursion_depth + 1,
+ obligation.param_env,
+ trait_ref1,
+ )
+ };
+
+ // If Dst is mutable, check bidirectionally.
+ // For example, transmuting bool -> u8 is OK as long as you can't update that u8
+ // to be > 1, because you could later transmute the u8 back to a bool and get UB.
+ match dst.mutability {
+ Mutability::Not => vec![make_obl(src.ty, dst.ty)],
+ Mutability::Mut => vec![make_obl(src.ty, dst.ty), make_obl(dst.ty, src.ty)],
+ }
+ }
+ }
+ }
// We erase regions here because transmutability calls layout queries,
// which does not handle inference regions and doesn't particularly
@@ -301,21 +347,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Err(Unimplemented);
};
+ let dst = predicate.trait_ref.substs.type_at(0);
+ let src = predicate.trait_ref.substs.type_at(1);
+ debug!(?src, ?dst);
let mut transmute_env = rustc_transmute::TransmuteTypeEnv::new(self.infcx);
let maybe_transmutable = transmute_env.is_transmutable(
obligation.cause.clone(),
- rustc_transmute::Types {
- dst: predicate.trait_ref.substs.type_at(0),
- src: predicate.trait_ref.substs.type_at(1),
- },
+ rustc_transmute::Types { dst, src },
predicate.trait_ref.substs.type_at(2),
assume,
);
- match maybe_transmutable {
- rustc_transmute::Answer::Yes => Ok(ImplSourceBuiltinData { nested: vec![] }),
- _ => Err(Unimplemented),
- }
+ let fully_flattened = match maybe_transmutable {
+ Answer::No(_) => Err(Unimplemented)?,
+ Answer::If(cond) => flatten_answer_tree(self.tcx(), obligation, predicate, cond),
+ Answer::Yes => vec![],
+ };
+
+ debug!(?fully_flattened);
+ Ok(fully_flattened)
}
/// This handles the case where an `auto trait Foo` impl is being used.
@@ -325,22 +375,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
fn confirm_auto_impl_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
- ) -> ImplSourceAutoImplData<PredicateObligation<'tcx>> {
+ obligation: &PolyTraitObligation<'tcx>,
+ ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
debug!(?obligation, "confirm_auto_impl_candidate");
let self_ty = self.infcx.shallow_resolve(obligation.predicate.self_ty());
- let types = self.constituent_types_for_ty(self_ty);
- self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types)
+ let types = self.constituent_types_for_ty(self_ty)?;
+ Ok(self.vtable_auto_impl(obligation, obligation.predicate.def_id(), types))
}
/// See `confirm_auto_impl_candidate`.
fn vtable_auto_impl(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
trait_def_id: DefId,
nested: ty::Binder<'tcx, Vec<Ty<'tcx>>>,
- ) -> ImplSourceAutoImplData<PredicateObligation<'tcx>> {
+ ) -> Vec<PredicateObligation<'tcx>> {
debug!(?nested, "vtable_auto_impl");
ensure_sufficient_stack(|| {
let cause = obligation.derived_cause(BuiltinDerivedObligation);
@@ -370,13 +420,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?obligations, "vtable_auto_impl");
- ImplSourceAutoImplData { trait_def_id, nested: obligations }
+ obligations
})
}
fn confirm_impl_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
impl_def_id: DefId,
) -> ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>> {
debug!(?obligation, ?impl_def_id, "confirm_impl_candidate");
@@ -431,9 +481,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_object_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
index: usize,
- ) -> Result<ImplSourceObjectData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ ) -> Result<ImplSourceObjectData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();
debug!(?obligation, ?index, "confirm_object_candidate");
@@ -527,9 +577,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
substs.extend(trait_predicate.trait_ref.substs.iter());
let mut bound_vars: smallvec::SmallVec<[ty::BoundVariableKind; 8]> =
smallvec::SmallVec::with_capacity(
- bound.0.kind().bound_vars().len() + defs.count(),
+ bound.skip_binder().kind().bound_vars().len() + defs.count(),
);
- bound_vars.extend(bound.0.kind().bound_vars().into_iter());
+ bound_vars.extend(bound.skip_binder().kind().bound_vars().into_iter());
InternalSubsts::fill_single(&mut substs, defs, &mut |param, _| match param
.kind
{
@@ -537,7 +587,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
bound_vars.push(bound_var);
- tcx.mk_bound(
+ Ty::new_bound(
+ tcx,
ty::INNERMOST,
ty::BoundTy {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
@@ -550,7 +601,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Region(kind);
bound_vars.push(bound_var);
- tcx.mk_re_late_bound(
+ ty::Region::new_late_bound(
+ tcx,
ty::INNERMOST,
ty::BoundRegion {
var: ty::BoundVar::from_usize(bound_vars.len() - 1),
@@ -562,11 +614,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
GenericParamDefKind::Const { .. } => {
let bound_var = ty::BoundVariableKind::Const;
bound_vars.push(bound_var);
- tcx.mk_const(
- ty::ConstKind::Bound(
- ty::INNERMOST,
- ty::BoundVar::from_usize(bound_vars.len() - 1),
- ),
+ ty::Const::new_bound(
+ tcx,
+ ty::INNERMOST,
+ ty::BoundVar::from_usize(bound_vars.len() - 1),
tcx.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic"),
@@ -578,7 +629,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let assoc_ty_substs = tcx.mk_substs(&substs);
let bound =
bound.map_bound(|b| b.kind().skip_binder()).subst(tcx, assoc_ty_substs);
- tcx.mk_predicate(ty::Binder::bind_with_vars(bound, bound_vars))
+ ty::Binder::bind_with_vars(bound, bound_vars).to_predicate(tcx)
};
let normalized_bound = normalize_with_depth_to(
self,
@@ -599,15 +650,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
(unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
);
- Ok(ImplSourceObjectData { upcast_trait_ref, vtable_base, nested })
+ Ok(ImplSourceObjectData { vtable_base, nested })
}
fn confirm_fn_pointer_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
is_const: bool,
- ) -> Result<ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>>
- {
+ ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
debug!(?obligation, "confirm_fn_pointer_candidate");
let tcx = self.tcx();
@@ -659,16 +709,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let tr = ty::TraitRef::from_lang_item(self.tcx(), LangItem::Sized, cause.span, [output_ty]);
nested.push(Obligation::new(self.infcx.tcx, cause, obligation.param_env, tr));
- Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested })
+ Ok(nested)
}
fn confirm_trait_alias_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
- ) -> ImplSourceTraitAliasData<'tcx, PredicateObligation<'tcx>> {
+ obligation: &PolyTraitObligation<'tcx>,
+ ) -> Vec<PredicateObligation<'tcx>> {
debug!(?obligation, "confirm_trait_alias_candidate");
- let alias_def_id = obligation.predicate.def_id();
let predicate = self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
let trait_ref = predicate.trait_ref;
let trait_def_id = trait_ref.def_id;
@@ -685,14 +734,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?trait_def_id, ?trait_obligations, "trait alias obligations");
- ImplSourceTraitAliasData { alias_def_id, substs, nested: trait_obligations }
+ trait_obligations
}
fn confirm_generator_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
- ) -> Result<ImplSourceGeneratorData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>>
- {
+ obligation: &PolyTraitObligation<'tcx>,
+ ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// Okay to skip binder because the substs on generator types never
// touch bound regions, they just capture the in-scope
// type/region parameters.
@@ -725,13 +773,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
debug!(?trait_ref, ?nested, "generator candidate obligations");
- Ok(ImplSourceGeneratorData { generator_def_id, substs, nested })
+ Ok(nested)
}
fn confirm_future_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
- ) -> Result<ImplSourceFutureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ obligation: &PolyTraitObligation<'tcx>,
+ ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// Okay to skip binder because the substs on generator types never
// touch bound regions, they just capture the in-scope
// type/region parameters.
@@ -755,14 +803,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
debug!(?trait_ref, ?nested, "future candidate obligations");
- Ok(ImplSourceFutureData { generator_def_id, substs, nested })
+ Ok(nested)
}
#[instrument(skip(self), level = "debug")]
fn confirm_closure_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
- ) -> Result<ImplSourceClosureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ obligation: &PolyTraitObligation<'tcx>,
+ ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let kind = self
.tcx()
.fn_trait_kind_from_def_id(obligation.predicate.def_id())
@@ -781,15 +829,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations");
- // FIXME: Chalk
- if self.tcx().sess.opts.unstable_opts.trait_solver != TraitSolver::Chalk {
- nested.push(obligation.with(
- self.tcx(),
- ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)),
- ));
- }
+ nested.push(obligation.with(
+ self.tcx(),
+ ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)),
+ ));
- Ok(ImplSourceClosureData { closure_def_id, substs, nested })
+ Ok(nested)
}
/// In the case of closure types and fn pointers,
@@ -820,7 +865,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(skip(self), level = "trace")]
fn confirm_poly_trait_refs(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
self_ty_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let obligation_trait_ref = obligation.predicate.to_poly_trait_ref();
@@ -855,10 +900,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_trait_upcasting_unsize_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
idx: usize,
- ) -> Result<ImplSourceTraitUpcastingData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>>
- {
+ ) -> Result<ImplSourceTraitUpcastingData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();
// `assemble_candidates_for_unsizing` should ensure there are no late-bound
@@ -903,7 +947,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map(ty::Binder::dummy),
);
let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
- let source_trait = tcx.mk_dynamic(existential_predicates, r_b, repr_a);
+ let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, repr_a);
// Require that the traits involved in this upcast are **equal**;
// only the **lifetime bound** is changed.
@@ -955,13 +999,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let vtable_vptr_slot =
prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback).unwrap();
- Ok(ImplSourceTraitUpcastingData { upcast_trait_ref, vtable_vptr_slot, nested })
+ Ok(ImplSourceTraitUpcastingData { vtable_vptr_slot, nested })
}
fn confirm_builtin_unsize_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
- ) -> Result<ImplSourceBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ obligation: &PolyTraitObligation<'tcx>,
+ ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
let tcx = self.tcx();
// `assemble_candidates_for_unsizing` should ensure there are no late-bound
@@ -996,7 +1040,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map(ty::Binder::dummy),
);
let existential_predicates = tcx.mk_poly_existential_predicates_from_iter(iter);
- let source_trait = tcx.mk_dynamic(existential_predicates, r_b, dyn_a);
+ let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a);
// Require that the traits involved in this upcast are **equal**;
// only the **lifetime bound** is changed.
@@ -1054,12 +1098,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation.cause.span,
[source],
);
- nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
+ nested.push(predicate_to_obligation(tr.to_predicate(tcx)));
// If the type is `Foo + 'a`, ensure that the type
// being cast to `Foo + 'a` outlives `'a`:
let outlives = ty::OutlivesPredicate(source, r);
- nested.push(predicate_to_obligation(ty::Binder::dummy(outlives).to_predicate(tcx)));
+ nested.push(predicate_to_obligation(
+ ty::Binder::dummy(ty::ClauseKind::TypeOutlives(outlives)).to_predicate(tcx),
+ ));
}
// `[T; n]` -> `[T]`
@@ -1079,12 +1125,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Err(Unimplemented);
}
- let tail_field = def
- .non_enum_variant()
- .fields
- .raw
- .last()
- .expect("expected unsized ADT to have a tail field");
+ let tail_field = def.non_enum_variant().tail();
let tail_field_ty = tcx.type_of(tail_field.did);
// Extract `TailField<T>` and `TailField<U>` from `Struct<T>` and `Struct<U>`,
@@ -1112,7 +1153,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let substs = tcx.mk_substs_from_iter(substs_a.iter().enumerate().map(|(i, k)| {
if unsizing_params.contains(i as u32) { substs_b[i] } else { k }
}));
- let new_struct = tcx.mk_adt(def, substs);
+ let new_struct = Ty::new_adt(tcx, def, substs);
let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
@@ -1143,7 +1184,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Check that the source tuple with the target's
// last element is equal to the target.
let new_tuple =
- tcx.mk_tup_from_iter(a_mid.iter().copied().chain(iter::once(b_last)));
+ Ty::new_tup_from_iter(tcx, a_mid.iter().copied().chain(iter::once(b_last)));
let InferOk { obligations, .. } = self
.infcx
.at(&obligation.cause, obligation.param_env)
@@ -1162,17 +1203,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
_ => bug!("source: {source}, target: {target}"),
};
- Ok(ImplSourceBuiltinData { nested })
+ Ok(nested)
}
fn confirm_const_destruct_candidate(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
impl_def_id: Option<DefId>,
- ) -> Result<ImplSourceConstDestructData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+ ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
// `~const Destruct` in a non-const environment is always trivially true, since our type is `Drop`
if !obligation.is_const() {
- return Ok(ImplSourceConstDestructData { nested: vec![] });
+ return Ok(vec![]);
}
let drop_trait = self.tcx().require_lang_item(LangItem::Drop, None);
@@ -1326,6 +1367,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- Ok(ImplSourceConstDestructData { nested })
+ Ok(nested)
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 3baf1c97c..7f31ab751 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -15,11 +15,12 @@ use super::util::closure_trait_ref_and_return_type;
use super::wf;
use super::{
ErrorReporting, ImplDerivedObligation, ImplDerivedObligationCause, Normalized, Obligation,
- ObligationCause, ObligationCauseCode, Overflow, PredicateObligation, Selection, SelectionError,
- SelectionResult, TraitObligation, TraitQueryMode,
+ ObligationCause, ObligationCauseCode, Overflow, PolyTraitObligation, PredicateObligation,
+ Selection, SelectionError, SelectionResult, TraitQueryMode,
};
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
+use crate::solve::InferCtxtSelectExt;
use crate::traits::error_reporting::TypeErrCtxtExt;
use crate::traits::project::try_normalize_with_depth_to;
use crate::traits::project::ProjectAndUnifyResult;
@@ -33,8 +34,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::DefineOpaqueTypes;
use rustc_infer::infer::LateBoundRegionConversionTime;
-use rustc_infer::traits::TraitEngine;
-use rustc_infer::traits::TraitEngineExt;
+use rustc_infer::traits::TraitObligation;
use rustc_middle::dep_graph::{DepKind, DepNodeIndex};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@@ -123,7 +123,7 @@ pub struct SelectionContext<'cx, 'tcx> {
// A stack that walks back up the stack frame.
struct TraitObligationStack<'prev, 'tcx> {
- obligation: &'prev TraitObligation<'tcx>,
+ obligation: &'prev PolyTraitObligation<'tcx>,
/// The trait predicate from `obligation` but "freshened" with the
/// selection-context's freshener. Used to check for recursion.
@@ -260,10 +260,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// Attempts to satisfy the obligation. If successful, this will affect the surrounding
/// type environment by performing unification.
#[instrument(level = "debug", skip(self), ret)]
- pub fn select(
+ pub fn poly_select(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
) -> SelectionResult<'tcx, Selection<'tcx>> {
+ if self.infcx.next_trait_solver() {
+ return self.infcx.select_in_new_trait_solver(obligation);
+ }
+
let candidate = match self.select_from_obligation(obligation) {
Err(SelectionError::Overflow(OverflowError::Canonical)) => {
// In standard mode, overflow must have been caught and reported
@@ -290,9 +294,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- pub(crate) fn select_from_obligation(
+ pub fn select(
&mut self,
obligation: &TraitObligation<'tcx>,
+ ) -> SelectionResult<'tcx, Selection<'tcx>> {
+ self.poly_select(&Obligation {
+ cause: obligation.cause.clone(),
+ param_env: obligation.param_env,
+ predicate: ty::Binder::dummy(obligation.predicate),
+ recursion_depth: obligation.recursion_depth,
+ })
+ }
+
+ fn select_from_obligation(
+ &mut self,
+ obligation: &PolyTraitObligation<'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
debug_assert!(!obligation.predicate.has_escaping_bound_vars());
@@ -307,6 +323,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
stack: &TraitObligationStack<'o, 'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
+ debug_assert!(!self.infcx.next_trait_solver());
// Watch out for overflow. This intentionally bypasses (and does
// not update) the cache.
self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
@@ -365,7 +382,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
if !candidate_set.ambiguous && no_candidates_apply {
- let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
+ let trait_ref = self.infcx.resolve_vars_if_possible(
+ stack.obligation.predicate.skip_binder().trait_ref,
+ );
if !trait_ref.references_error() {
let self_ty = trait_ref.self_ty();
let (trait_desc, self_desc) = with_no_trimmed_paths!({
@@ -516,37 +535,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// The result is "true" if the obligation *may* hold and "false" if
// we can be sure it does not.
- /// Evaluates whether the obligation `obligation` can be satisfied (by any means).
- pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool {
- debug!(?obligation, "predicate_may_hold_fatal");
-
- // This fatal query is a stopgap that should only be used in standard mode,
- // where we do not expect overflow to be propagated.
- assert!(self.query_mode == TraitQueryMode::Standard);
-
- self.evaluate_root_obligation(obligation)
- .expect("Overflow should be caught earlier in standard query mode")
- .may_apply()
- }
-
/// Evaluates whether the obligation `obligation` can be satisfied
/// and returns an `EvaluationResult`. This is meant for the
/// *initial* call.
+ ///
+ /// Do not use this directly, use `infcx.evaluate_obligation` instead.
pub fn evaluate_root_obligation(
&mut self,
obligation: &PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
+ debug_assert!(!self.infcx.next_trait_solver());
self.evaluation_probe(|this| {
let goal =
this.infcx.resolve_vars_if_possible((obligation.predicate, obligation.param_env));
- let mut result = if this.tcx().trait_solver_next() {
- this.evaluate_predicates_recursively_in_new_solver([obligation.clone()])?
- } else {
- this.evaluate_predicate_recursively(
- TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
- obligation.clone(),
- )?
- };
+ let mut result = this.evaluate_predicate_recursively(
+ TraitObligationStackList::empty(&ProvisionalEvaluationCache::default()),
+ obligation.clone(),
+ )?;
// If the predicate has done any inference, then downgrade the
// result to ambiguous.
if this.infcx.shallow_resolve(goal) != goal {
@@ -561,9 +566,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
op: impl FnOnce(&mut Self) -> Result<EvaluationResult, OverflowError>,
) -> Result<EvaluationResult, OverflowError> {
self.infcx.probe(|snapshot| -> Result<EvaluationResult, OverflowError> {
+ let outer_universe = self.infcx.universe();
let result = op(self)?;
- match self.infcx.leak_check(true, snapshot) {
+ match self.infcx.leak_check(outer_universe, Some(snapshot)) {
Ok(()) => {}
Err(_) => return Ok(EvaluatedToErr),
}
@@ -572,9 +578,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
return Ok(result.max(EvaluatedToOkModuloOpaqueTypes));
}
- match self.infcx.region_constraints_added_in_snapshot(snapshot) {
- None => Ok(result),
- Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),
+ if self.infcx.region_constraints_added_in_snapshot(snapshot) {
+ Ok(result.max(EvaluatedToOkModuloRegions))
+ } else {
+ Ok(result)
}
})
}
@@ -591,42 +598,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
where
I: IntoIterator<Item = PredicateObligation<'tcx>> + std::fmt::Debug,
{
- if self.tcx().trait_solver_next() {
- self.evaluate_predicates_recursively_in_new_solver(predicates)
- } else {
- let mut result = EvaluatedToOk;
- for mut obligation in predicates {
- obligation.set_depth_from_parent(stack.depth());
- let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
- if let EvaluatedToErr = eval {
- // fast-path - EvaluatedToErr is the top of the lattice,
- // so we don't need to look on the other predicates.
- return Ok(EvaluatedToErr);
- } else {
- result = cmp::max(result, eval);
- }
+ let mut result = EvaluatedToOk;
+ for mut obligation in predicates {
+ obligation.set_depth_from_parent(stack.depth());
+ let eval = self.evaluate_predicate_recursively(stack, obligation.clone())?;
+ if let EvaluatedToErr = eval {
+ // fast-path - EvaluatedToErr is the top of the lattice,
+ // so we don't need to look on the other predicates.
+ return Ok(EvaluatedToErr);
+ } else {
+ result = cmp::max(result, eval);
}
- Ok(result)
}
- }
-
- /// Evaluates the predicates using the new solver when `-Ztrait-solver=next` is enabled
- fn evaluate_predicates_recursively_in_new_solver(
- &mut self,
- predicates: impl IntoIterator<Item = PredicateObligation<'tcx>>,
- ) -> Result<EvaluationResult, OverflowError> {
- let mut fulfill_cx = crate::solve::FulfillmentCtxt::new();
- fulfill_cx.register_predicate_obligations(self.infcx, predicates);
- // True errors
- // FIXME(-Ztrait-solver=next): Overflows are reported as ambig here, is that OK?
- if !fulfill_cx.select_where_possible(self.infcx).is_empty() {
- return Ok(EvaluatedToErr);
- }
- if !fulfill_cx.select_all_or_error(self.infcx).is_empty() {
- return Ok(EvaluatedToAmbig);
- }
- // Regions and opaques are handled in the `evaluation_probe` by looking at the snapshot
- Ok(EvaluatedToOk)
+ Ok(result)
}
#[instrument(
@@ -640,7 +624,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
previous_stack: TraitObligationStackList<'o, 'tcx>,
obligation: PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
- // `previous_stack` stores a `TraitObligation`, while `obligation` is
+ debug_assert!(!self.infcx.next_trait_solver());
+ // `previous_stack` stores a `PolyTraitObligation`, while `obligation` is
// a `PredicateObligation`. These are distinct types, so we can't
// use any `Option` combinator method that would force them to be
// the same.
@@ -652,7 +637,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ensure_sufficient_stack(|| {
let bound_predicate = obligation.predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(t)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => {
let t = bound_predicate.rebind(t);
debug_assert!(!t.has_escaping_bound_vars());
let obligation = obligation.with(self.tcx(), t);
@@ -683,7 +668,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- ty::PredicateKind::WellFormed(arg) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
// So, there is a bit going on here. First, `WellFormed` predicates
// are coinductive, like trait predicates with auto traits.
// This means that we need to detect if we have recursively
@@ -769,7 +754,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(pred)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(pred)) => {
// A global type with no free lifetimes or generic parameters
// outlives anything.
if pred.0.has_free_regions()
@@ -783,7 +768,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {
// We do not consider region relationships when evaluating trait matches.
Ok(EvaluatedToOkModuloRegions)
}
@@ -796,7 +781,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- ty::PredicateKind::Clause(ty::Clause::Projection(data)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
let data = bound_predicate.rebind(data);
let project_obligation = obligation.with(self.tcx(), data);
match project::poly_project_and_unify_type(self, &project_obligation) {
@@ -871,7 +856,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- ty::PredicateKind::ConstEvaluatable(uv) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
match const_evaluatable::is_const_evaluatable(
self.infcx,
uv,
@@ -901,7 +886,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
use rustc_hir::def::DefKind;
- use ty::ConstKind::Unevaluated;
+ use ty::Unevaluated;
match (c1.kind(), c2.kind()) {
(Unevaluated(a), Unevaluated(b))
if a.def == b.def && tcx.def_kind(a.def) == DefKind::AssocConst =>
@@ -976,14 +961,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
}
- ty::PredicateKind::TypeWellFormedFromEnv(..) => {
- bug!("TypeWellFormedFromEnv is only used for chalk")
- }
ty::PredicateKind::AliasRelate(..) => {
bug!("AliasRelate is only used for new solver")
}
ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig),
- ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, ty)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
match self.infcx.at(&obligation.cause, obligation.param_env).eq(
DefineOpaqueTypes::No,
ct.ty(),
@@ -1004,7 +986,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn evaluate_trait_predicate_recursively<'o>(
&mut self,
previous_stack: TraitObligationStackList<'o, 'tcx>,
- mut obligation: TraitObligation<'tcx>,
+ mut obligation: PolyTraitObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
if !self.is_intercrate()
&& obligation.is_global()
@@ -1186,6 +1168,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
stack: &TraitObligationStack<'o, 'tcx>,
) -> Result<EvaluationResult, OverflowError> {
+ debug_assert!(!self.infcx.next_trait_solver());
// In intercrate mode, whenever any of the generics are unbound,
// there can always be an impl. Even if there are no impls in
// this crate, perhaps the type would be unified with
@@ -1409,7 +1392,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn filter_impls(
&mut self,
candidates: Vec<SelectionCandidate<'tcx>>,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
) -> Vec<SelectionCandidate<'tcx>> {
trace!("{candidates:#?}");
let tcx = self.tcx();
@@ -1472,7 +1455,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn filter_reservation_impls(
&mut self,
candidate: SelectionCandidate<'tcx>,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
let tcx = self.tcx();
// Treat reservation impls as ambiguity.
@@ -1644,7 +1627,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
#[instrument(level = "debug", skip(self), ret)]
fn match_projection_obligation_against_definition_bounds(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
) -> smallvec::SmallVec<[(usize, ty::BoundConstness); 2]> {
let poly_trait_predicate = self.infcx.resolve_vars_if_possible(obligation.predicate);
let placeholder_trait_predicate =
@@ -1677,9 +1660,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.enumerate()
.filter_map(|(idx, bound)| {
let bound_predicate = bound.kind();
- if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) =
- bound_predicate.skip_binder()
- {
+ if let ty::ClauseKind::Trait(pred) = bound_predicate.skip_binder() {
let bound = bound_predicate.rebind(pred.trait_ref);
if self.infcx.probe(|_| {
match self.match_normalize_trait_ref(
@@ -1709,7 +1690,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// variables or placeholders, the normalized bound is returned.
fn match_normalize_trait_ref(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
trait_bound: ty::PolyTraitRef<'tcx>,
placeholder_trait_ref: ty::TraitRef<'tcx>,
) -> Result<Option<ty::PolyTraitRef<'tcx>>, ()> {
@@ -2110,7 +2091,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
impl<'tcx> SelectionContext<'_, 'tcx> {
fn sized_conditions(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
) -> BuiltinImplConditions<'tcx> {
use self::BuiltinImplConditions::{Ambiguous, None, Where};
@@ -2149,13 +2130,11 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
ty::Adt(def, substs) => {
let sized_crit = def.sized_constraint(self.tcx());
// (*) binder moved here
- Where(obligation.predicate.rebind({
- sized_crit
- .0
- .iter()
- .map(|ty| sized_crit.rebind(*ty).subst(self.tcx(), substs))
- .collect()
- }))
+ Where(
+ obligation
+ .predicate
+ .rebind(sized_crit.subst_iter_copied(self.tcx(), substs).collect()),
+ )
}
ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => None,
@@ -2172,7 +2151,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
fn copy_clone_conditions(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
) -> BuiltinImplConditions<'tcx> {
// NOTE: binder moved to (*)
let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
@@ -2305,8 +2284,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
fn constituent_types_for_ty(
&self,
t: ty::Binder<'tcx, Ty<'tcx>>,
- ) -> ty::Binder<'tcx, Vec<Ty<'tcx>>> {
- match *t.skip_binder().kind() {
+ ) -> Result<ty::Binder<'tcx, Vec<Ty<'tcx>>>, SelectionError<'tcx>> {
+ Ok(match *t.skip_binder().kind() {
ty::Uint(_)
| ty::Int(_)
| ty::Bool
@@ -2319,13 +2298,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
| ty::Char => ty::Binder::dummy(Vec::new()),
// Treat this like `struct str([u8]);`
- ty::Str => ty::Binder::dummy(vec![self.tcx().mk_slice(self.tcx().types.u8)]),
+ ty::Str => ty::Binder::dummy(vec![Ty::new_slice(self.tcx(), self.tcx().types.u8)]),
ty::Placeholder(..)
| ty::Dynamic(..)
| ty::Param(..)
| ty::Foreign(..)
- | ty::Alias(ty::Projection | ty::Inherent, ..)
+ | ty::Alias(ty::Projection | ty::Inherent | ty::Weak, ..)
| ty::Bound(..)
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("asked to assemble constituent types of unexpected type: {:?}", t);
@@ -2370,12 +2349,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
+ let ty = self.tcx().type_of(def_id);
+ if ty.skip_binder().references_error() {
+ return Err(SelectionError::OpaqueTypeAutoTraitLeakageUnknown(def_id));
+ }
// We can resolve the `impl Trait` to its concrete type,
// which enforces a DAG between the functions requiring
// the auto trait bounds in question.
- t.rebind(vec![self.tcx().type_of(def_id).subst(self.tcx(), substs)])
+ t.rebind(vec![ty.subst(self.tcx(), substs)])
}
- }
+ })
}
fn collect_predicates_for_types(
@@ -2444,7 +2427,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
fn rematch_impl(
&mut self,
impl_def_id: DefId,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
) -> Normalized<'tcx, SubstsRef<'tcx>> {
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
@@ -2465,7 +2448,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
),
);
let value = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
- let err = self.tcx().ty_error(guar);
+ let err = Ty::new_error(self.tcx(), guar);
let value = value.fold_with(&mut BottomUpFolder {
tcx: self.tcx(),
ty_op: |_| err,
@@ -2482,7 +2465,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
&mut self,
impl_def_id: DefId,
impl_trait_ref: EarlyBinder<ty::TraitRef<'tcx>>,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
) -> Result<Normalized<'tcx, SubstsRef<'tcx>>, ()> {
let placeholder_obligation =
self.infcx.instantiate_binder_with_placeholders(obligation.predicate);
@@ -2540,7 +2523,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
/// result from the normalization.
fn match_where_clause_trait_ref(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
self.match_poly_trait_ref(obligation, where_clause_trait_ref)
@@ -2551,7 +2534,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn match_poly_trait_ref(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
self.infcx
@@ -2577,7 +2560,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
fn push_stack<'o>(
&mut self,
previous_stack: TraitObligationStackList<'o, 'tcx>,
- obligation: &'o TraitObligation<'tcx>,
+ obligation: &'o PolyTraitObligation<'tcx>,
) -> TraitObligationStack<'o, 'tcx> {
let fresh_trait_pred = obligation.predicate.fold_with(&mut self.freshener);
@@ -2596,7 +2579,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn closure_trait_ref_unnormalized(
&mut self,
- obligation: &TraitObligation<'tcx>,
+ obligation: &PolyTraitObligation<'tcx>,
substs: SubstsRef<'tcx>,
) -> ty::PolyTraitRef<'tcx> {
let closure_sig = substs.as_closure().sig();
@@ -2670,7 +2653,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
}))
})
};
- let predicate = normalize_with_depth_to(
+ let clause = normalize_with_depth_to(
self,
param_env,
cause.clone(),
@@ -2678,7 +2661,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
predicate,
&mut obligations,
);
- obligations.push(Obligation { cause, recursion_depth, param_env, predicate });
+ obligations.push(Obligation {
+ cause,
+ recursion_depth,
+ param_env,
+ predicate: clause.as_predicate(),
+ });
}
obligations
@@ -3029,7 +3017,7 @@ fn bind_generator_hidden_types_above<'tcx>(
kind: ty::BrAnon(None),
};
counter += 1;
- tcx.mk_re_late_bound(current_depth, br)
+ ty::Region::new_late_bound(tcx, current_depth, br)
}
r => bug!("unexpected region: {r:?}"),
})