summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/query
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/query')
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs43
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs38
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs6
6 files changed, 64 insertions, 32 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
index 0f21813bc..455b53bfb 100644
--- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs
@@ -31,6 +31,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
| ty::FnPtr(_)
| ty::Char
| ty::GeneratorWitness(..)
+ | ty::GeneratorWitnessMIR(..)
| ty::RawPtr(_)
| ty::Ref(..)
| ty::Str
diff --git a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
index 09b58894d..f183248f2 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -1,7 +1,9 @@
use rustc_middle::ty;
+use rustc_session::config::TraitSolver;
use crate::infer::canonical::OriginalQueryValues;
use crate::infer::InferCtxt;
+use crate::solve::{Certainty, Goal, InferCtxtEvalExt, MaybeCause};
use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
pub trait InferCtxtExt<'tcx> {
@@ -77,12 +79,38 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
_ => obligation.param_env.without_const(),
};
- let c_pred = self
- .canonicalize_query_keep_static(param_env.and(obligation.predicate), &mut _orig_values);
- // Run canonical query. If overflow occurs, rerun from scratch but this time
- // in standard trait query mode so that overflow is handled appropriately
- // within `SelectionContext`.
- self.tcx.at(obligation.cause.span()).evaluate_obligation(c_pred)
+ if self.tcx.sess.opts.unstable_opts.trait_solver != TraitSolver::Next {
+ let c_pred = self.canonicalize_query_keep_static(
+ param_env.and(obligation.predicate),
+ &mut _orig_values,
+ );
+ self.tcx.at(obligation.cause.span()).evaluate_obligation(c_pred)
+ } else {
+ self.probe(|snapshot| {
+ if let Ok((_, certainty)) =
+ self.evaluate_root_goal(Goal::new(self.tcx, param_env, obligation.predicate))
+ {
+ match certainty {
+ Certainty::Yes => {
+ if self.opaque_types_added_in_snapshot(snapshot) {
+ Ok(EvaluationResult::EvaluatedToOkModuloOpaqueTypes)
+ } else if self.region_constraints_added_in_snapshot(snapshot).is_some()
+ {
+ Ok(EvaluationResult::EvaluatedToOkModuloRegions)
+ } else {
+ Ok(EvaluationResult::EvaluatedToOk)
+ }
+ }
+ Certainty::Maybe(MaybeCause::Ambiguity) => {
+ Ok(EvaluationResult::EvaluatedToAmbig)
+ }
+ Certainty::Maybe(MaybeCause::Overflow) => Err(OverflowError::Canonical),
+ }
+ } else {
+ Ok(EvaluationResult::EvaluatedToErr)
+ }
+ })
+ }
}
// Helper function that canonicalizes and runs the query. If an
@@ -92,6 +120,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
&self,
obligation: &PredicateObligation<'tcx>,
) -> EvaluationResult {
+ // Run canonical query. If overflow occurs, rerun from scratch but this time
+ // in standard trait query mode so that overflow is handled appropriately
+ // within `SelectionContext`.
match self.evaluate_obligation(obligation) {
Ok(result) => result,
Err(OverflowError::Canonical) => {
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index 27247271d..b0cec3ce7 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::sso::SsoHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::traits::Normalized;
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
-use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitor};
use rustc_span::DUMMY_SP;
@@ -32,7 +32,7 @@ pub trait QueryNormalizeExt<'tcx> {
/// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure.
fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
where
- T: TypeFoldable<'tcx>;
+ T: TypeFoldable<TyCtxt<'tcx>>;
}
impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
@@ -51,7 +51,7 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
/// and other details are still "under development".
fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
where
- T: TypeFoldable<'tcx>,
+ T: TypeFoldable<TyCtxt<'tcx>>,
{
debug!(
"normalize::<{}>(value={:?}, param_env={:?}, cause={:?})",
@@ -115,8 +115,8 @@ struct MaxEscapingBoundVarVisitor {
escaping: usize,
}
-impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor {
- fn visit_binder<T: TypeVisitable<'tcx>>(
+impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
+ fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &ty::Binder<'tcx, T>,
) -> ControlFlow<Self::BreakTy> {
@@ -170,14 +170,14 @@ struct QueryNormalizer<'cx, 'tcx> {
universes: Vec<Option<ty::UniverseIndex>>,
}
-impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
+impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx> {
type Error = NoSolution;
- fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
- fn try_fold_binder<T: TypeFoldable<'tcx>>(
+ fn try_fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> Result<ty::Binder<'tcx, T>, Self::Error> {
@@ -214,18 +214,22 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
Reveal::All => {
let substs = substs.try_fold_with(self)?;
- let recursion_limit = self.tcx().recursion_limit();
+ let recursion_limit = self.interner().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) {
- self.infcx.err_ctxt().report_overflow_error(
- &ty,
- self.cause.span,
- true,
- |_| {},
- );
+ // A closure or generator may have itself as in its upvars.
+ // This should be checked handled by the recursion check for opaque
+ // types, but we may end up here before that check can happen.
+ // In that case, we delay a bug to mark the trip, and continue without
+ // revealing the opaque.
+ self.infcx
+ .err_ctxt()
+ .build_overflow_error(&ty, self.cause.span, true)
+ .delay_as_bug();
+ return ty.try_super_fold_with(self);
}
- let generic_ty = self.tcx().bound_type_of(def_id);
- let concrete_ty = generic_ty.subst(self.tcx(), substs);
+ let generic_ty = self.interner().type_of(def_id);
+ let concrete_ty = generic_ty.subst(self.interner(), substs);
self.anon_depth += 1;
if concrete_ty == ty {
bug!(
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 97002b461..9e8bc8bce 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -54,8 +54,8 @@ pub struct TypeOpOutput<'tcx, Op: TypeOp<'tcx>> {
/// which produces the resulting query region constraints.
///
/// [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
-pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<'tcx> + 'tcx {
- type QueryResponse: TypeFoldable<'tcx>;
+pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 'tcx {
+ type QueryResponse: TypeFoldable<TyCtxt<'tcx>>;
/// Give query the option for a simple fast path that never
/// actually hits the tcx cache lookup etc. Return `Some(r)` with
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
index 8f0b4de31..5b216c076 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs
@@ -1,7 +1,7 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::Fallible;
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt};
+use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use std::fmt;
pub use rustc_middle::traits::query::type_op::Normalize;
@@ -24,7 +24,7 @@ where
}
}
-pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<'tcx> + Lift<'tcx> + Copy {
+pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx> + Copy {
fn type_op_method(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
index 0d42cd825..21ef4e24f 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs
@@ -21,11 +21,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
tcx: TyCtxt<'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResponse> {
- if trivial_dropck_outlives(tcx, key.value.dropped_ty) {
- Some(DropckOutlivesResult::default())
- } else {
- None
- }
+ trivial_dropck_outlives(tcx, key.value.dropped_ty).then(DropckOutlivesResult::default)
}
fn perform_query(