summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/query
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:20:39 +0000
commit1376c5a617be5c25655d0d7cb63e3beaa5a6e026 (patch)
tree3bb8d61aee02bc7a15eab3f36e3b921afc2075d0 /compiler/rustc_trait_selection/src/traits/query
parentReleasing progress-linux version 1.69.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.tar.xz
rustc-1376c5a617be5c25655d0d7cb63e3beaa5a6e026.zip
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/query')
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/normalize.rs103
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs8
3 files changed, 60 insertions, 99 deletions
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 f183248f2..edbe2de81 100644
--- a/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs
@@ -1,9 +1,8 @@
+use rustc_infer::traits::{TraitEngine, TraitEngineExt};
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> {
@@ -79,37 +78,30 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
_ => obligation.param_env.without_const(),
};
- if self.tcx.sess.opts.unstable_opts.trait_solver != TraitSolver::Next {
+ if self.tcx.trait_solver_next() {
+ self.probe(|snapshot| {
+ let mut fulfill_cx = crate::solve::FulfillmentCtxt::new();
+ fulfill_cx.register_predicate_obligation(self, obligation.clone());
+ // True errors
+ // FIXME(-Ztrait-solver=next): Overflows are reported as ambig here, is that OK?
+ if !fulfill_cx.select_where_possible(self).is_empty() {
+ Ok(EvaluationResult::EvaluatedToErr)
+ } else if !fulfill_cx.select_all_or_error(self).is_empty() {
+ Ok(EvaluationResult::EvaluatedToAmbig)
+ } else 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)
+ }
+ })
+ } else {
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)
- }
- })
}
}
diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
index b0cec3ce7..a986a9b6a 100644
--- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs
@@ -197,23 +197,30 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
return Ok(*ty);
}
+ let (kind, data) = match *ty.kind() {
+ ty::Alias(kind, data) => (kind, data),
+ _ => {
+ let res = ty.try_super_fold_with(self)?;
+ self.cache.insert(ty, res);
+ return Ok(res);
+ }
+ };
+
// See note in `rustc_trait_selection::traits::project` about why we
// wait to fold the substs.
// Wrap this in a closure so we don't accidentally return from the outer function
- let res = match *ty.kind() {
+ let res = match kind {
// This is really important. While we *can* handle this, this has
// severe performance implications for large opaque types with
// late-bound regions. See `issue-88862` benchmark.
- ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
- if !substs.has_escaping_bound_vars() =>
- {
+ ty::Opaque if !data.substs.has_escaping_bound_vars() => {
// Only normalize `impl Trait` outside of type inference, usually in codegen.
match self.param_env.reveal() {
Reveal::UserFacing => ty.try_super_fold_with(self)?,
Reveal::All => {
- let substs = substs.try_fold_with(self)?;
+ let substs = data.substs.try_fold_with(self)?;
let recursion_limit = self.interner().recursion_limit();
if !recursion_limit.value_within_limit(self.anon_depth) {
// A closure or generator may have itself as in its upvars.
@@ -228,7 +235,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
return ty.try_super_fold_with(self);
}
- let generic_ty = self.interner().type_of(def_id);
+ let generic_ty = self.interner().type_of(data.def_id);
let concrete_ty = generic_ty.subst(self.interner(), substs);
self.anon_depth += 1;
if concrete_ty == ty {
@@ -248,62 +255,22 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
}
}
- ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
- // This branch is just an optimization: when we don't have escaping bound vars,
- // we don't need to replace them with placeholders (see branch below).
-
- let tcx = self.infcx.tcx;
- let data = data.try_fold_with(self)?;
-
- let mut orig_values = OriginalQueryValues::default();
- // HACK(matthewjasper) `'static` is special-cased in selection,
- // so we cannot canonicalize it.
- let c_data = self
- .infcx
- .canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
- debug!("QueryNormalizer: c_data = {:#?}", c_data);
- debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
- let result = tcx.normalize_projection_ty(c_data)?;
- // We don't expect ambiguity.
- if result.is_ambiguous() {
- // Rustdoc normalizes possibly not well-formed types, so only
- // treat this as a bug if we're not in rustdoc.
- if !tcx.sess.opts.actually_rustdoc {
- tcx.sess.delay_span_bug(
- DUMMY_SP,
- format!("unexpected ambiguity: {:?} {:?}", c_data, result),
- );
- }
- return Err(NoSolution);
- }
- let InferOk { value: result, obligations } =
- self.infcx.instantiate_query_response_and_region_obligations(
- self.cause,
- self.param_env,
- &orig_values,
- result,
- )?;
- debug!("QueryNormalizer: result = {:#?}", result);
- debug!("QueryNormalizer: obligations = {:#?}", obligations);
- self.obligations.extend(obligations);
-
- let res = result.normalized_ty;
- // `tcx.normalize_projection_ty` may normalize to a type that still has
- // unevaluated consts, so keep normalizing here if that's the case.
- if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
- res.try_super_fold_with(self)?
- } else {
- res
- }
- }
+ ty::Opaque => ty.try_super_fold_with(self)?,
- ty::Alias(ty::Projection, data) => {
+ ty::Projection => {
// See note in `rustc_trait_selection::traits::project`
let tcx = self.infcx.tcx;
let infcx = self.infcx;
- let (data, mapped_regions, mapped_types, mapped_consts) =
- BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
+ // Just an optimization: When we don't have escaping bound vars,
+ // we don't need to replace them with placeholders.
+ let (data, maps) = if data.has_escaping_bound_vars() {
+ let (data, mapped_regions, mapped_types, mapped_consts) =
+ BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
+ (data, Some((mapped_regions, mapped_types, mapped_consts)))
+ } else {
+ (data, None)
+ };
let data = data.try_fold_with(self)?;
let mut orig_values = OriginalQueryValues::default();
@@ -337,14 +304,18 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
debug!("QueryNormalizer: result = {:#?}", result);
debug!("QueryNormalizer: obligations = {:#?}", obligations);
self.obligations.extend(obligations);
- let res = PlaceholderReplacer::replace_placeholders(
- infcx,
- mapped_regions,
- mapped_types,
- mapped_consts,
- &self.universes,
- result.normalized_ty,
- );
+ let res = if let Some((mapped_regions, mapped_types, mapped_consts)) = maps {
+ PlaceholderReplacer::replace_placeholders(
+ infcx,
+ mapped_regions,
+ mapped_types,
+ mapped_consts,
+ &self.universes,
+ result.normalized_ty,
+ )
+ } else {
+ result.normalized_ty
+ };
// `tcx.normalize_projection_ty` may normalize to a type that still has
// unevaluated consts, so keep normalizing here if that's the case.
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
@@ -353,8 +324,6 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
res
}
}
-
- _ => ty.try_super_fold_with(self)?,
};
self.cache.insert(ty, res);
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 6bf3ed0d0..8f1b05c11 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -1,8 +1,8 @@
use crate::infer::canonical::query_response;
use crate::infer::{InferCtxt, InferOk};
-use crate::traits;
use crate::traits::query::type_op::TypeOpOutput;
use crate::traits::query::Fallible;
+use crate::traits::ObligationCtxt;
use rustc_infer::infer::region_constraints::RegionConstraintData;
use rustc_span::source_map::DUMMY_SP;
@@ -73,7 +73,9 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
);
let InferOk { value, obligations } = infcx.commit_if_ok(|_| op())?;
- let errors = traits::fully_solve_obligations(infcx, obligations);
+ let ocx = ObligationCtxt::new(infcx);
+ ocx.register_obligations(obligations);
+ let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.tcx.sess.diagnostic().delay_span_bug(
DUMMY_SP,
@@ -82,9 +84,7 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
}
let region_obligations = infcx.take_registered_region_obligations();
-
let region_constraint_data = infcx.take_and_reset_region_constraints();
-
let region_constraints = query_response::make_query_region_constraints(
infcx.tcx,
region_obligations