mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 00:03:43 +00:00
Use ObligationCtxt in favor of TraitEngine in many places
This commit is contained in:
parent
79734f1db8
commit
d9eb5232b6
@ -1,6 +1,6 @@
|
|||||||
use crate::errors::AutoDerefReachedRecursionLimit;
|
use crate::errors::AutoDerefReachedRecursionLimit;
|
||||||
|
use crate::traits;
|
||||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use crate::traits::{self, TraitEngine, TraitEngineExt};
|
|
||||||
use rustc_infer::infer::InferCtxt;
|
use rustc_infer::infer::InferCtxt;
|
||||||
use rustc_middle::ty::TypeVisitableExt;
|
use rustc_middle::ty::TypeVisitableExt;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
@ -8,7 +8,7 @@ use rustc_session::Limit;
|
|||||||
use rustc_span::def_id::LocalDefId;
|
use rustc_span::def_id::LocalDefId;
|
||||||
use rustc_span::def_id::LOCAL_CRATE;
|
use rustc_span::def_id::LOCAL_CRATE;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_trait_selection::traits::StructurallyNormalizeExt;
|
use rustc_trait_selection::traits::ObligationCtxt;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum AutoderefKind {
|
pub enum AutoderefKind {
|
||||||
@ -167,25 +167,19 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> {
|
) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> {
|
||||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.infcx);
|
let ocx = ObligationCtxt::new(self.infcx);
|
||||||
|
let Ok(normalized_ty) = ocx.structurally_normalize(
|
||||||
let cause = traits::ObligationCause::misc(self.span, self.body_id);
|
&traits::ObligationCause::misc(self.span, self.body_id),
|
||||||
let normalized_ty = match self
|
self.param_env,
|
||||||
.infcx
|
ty,
|
||||||
.at(&cause, self.param_env)
|
) else {
|
||||||
.structurally_normalize(ty, &mut *fulfill_cx)
|
// We shouldn't have errors here, except for evaluate/fulfill mismatches,
|
||||||
{
|
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
|
||||||
Ok(normalized_ty) => normalized_ty,
|
// by design).
|
||||||
Err(errors) => {
|
// FIXME(-Znext-solver): This *actually* shouldn't happen then.
|
||||||
// This shouldn't happen, except for evaluate/fulfill mismatches,
|
return None;
|
||||||
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
|
|
||||||
// by design).
|
|
||||||
debug!(?errors, "encountered errors while fulfilling");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
let errors = ocx.select_where_possible();
|
||||||
let errors = fulfill_cx.select_where_possible(self.infcx);
|
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
// This shouldn't happen, except for evaluate/fulfill mismatches,
|
// This shouldn't happen, except for evaluate/fulfill mismatches,
|
||||||
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
|
// but that's not a reason for an ICE (`predicate_may_hold` is conservative
|
||||||
@ -194,7 +188,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some((normalized_ty, fulfill_cx.pending_obligations()))
|
Some((normalized_ty, ocx.pending_obligations()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the final type we ended up with, which may be an inference
|
/// Returns the final type we ended up with, which may be an inference
|
||||||
|
@ -45,8 +45,7 @@ use rustc_hir::Expr;
|
|||||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||||
use rustc_infer::infer::type_variable::TypeVariableOrigin;
|
use rustc_infer::infer::type_variable::TypeVariableOrigin;
|
||||||
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
|
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
|
||||||
use rustc_infer::traits::TraitEngineExt as _;
|
use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause};
|
||||||
use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, TraitEngine};
|
|
||||||
use rustc_infer::traits::{Obligation, PredicateObligation};
|
use rustc_infer::traits::{Obligation, PredicateObligation};
|
||||||
use rustc_middle::lint::in_external_macro;
|
use rustc_middle::lint::in_external_macro;
|
||||||
use rustc_middle::traits::BuiltinImplSource;
|
use rustc_middle::traits::BuiltinImplSource;
|
||||||
@ -65,7 +64,6 @@ use rustc_trait_selection::infer::InferCtxtExt as _;
|
|||||||
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
use rustc_trait_selection::traits::error_reporting::suggestions::TypeErrCtxtExt;
|
||||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::TraitEngineExt as _;
|
|
||||||
use rustc_trait_selection::traits::{
|
use rustc_trait_selection::traits::{
|
||||||
self, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt,
|
self, NormalizeExt, ObligationCause, ObligationCauseCode, ObligationCtxt,
|
||||||
};
|
};
|
||||||
@ -164,11 +162,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
// Filter these cases out to make sure our coercion is more accurate.
|
// Filter these cases out to make sure our coercion is more accurate.
|
||||||
match res {
|
match res {
|
||||||
Ok(InferOk { value, obligations }) if self.next_trait_solver() => {
|
Ok(InferOk { value, obligations }) if self.next_trait_solver() => {
|
||||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self);
|
let ocx = ObligationCtxt::new(self);
|
||||||
fulfill_cx.register_predicate_obligations(self, obligations);
|
ocx.register_obligations(obligations);
|
||||||
let errs = fulfill_cx.select_where_possible(self);
|
if ocx.select_where_possible().is_empty() {
|
||||||
if errs.is_empty() {
|
Ok(InferOk { value, obligations: ocx.pending_obligations() })
|
||||||
Ok(InferOk { value, obligations: fulfill_cx.pending_obligations() })
|
|
||||||
} else {
|
} else {
|
||||||
Err(TypeError::Mismatch)
|
Err(TypeError::Mismatch)
|
||||||
}
|
}
|
||||||
@ -631,13 +628,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
// but we need to constrain vars before processing goals mentioning
|
// but we need to constrain vars before processing goals mentioning
|
||||||
// them.
|
// them.
|
||||||
Some(ty::PredicateKind::AliasRelate(..)) => {
|
Some(ty::PredicateKind::AliasRelate(..)) => {
|
||||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self);
|
let ocx = ObligationCtxt::new(self);
|
||||||
fulfill_cx.register_predicate_obligation(self, obligation);
|
ocx.register_obligation(obligation);
|
||||||
let errs = fulfill_cx.select_where_possible(self);
|
if !ocx.select_where_possible().is_empty() {
|
||||||
if !errs.is_empty() {
|
|
||||||
return Err(TypeError::Mismatch);
|
return Err(TypeError::Mismatch);
|
||||||
}
|
}
|
||||||
coercion.obligations.extend(fulfill_cx.pending_obligations());
|
coercion.obligations.extend(ocx.pending_obligations());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -206,6 +206,18 @@ impl<'tcx> FulfillmentError<'tcx> {
|
|||||||
) -> FulfillmentError<'tcx> {
|
) -> FulfillmentError<'tcx> {
|
||||||
FulfillmentError { obligation, code, root_obligation }
|
FulfillmentError { obligation, code, root_obligation }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_true_error(&self) -> bool {
|
||||||
|
match self.code {
|
||||||
|
FulfillmentErrorCode::SelectionError(_)
|
||||||
|
| FulfillmentErrorCode::ProjectionError(_)
|
||||||
|
| FulfillmentErrorCode::SubtypeError(_, _)
|
||||||
|
| FulfillmentErrorCode::ConstEquateError(_, _) => true,
|
||||||
|
FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> PolyTraitObligation<'tcx> {
|
impl<'tcx> PolyTraitObligation<'tcx> {
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||||
use crate::traits::{self, ObligationCtxt, SelectionContext, TraitEngineExt as _};
|
use crate::traits::{self, ObligationCtxt, SelectionContext};
|
||||||
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_infer::traits::{Obligation, TraitEngine, TraitEngineExt as _};
|
use rustc_infer::traits::Obligation;
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
use rustc_middle::arena::ArenaAllocatable;
|
use rustc_middle::arena::ArenaAllocatable;
|
||||||
use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
|
use rustc_middle::infer::canonical::{Canonical, CanonicalQueryResponse, QueryResponse};
|
||||||
@ -93,9 +94,9 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
ty::TraitRef::new(self.tcx, trait_def_id, [ty]),
|
ty::TraitRef::new(self.tcx, trait_def_id, [ty]),
|
||||||
)) {
|
)) {
|
||||||
Ok(Some(selection)) => {
|
Ok(Some(selection)) => {
|
||||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self);
|
let ocx = ObligationCtxt::new(self);
|
||||||
fulfill_cx.register_predicate_obligations(self, selection.nested_obligations());
|
ocx.register_obligations(selection.nested_obligations());
|
||||||
Some(fulfill_cx.select_all_or_error(self))
|
Some(ocx.select_all_or_error())
|
||||||
}
|
}
|
||||||
Ok(None) | Err(_) => None,
|
Ok(None) | Err(_) => None,
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ use rustc_ast_ir::visit::VisitorResult;
|
|||||||
use rustc_infer::infer::resolve::EagerResolver;
|
use rustc_infer::infer::resolve::EagerResolver;
|
||||||
use rustc_infer::infer::type_variable::TypeVariableOrigin;
|
use rustc_infer::infer::type_variable::TypeVariableOrigin;
|
||||||
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
||||||
use rustc_infer::traits::{TraitEngine, TraitEngineExt};
|
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
use rustc_middle::infer::unify_key::ConstVariableOrigin;
|
use rustc_middle::infer::unify_key::ConstVariableOrigin;
|
||||||
use rustc_middle::traits::query::NoSolution;
|
use rustc_middle::traits::query::NoSolution;
|
||||||
@ -26,9 +25,9 @@ use rustc_middle::ty::TypeFoldable;
|
|||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
|
||||||
use crate::solve::eval_ctxt::canonical;
|
use crate::solve::eval_ctxt::canonical;
|
||||||
use crate::solve::FulfillmentCtxt;
|
|
||||||
use crate::solve::{EvalCtxt, GoalEvaluationKind, GoalSource};
|
use crate::solve::{EvalCtxt, GoalEvaluationKind, GoalSource};
|
||||||
use crate::solve::{GenerateProofTree, InferCtxtEvalExt};
|
use crate::solve::{GenerateProofTree, InferCtxtEvalExt};
|
||||||
|
use crate::traits::ObligationCtxt;
|
||||||
|
|
||||||
pub struct InspectConfig {
|
pub struct InspectConfig {
|
||||||
pub max_depth: usize,
|
pub max_depth: usize,
|
||||||
@ -74,14 +73,13 @@ impl<'tcx> NormalizesToTermHack<'tcx> {
|
|||||||
.eq(DefineOpaqueTypes::Yes, self.term, self.unconstrained_term)
|
.eq(DefineOpaqueTypes::Yes, self.term, self.unconstrained_term)
|
||||||
.map_err(|_| NoSolution)
|
.map_err(|_| NoSolution)
|
||||||
.and_then(|InferOk { value: (), obligations }| {
|
.and_then(|InferOk { value: (), obligations }| {
|
||||||
let mut fulfill_cx = FulfillmentCtxt::new(infcx);
|
let ocx = ObligationCtxt::new(infcx);
|
||||||
fulfill_cx.register_predicate_obligations(infcx, obligations);
|
ocx.register_obligations(obligations);
|
||||||
if fulfill_cx.select_where_possible(infcx).is_empty() {
|
let errors = ocx.select_all_or_error();
|
||||||
if fulfill_cx.pending_obligations().is_empty() {
|
if errors.is_empty() {
|
||||||
Ok(Certainty::Yes)
|
Ok(Certainty::Yes)
|
||||||
} else {
|
} else if errors.iter().all(|e| !e.is_true_error()) {
|
||||||
Ok(Certainty::AMBIGUOUS)
|
Ok(Certainty::AMBIGUOUS)
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Err(NoSolution)
|
Err(NoSolution)
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,9 @@
|
|||||||
|
|
||||||
use crate::infer::outlives::env::OutlivesEnvironment;
|
use crate::infer::outlives::env::OutlivesEnvironment;
|
||||||
use crate::infer::InferOk;
|
use crate::infer::InferOk;
|
||||||
use crate::regions::InferCtxtRegionExt;
|
|
||||||
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
|
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
|
||||||
use crate::solve::{deeply_normalize_for_diagnostics, inspect, FulfillmentCtxt};
|
use crate::solve::{deeply_normalize_for_diagnostics, inspect};
|
||||||
use crate::traits::engine::TraitEngineExt as _;
|
|
||||||
use crate::traits::select::IntercrateAmbiguityCause;
|
use crate::traits::select::IntercrateAmbiguityCause;
|
||||||
use crate::traits::structural_normalize::StructurallyNormalizeExt;
|
|
||||||
use crate::traits::NormalizeExt;
|
use crate::traits::NormalizeExt;
|
||||||
use crate::traits::SkipLeakCheck;
|
use crate::traits::SkipLeakCheck;
|
||||||
use crate::traits::{
|
use crate::traits::{
|
||||||
@ -22,7 +19,7 @@ use rustc_errors::{Diag, EmissionGuarantee};
|
|||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
|
||||||
use rustc_infer::traits::{util, FulfillmentErrorCode, TraitEngine, TraitEngineExt};
|
use rustc_infer::traits::{util, FulfillmentErrorCode};
|
||||||
use rustc_middle::traits::query::NoSolution;
|
use rustc_middle::traits::query::NoSolution;
|
||||||
use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
|
use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
|
||||||
use rustc_middle::traits::specialization_graph::OverlapMode;
|
use rustc_middle::traits::specialization_graph::OverlapMode;
|
||||||
@ -35,6 +32,7 @@ use std::fmt::Debug;
|
|||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use super::error_reporting::suggest_new_overflow_limit;
|
use super::error_reporting::suggest_new_overflow_limit;
|
||||||
|
use super::ObligationCtxt;
|
||||||
|
|
||||||
/// Whether we do the orphan check relative to this crate or to some remote crate.
|
/// Whether we do the orphan check relative to this crate or to some remote crate.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@ -361,23 +359,27 @@ fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
|
|||||||
let infcx = selcx.infcx;
|
let infcx = selcx.infcx;
|
||||||
|
|
||||||
if infcx.next_trait_solver() {
|
if infcx.next_trait_solver() {
|
||||||
let mut fulfill_cx = FulfillmentCtxt::new(infcx);
|
let ocx = ObligationCtxt::new(infcx);
|
||||||
fulfill_cx.register_predicate_obligations(infcx, obligations.iter().cloned());
|
ocx.register_obligations(obligations.iter().cloned());
|
||||||
|
let errors_and_ambiguities = ocx.select_all_or_error();
|
||||||
// We only care about the obligations that are *definitely* true errors.
|
// We only care about the obligations that are *definitely* true errors.
|
||||||
// Ambiguities do not prove the disjointness of two impls.
|
// Ambiguities do not prove the disjointness of two impls.
|
||||||
let errors = fulfill_cx.select_where_possible(infcx);
|
let (errors, ambiguities): (Vec<_>, Vec<_>) =
|
||||||
|
errors_and_ambiguities.into_iter().partition(|error| error.is_true_error());
|
||||||
|
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
let overflow_errors = fulfill_cx.collect_remaining_errors(infcx);
|
IntersectionHasImpossibleObligations::No {
|
||||||
let overflowing_predicates = overflow_errors
|
overflowing_predicates: ambiguities
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|e| match e.code {
|
.filter(|error| {
|
||||||
FulfillmentErrorCode::Ambiguity { overflow: Some(true) } => true,
|
matches!(
|
||||||
_ => false,
|
error.code,
|
||||||
})
|
FulfillmentErrorCode::Ambiguity { overflow: Some(true) }
|
||||||
.map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate))
|
)
|
||||||
.collect();
|
})
|
||||||
IntersectionHasImpossibleObligations::No { overflowing_predicates }
|
.map(|e| infcx.resolve_vars_if_possible(e.obligation.predicate))
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
IntersectionHasImpossibleObligations::Yes
|
IntersectionHasImpossibleObligations::Yes
|
||||||
}
|
}
|
||||||
@ -589,13 +591,14 @@ fn try_prove_negated_where_clause<'tcx>(
|
|||||||
// Without this, we over-eagerly register coherence ambiguity candidates when
|
// Without this, we over-eagerly register coherence ambiguity candidates when
|
||||||
// impl candidates do exist.
|
// impl candidates do exist.
|
||||||
let ref infcx = root_infcx.fork_with_intercrate(false);
|
let ref infcx = root_infcx.fork_with_intercrate(false);
|
||||||
let mut fulfill_cx = FulfillmentCtxt::new(infcx);
|
let ocx = ObligationCtxt::new(infcx);
|
||||||
|
ocx.register_obligation(Obligation::new(
|
||||||
fulfill_cx.register_predicate_obligation(
|
infcx.tcx,
|
||||||
infcx,
|
ObligationCause::dummy(),
|
||||||
Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, negative_predicate),
|
param_env,
|
||||||
);
|
negative_predicate,
|
||||||
if !fulfill_cx.select_all_or_error(infcx).is_empty() {
|
));
|
||||||
|
if !ocx.select_all_or_error().is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,8 +606,7 @@ fn try_prove_negated_where_clause<'tcx>(
|
|||||||
// if that wasn't implemented just for LocalDefId, and we'd need to do
|
// if that wasn't implemented just for LocalDefId, and we'd need to do
|
||||||
// the normalization ourselves since this is totally fallible...
|
// the normalization ourselves since this is totally fallible...
|
||||||
let outlives_env = OutlivesEnvironment::new(param_env);
|
let outlives_env = OutlivesEnvironment::new(param_env);
|
||||||
|
let errors = ocx.resolve_regions(&outlives_env);
|
||||||
let errors = infcx.resolve_regions(&outlives_env);
|
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1129,22 +1131,17 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
|
|||||||
result: Ok(_),
|
result: Ok(_),
|
||||||
} = cand.kind()
|
} = cand.kind()
|
||||||
{
|
{
|
||||||
let lazily_normalize_ty = |ty: Ty<'tcx>| {
|
let lazily_normalize_ty = |mut ty: Ty<'tcx>| {
|
||||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(infcx);
|
|
||||||
if matches!(ty.kind(), ty::Alias(..)) {
|
if matches!(ty.kind(), ty::Alias(..)) {
|
||||||
// FIXME(-Znext-solver=coherence): we currently don't
|
let ocx = ObligationCtxt::new(infcx);
|
||||||
// normalize opaque types here, resulting in diverging behavior
|
ty = ocx
|
||||||
// for TAITs.
|
.structurally_normalize(&ObligationCause::dummy(), param_env, ty)
|
||||||
match infcx
|
.map_err(|_| ())?;
|
||||||
.at(&ObligationCause::dummy(), param_env)
|
if !ocx.select_where_possible().is_empty() {
|
||||||
.structurally_normalize(ty, &mut *fulfill_cx)
|
return Err(());
|
||||||
{
|
|
||||||
Ok(ty) => Ok(ty),
|
|
||||||
Err(_errs) => Err(()),
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Ok(ty)
|
|
||||||
}
|
}
|
||||||
|
Ok(ty)
|
||||||
};
|
};
|
||||||
|
|
||||||
infcx.probe(|_| {
|
infcx.probe(|_| {
|
||||||
|
@ -7,6 +7,7 @@ use crate::regions::InferCtxtRegionExt;
|
|||||||
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
|
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
|
||||||
use crate::traits::error_reporting::TypeErrCtxtExt;
|
use crate::traits::error_reporting::TypeErrCtxtExt;
|
||||||
use crate::traits::NormalizeExt;
|
use crate::traits::NormalizeExt;
|
||||||
|
use crate::traits::StructurallyNormalizeExt;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_errors::ErrorGuaranteed;
|
use rustc_errors::ErrorGuaranteed;
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
@ -15,6 +16,7 @@ use rustc_infer::infer::canonical::{
|
|||||||
Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse,
|
Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse,
|
||||||
};
|
};
|
||||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
|
use rustc_infer::infer::RegionResolutionError;
|
||||||
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
||||||
use rustc_infer::traits::{
|
use rustc_infer::traits::{
|
||||||
FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
|
FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
|
||||||
@ -117,6 +119,17 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
|||||||
self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut())
|
self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn structurally_normalize(
|
||||||
|
&self,
|
||||||
|
cause: &ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
value: Ty<'tcx>,
|
||||||
|
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
|
||||||
|
self.infcx
|
||||||
|
.at(cause, param_env)
|
||||||
|
.structurally_normalize(value, &mut **self.engine.borrow_mut())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn eq<T: ToTrace<'tcx>>(
|
pub fn eq<T: ToTrace<'tcx>>(
|
||||||
&self,
|
&self,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
@ -182,6 +195,11 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
|||||||
self.engine.borrow_mut().select_all_or_error(self.infcx)
|
self.engine.borrow_mut().select_all_or_error(self.infcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>> {
|
||||||
|
self.engine.borrow().pending_obligations()
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolves regions and reports errors.
|
/// Resolves regions and reports errors.
|
||||||
///
|
///
|
||||||
/// Takes ownership of the context as doing trait solving afterwards
|
/// Takes ownership of the context as doing trait solving afterwards
|
||||||
@ -199,6 +217,18 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Resolves regions and reports errors.
|
||||||
|
///
|
||||||
|
/// Takes ownership of the context as doing trait solving afterwards
|
||||||
|
/// will result in region constraints getting ignored.
|
||||||
|
#[must_use]
|
||||||
|
pub fn resolve_regions(
|
||||||
|
self,
|
||||||
|
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||||
|
) -> Vec<RegionResolutionError<'tcx>> {
|
||||||
|
self.infcx.resolve_regions(outlives_env)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn assumed_wf_types_and_report_errors(
|
pub fn assumed_wf_types_and_report_errors(
|
||||||
&self,
|
&self,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use rustc_infer::traits::{TraitEngine, TraitEngineExt};
|
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
|
|
||||||
use crate::infer::canonical::OriginalQueryValues;
|
use crate::infer::canonical::OriginalQueryValues;
|
||||||
use crate::infer::InferCtxt;
|
use crate::infer::InferCtxt;
|
||||||
use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext};
|
use crate::traits::{
|
||||||
|
EvaluationResult, ObligationCtxt, OverflowError, PredicateObligation, SelectionContext,
|
||||||
|
};
|
||||||
|
|
||||||
#[extension(pub trait InferCtxtExt<'tcx>)]
|
#[extension(pub trait InferCtxtExt<'tcx>)]
|
||||||
impl<'tcx> InferCtxt<'tcx> {
|
impl<'tcx> InferCtxt<'tcx> {
|
||||||
@ -67,21 +68,22 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
|
|
||||||
if self.next_trait_solver() {
|
if self.next_trait_solver() {
|
||||||
self.probe(|snapshot| {
|
self.probe(|snapshot| {
|
||||||
let mut fulfill_cx = crate::solve::FulfillmentCtxt::new(self);
|
let ocx = ObligationCtxt::new(self);
|
||||||
fulfill_cx.register_predicate_obligation(self, obligation.clone());
|
ocx.register_obligation(obligation.clone());
|
||||||
// True errors
|
let mut result = EvaluationResult::EvaluatedToOk;
|
||||||
// FIXME(-Znext-solver): Overflows are reported as ambig here, is that OK?
|
for error in ocx.select_all_or_error() {
|
||||||
if !fulfill_cx.select_where_possible(self).is_empty() {
|
if error.is_true_error() {
|
||||||
Ok(EvaluationResult::EvaluatedToErr)
|
return Ok(EvaluationResult::EvaluatedToErr);
|
||||||
} else if !fulfill_cx.select_all_or_error(self).is_empty() {
|
} else {
|
||||||
Ok(EvaluationResult::EvaluatedToAmbig)
|
result = result.max(EvaluationResult::EvaluatedToAmbig);
|
||||||
} else if self.opaque_types_added_in_snapshot(snapshot) {
|
}
|
||||||
Ok(EvaluationResult::EvaluatedToOkModuloOpaqueTypes)
|
|
||||||
} else if self.region_constraints_added_in_snapshot(snapshot) {
|
|
||||||
Ok(EvaluationResult::EvaluatedToOkModuloRegions)
|
|
||||||
} else {
|
|
||||||
Ok(EvaluationResult::EvaluatedToOk)
|
|
||||||
}
|
}
|
||||||
|
if self.opaque_types_added_in_snapshot(snapshot) {
|
||||||
|
result = result.max(EvaluationResult::EvaluatedToOkModuloOpaqueTypes);
|
||||||
|
} else if self.region_constraints_added_in_snapshot(snapshot) {
|
||||||
|
result = result.max(EvaluationResult::EvaluatedToOkModuloRegions);
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
assert!(!self.intercrate);
|
assert!(!self.intercrate);
|
||||||
|
@ -4,14 +4,13 @@
|
|||||||
// general routines.
|
// general routines.
|
||||||
|
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _};
|
use rustc_infer::traits::FulfillmentErrorCode;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::traits::CodegenObligationError;
|
use rustc_middle::traits::CodegenObligationError;
|
||||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||||
use rustc_trait_selection::traits::{
|
use rustc_trait_selection::traits::{
|
||||||
ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
|
ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext, Unimplemented,
|
||||||
Unimplemented,
|
|
||||||
};
|
};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
@ -51,15 +50,15 @@ pub fn codegen_select_candidate<'tcx>(
|
|||||||
// Currently, we use a fulfillment context to completely resolve
|
// Currently, we use a fulfillment context to completely resolve
|
||||||
// all nested obligations. This is because they can inform the
|
// all nested obligations. This is because they can inform the
|
||||||
// inference of the impl's type parameters.
|
// inference of the impl's type parameters.
|
||||||
let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(&infcx);
|
let ocx = ObligationCtxt::new(&infcx);
|
||||||
let impl_source = selection.map(|predicate| {
|
let impl_source = selection.map(|obligation| {
|
||||||
fulfill_cx.register_predicate_obligation(&infcx, predicate);
|
ocx.register_obligation(obligation);
|
||||||
});
|
});
|
||||||
|
|
||||||
// In principle, we only need to do this so long as `impl_source`
|
// In principle, we only need to do this so long as `impl_source`
|
||||||
// contains unbound type parameters. It could be a slight
|
// contains unbound type parameters. It could be a slight
|
||||||
// optimization to stop iterating early.
|
// optimization to stop iterating early.
|
||||||
let errors = fulfill_cx.select_all_or_error(&infcx);
|
let errors = ocx.select_all_or_error();
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
// `rustc_monomorphize::collector` assumes there are no type errors.
|
// `rustc_monomorphize::collector` assumes there are no type errors.
|
||||||
// Cycle errors are the only post-monomorphization errors possible; emit them now so
|
// Cycle errors are the only post-monomorphization errors possible; emit them now so
|
||||||
|
Loading…
Reference in New Issue
Block a user