summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs')
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs68
1 files changed, 54 insertions, 14 deletions
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 9e8bc8bce..642fdec2d 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
@@ -2,13 +2,14 @@ use crate::infer::canonical::{
Canonical, CanonicalQueryResponse, OriginalQueryValues, QueryRegionConstraints,
};
use crate::infer::{InferCtxt, InferOk};
-use crate::traits::query::Fallible;
-use crate::traits::ObligationCause;
+use crate::traits::{ObligationCause, ObligationCtxt};
+use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::canonical::Certainty;
-use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::PredicateObligations;
+use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
+use rustc_span::Span;
use std::fmt;
pub mod ascribe_user_type;
@@ -22,6 +23,8 @@ pub mod subtype;
pub use rustc_middle::traits::query::type_op::*;
+use self::custom::scrape_region_constraints;
+
/// "Type ops" are used in NLL to perform some particular action and
/// extract out the resulting region constraints (or an error if it
/// cannot be completed).
@@ -32,7 +35,11 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
/// Processes the operation and all resulting obligations,
/// returning the final result along with any region constraints
/// (they will be given over to the NLL region solver).
- fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>;
+ fn fully_perform(
+ self,
+ infcx: &InferCtxt<'tcx>,
+ span: Span,
+ ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed>;
}
/// The output from performing a type op
@@ -74,18 +81,32 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
fn perform_query(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
- ) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>>;
+ ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution>;
+
+ /// In the new trait solver, we already do caching in the solver itself,
+ /// so there's no need to canonicalize and cache via the query system.
+ /// Additionally, even if we were to canonicalize, we'd still need to
+ /// make sure to feed it predefined opaque types and the defining anchor
+ /// and that would require duplicating all of the tcx queries. Instead,
+ /// just perform these ops locally.
+ fn perform_locally_in_new_solver(
+ ocx: &ObligationCtxt<'_, 'tcx>,
+ key: ParamEnvAnd<'tcx, Self>,
+ ) -> Result<Self::QueryResponse, NoSolution>;
fn fully_perform_into(
query_key: ParamEnvAnd<'tcx, Self>,
infcx: &InferCtxt<'tcx>,
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
- ) -> Fallible<(
- Self::QueryResponse,
- Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
- PredicateObligations<'tcx>,
- Certainty,
- )> {
+ ) -> Result<
+ (
+ Self::QueryResponse,
+ Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
+ PredicateObligations<'tcx>,
+ Certainty,
+ ),
+ NoSolution,
+ > {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
return Ok((result, None, vec![], Certainty::Proven));
}
@@ -120,10 +141,26 @@ where
type Output = Q::QueryResponse;
type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>;
- fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
+ fn fully_perform(
+ self,
+ infcx: &InferCtxt<'tcx>,
+ span: Span,
+ ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
+ if infcx.tcx.trait_solver_next() {
+ return Ok(scrape_region_constraints(
+ infcx,
+ |ocx| QueryTypeOp::perform_locally_in_new_solver(ocx, self),
+ "query type op",
+ span,
+ )?
+ .0);
+ }
+
let mut region_constraints = QueryRegionConstraints::default();
let (output, error_info, mut obligations, _) =
- Q::fully_perform_into(self, infcx, &mut region_constraints)?;
+ Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
+ infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}"))
+ })?;
// Typically, instantiating NLL query results does not
// create obligations. However, in some cases there
@@ -151,7 +188,10 @@ where
}
}
if !progress {
- return Err(NoSolution);
+ return Err(infcx.tcx.sess.delay_span_bug(
+ span,
+ format!("ambiguity processing {obligations:?} from {self:?}"),
+ ));
}
}