Make TraitEngines generic over error
This commit is contained in:
parent
084ccd2390
commit
54b2b7d460
@ -13,6 +13,7 @@
|
|||||||
use rustc_trait_selection::solve::deeply_normalize;
|
use rustc_trait_selection::solve::deeply_normalize;
|
||||||
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
||||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||||
|
use rustc_trait_selection::traits::FulfillmentError;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
constraints::OutlivesConstraint,
|
constraints::OutlivesConstraint,
|
||||||
@ -286,7 +287,7 @@ fn normalize_and_add_type_outlives_constraints(
|
|||||||
ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env),
|
ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env),
|
||||||
ty,
|
ty,
|
||||||
)
|
)
|
||||||
.map_err(|_| NoSolution)
|
.map_err(|_: Vec<FulfillmentError<'tcx>>| NoSolution)
|
||||||
},
|
},
|
||||||
"normalize type outlives obligation",
|
"normalize type outlives obligation",
|
||||||
)
|
)
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
use rustc_hir::{GenericParamKind, ImplItemKind};
|
use rustc_hir::{GenericParamKind, ImplItemKind};
|
||||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
|
||||||
use rustc_infer::traits::{util, FulfillmentError};
|
use rustc_infer::traits::util;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::BottomUpFolder;
|
use rustc_middle::ty::fold::BottomUpFolder;
|
||||||
use rustc_middle::ty::util::ExplicitSelf;
|
use rustc_middle::ty::util::ExplicitSelf;
|
||||||
@ -25,7 +25,7 @@
|
|||||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::{
|
use rustc_trait_selection::traits::{
|
||||||
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
|
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
|
||||||
};
|
};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_span::def_id::{DefId, LocalDefId};
|
use rustc_span::def_id::{DefId, LocalDefId};
|
||||||
use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams};
|
use rustc_trait_selection::traits::{self, IsFirstInputType, UncoveredTyParams};
|
||||||
|
use rustc_trait_selection::traits::{FulfillmentError, StructurallyNormalizeExt, TraitEngineExt};
|
||||||
use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode};
|
use rustc_trait_selection::traits::{OrphanCheckErr, OrphanCheckMode};
|
||||||
use rustc_trait_selection::traits::{StructurallyNormalizeExt, TraitEngineExt};
|
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
#[instrument(level = "debug", skip(tcx))]
|
||||||
pub(crate) fn orphan_check_impl(
|
pub(crate) fn orphan_check_impl(
|
||||||
@ -317,7 +317,8 @@ fn orphan_check<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let ty = if infcx.next_trait_solver() {
|
let ty = if infcx.next_trait_solver() {
|
||||||
let mut fulfill_cx = <dyn traits::TraitEngine<'_>>::new(&infcx);
|
let mut fulfill_cx =
|
||||||
|
<dyn traits::TraitEngine<'tcx, FulfillmentError<'tcx>>>::new(&infcx);
|
||||||
infcx
|
infcx
|
||||||
.at(&cause, ty::ParamEnv::empty())
|
.at(&cause, ty::ParamEnv::empty())
|
||||||
.structurally_normalize(ty, &mut *fulfill_cx)
|
.structurally_normalize(ty, &mut *fulfill_cx)
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_infer::traits::FulfillmentError;
|
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::query::Key;
|
use rustc_middle::query::Key;
|
||||||
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
|
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
|
||||||
@ -28,6 +27,7 @@
|
|||||||
use rustc_span::symbol::{kw, sym, Ident};
|
use rustc_span::symbol::{kw, sym, Ident};
|
||||||
use rustc_span::BytePos;
|
use rustc_span::BytePos;
|
||||||
use rustc_span::{Span, Symbol, DUMMY_SP};
|
use rustc_span::{Span, Symbol, DUMMY_SP};
|
||||||
|
use rustc_trait_selection::traits::FulfillmentError;
|
||||||
use rustc_trait_selection::traits::{
|
use rustc_trait_selection::traits::{
|
||||||
object_safety_violations_for_assoc_item, TraitAliasExpansionInfo,
|
object_safety_violations_for_assoc_item, TraitAliasExpansionInfo,
|
||||||
};
|
};
|
||||||
|
@ -11,7 +11,9 @@
|
|||||||
use rustc_span::def_id::LocalDefIdMap;
|
use rustc_span::def_id::LocalDefIdMap;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, TraitEngineExt as _};
|
use rustc_trait_selection::traits::{
|
||||||
|
self, FulfillmentError, PredicateObligation, TraitEngine, TraitEngineExt as _,
|
||||||
|
};
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
@ -34,7 +36,7 @@ pub(crate) struct TypeckRootCtxt<'tcx> {
|
|||||||
|
|
||||||
pub(super) locals: RefCell<HirIdMap<Ty<'tcx>>>,
|
pub(super) locals: RefCell<HirIdMap<Ty<'tcx>>>,
|
||||||
|
|
||||||
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx>>>,
|
pub(super) fulfillment_cx: RefCell<Box<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>>,
|
||||||
|
|
||||||
/// Some additional `Sized` obligations badly affect type inference.
|
/// Some additional `Sized` obligations badly affect type inference.
|
||||||
/// These obligations are added in a later stage of typeck.
|
/// These obligations are added in a later stage of typeck.
|
||||||
@ -83,7 +85,7 @@ pub fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
|
|||||||
|
|
||||||
TypeckRootCtxt {
|
TypeckRootCtxt {
|
||||||
typeck_results,
|
typeck_results,
|
||||||
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_>>::new(&infcx)),
|
fulfillment_cx: RefCell::new(<dyn TraitEngine<'_, _>>::new(&infcx)),
|
||||||
infcx,
|
infcx,
|
||||||
locals: RefCell::new(Default::default()),
|
locals: RefCell::new(Default::default()),
|
||||||
deferred_sized_obligations: RefCell::new(Vec::new()),
|
deferred_sized_obligations: RefCell::new(Vec::new()),
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
use crate::infer::region_constraints::{Constraint, RegionConstraintData};
|
||||||
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult};
|
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult};
|
||||||
use crate::traits::query::NoSolution;
|
use crate::traits::query::NoSolution;
|
||||||
use crate::traits::TraitEngine;
|
use crate::traits::{FulfillmentErrorLike, TraitEngine};
|
||||||
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
|
use crate::traits::{Obligation, ObligationCause, PredicateObligation};
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_index::Idx;
|
use rustc_index::Idx;
|
||||||
@ -50,11 +50,11 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
/// - Finally, if any of the obligations result in a hard error,
|
/// - Finally, if any of the obligations result in a hard error,
|
||||||
/// then `Err(NoSolution)` is returned.
|
/// then `Err(NoSolution)` is returned.
|
||||||
#[instrument(skip(self, inference_vars, answer, fulfill_cx), level = "trace")]
|
#[instrument(skip(self, inference_vars, answer, fulfill_cx), level = "trace")]
|
||||||
pub fn make_canonicalized_query_response<T>(
|
pub fn make_canonicalized_query_response<T, E: FulfillmentErrorLike<'tcx>>(
|
||||||
&self,
|
&self,
|
||||||
inference_vars: CanonicalVarValues<'tcx>,
|
inference_vars: CanonicalVarValues<'tcx>,
|
||||||
answer: T,
|
answer: T,
|
||||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
|
||||||
) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
|
) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
|
||||||
where
|
where
|
||||||
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
||||||
@ -97,11 +97,11 @@ pub fn make_query_response_ignoring_pending_obligations<T>(
|
|||||||
/// Helper for `make_canonicalized_query_response` that does
|
/// Helper for `make_canonicalized_query_response` that does
|
||||||
/// everything up until the final canonicalization.
|
/// everything up until the final canonicalization.
|
||||||
#[instrument(skip(self, fulfill_cx), level = "debug")]
|
#[instrument(skip(self, fulfill_cx), level = "debug")]
|
||||||
fn make_query_response<T>(
|
fn make_query_response<T, E: FulfillmentErrorLike<'tcx>>(
|
||||||
&self,
|
&self,
|
||||||
inference_vars: CanonicalVarValues<'tcx>,
|
inference_vars: CanonicalVarValues<'tcx>,
|
||||||
answer: T,
|
answer: T,
|
||||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
|
||||||
) -> Result<QueryResponse<'tcx, T>, NoSolution>
|
) -> Result<QueryResponse<'tcx, T>, NoSolution>
|
||||||
where
|
where
|
||||||
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
T: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
||||||
@ -109,19 +109,13 @@ fn make_query_response<T>(
|
|||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
|
|
||||||
// Select everything, returning errors.
|
// Select everything, returning errors.
|
||||||
let true_errors = fulfill_cx.select_where_possible(self);
|
let errors = fulfill_cx.select_all_or_error(self);
|
||||||
debug!("true_errors = {:#?}", true_errors);
|
|
||||||
|
|
||||||
if !true_errors.is_empty() {
|
// True error!
|
||||||
// FIXME -- we don't indicate *why* we failed to solve
|
if errors.iter().any(|e| e.is_true_error()) {
|
||||||
debug!("make_query_response: true_errors={:#?}", true_errors);
|
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Anything left unselected *now* must be an ambiguity.
|
|
||||||
let ambig_errors = fulfill_cx.select_all_or_error(self);
|
|
||||||
debug!("ambig_errors = {:#?}", ambig_errors);
|
|
||||||
|
|
||||||
let region_obligations = self.take_registered_region_obligations();
|
let region_obligations = self.take_registered_region_obligations();
|
||||||
debug!(?region_obligations);
|
debug!(?region_obligations);
|
||||||
let region_constraints = self.with_region_constraints(|region_constraints| {
|
let region_constraints = self.with_region_constraints(|region_constraints| {
|
||||||
@ -135,8 +129,7 @@ fn make_query_response<T>(
|
|||||||
});
|
});
|
||||||
debug!(?region_constraints);
|
debug!(?region_constraints);
|
||||||
|
|
||||||
let certainty =
|
let certainty = if errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
|
||||||
if ambig_errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
|
|
||||||
|
|
||||||
let opaque_types = self.take_opaque_types_for_query_response();
|
let opaque_types = self.take_opaque_types_for_query_response();
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
pub use ValuePairs::*;
|
pub use ValuePairs::*;
|
||||||
|
|
||||||
use crate::traits::{
|
use crate::traits::{
|
||||||
self, ObligationCause, ObligationInspector, PredicateObligations, TraitEngine,
|
self, FulfillmentErrorLike, ObligationCause, ObligationInspector, PredicateObligations,
|
||||||
|
TraitEngine,
|
||||||
};
|
};
|
||||||
use error_reporting::TypeErrCtxt;
|
use error_reporting::TypeErrCtxt;
|
||||||
use free_regions::RegionRelations;
|
use free_regions::RegionRelations;
|
||||||
@ -737,10 +738,10 @@ pub fn build(&mut self) -> InferCtxt<'tcx> {
|
|||||||
|
|
||||||
impl<'tcx, T> InferOk<'tcx, T> {
|
impl<'tcx, T> InferOk<'tcx, T> {
|
||||||
/// Extracts `value`, registering any obligations into `fulfill_cx`.
|
/// Extracts `value`, registering any obligations into `fulfill_cx`.
|
||||||
pub fn into_value_registering_obligations(
|
pub fn into_value_registering_obligations<E: FulfillmentErrorLike<'tcx>>(
|
||||||
self,
|
self,
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
|
||||||
) -> T {
|
) -> T {
|
||||||
let InferOk { value, obligations } = self;
|
let InferOk { value, obligations } = self;
|
||||||
fulfill_cx.register_predicate_obligations(infcx, obligations);
|
fulfill_cx.register_predicate_obligations(infcx, obligations);
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use crate::infer::InferCtxt;
|
use crate::infer::InferCtxt;
|
||||||
use crate::traits::Obligation;
|
use crate::traits::Obligation;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_middle::ty::{self, Ty, Upcast};
|
use rustc_middle::ty::{self, Ty, Upcast};
|
||||||
|
|
||||||
use super::FulfillmentError;
|
|
||||||
use super::{ObligationCause, PredicateObligation};
|
use super::{ObligationCause, PredicateObligation};
|
||||||
|
|
||||||
pub trait TraitEngine<'tcx>: 'tcx {
|
pub trait TraitEngine<'tcx, E: FulfillmentErrorLike<'tcx>>: 'tcx {
|
||||||
/// Requires that `ty` must implement the trait with `def_id` in
|
/// Requires that `ty` must implement the trait with `def_id` in
|
||||||
/// the given environment. This trait must not have any type
|
/// the given environment. This trait must not have any type
|
||||||
/// parameters (except for `Self`).
|
/// parameters (except for `Self`).
|
||||||
@ -47,12 +48,12 @@ fn register_predicate_obligations(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
|
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
|
||||||
|
|
||||||
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
|
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E>;
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
|
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
|
||||||
let errors = self.select_where_possible(infcx);
|
let errors = self.select_where_possible(infcx);
|
||||||
if !errors.is_empty() {
|
if !errors.is_empty() {
|
||||||
return errors;
|
return errors;
|
||||||
@ -71,3 +72,11 @@ fn drain_unstalled_obligations(
|
|||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
) -> Vec<PredicateObligation<'tcx>>;
|
) -> Vec<PredicateObligation<'tcx>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait FulfillmentErrorLike<'tcx>: Debug + 'tcx {
|
||||||
|
fn is_true_error(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait FromSolverError<'tcx, E>: FulfillmentErrorLike<'tcx> {
|
||||||
|
fn from_solver_error(infcx: &InferCtxt<'tcx>, error: E) -> Self;
|
||||||
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
pub use self::SelectionError::*;
|
pub use self::SelectionError::*;
|
||||||
use crate::infer::InferCtxt;
|
use crate::infer::InferCtxt;
|
||||||
|
|
||||||
pub use self::engine::TraitEngine;
|
pub use self::engine::{FromSolverError, FulfillmentErrorLike, TraitEngine};
|
||||||
pub use self::project::MismatchedProjectionTypes;
|
pub use self::project::MismatchedProjectionTypes;
|
||||||
pub(crate) use self::project::UndoLog;
|
pub(crate) use self::project::UndoLog;
|
||||||
pub use self::project::{
|
pub use self::project::{
|
||||||
@ -124,15 +124,7 @@ pub fn derived_cause(
|
|||||||
pub type ObligationInspector<'tcx> =
|
pub type ObligationInspector<'tcx> =
|
||||||
fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
|
fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
|
||||||
|
|
||||||
pub struct FulfillmentError<'tcx> {
|
// TODO: Pull this down too
|
||||||
pub obligation: PredicateObligation<'tcx>,
|
|
||||||
pub code: FulfillmentErrorCode<'tcx>,
|
|
||||||
/// Diagnostics only: the 'root' obligation which resulted in
|
|
||||||
/// the failure to process `obligation`. This is the obligation
|
|
||||||
/// that was initially passed to `register_predicate_obligation`
|
|
||||||
pub root_obligation: PredicateObligation<'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum FulfillmentErrorCode<'tcx> {
|
pub enum FulfillmentErrorCode<'tcx> {
|
||||||
/// Inherently impossible to fulfill; this trait is implemented if and only
|
/// Inherently impossible to fulfill; this trait is implemented if and only
|
||||||
@ -198,28 +190,6 @@ pub fn with<P>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> FulfillmentError<'tcx> {
|
|
||||||
pub fn new(
|
|
||||||
obligation: PredicateObligation<'tcx>,
|
|
||||||
code: FulfillmentErrorCode<'tcx>,
|
|
||||||
root_obligation: PredicateObligation<'tcx>,
|
|
||||||
) -> FulfillmentError<'tcx> {
|
|
||||||
FulfillmentError { obligation, code, root_obligation }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_true_error(&self) -> bool {
|
|
||||||
match self.code {
|
|
||||||
FulfillmentErrorCode::Select(_)
|
|
||||||
| FulfillmentErrorCode::Project(_)
|
|
||||||
| FulfillmentErrorCode::Subtype(_, _)
|
|
||||||
| FulfillmentErrorCode::ConstEquate(_, _) => true,
|
|
||||||
FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> PolyTraitObligation<'tcx> {
|
impl<'tcx> PolyTraitObligation<'tcx> {
|
||||||
pub fn polarity(&self) -> ty::PredicatePolarity {
|
pub fn polarity(&self) -> ty::PredicatePolarity {
|
||||||
self.predicate.skip_binder().polarity
|
self.predicate.skip_binder().polarity
|
||||||
|
@ -29,12 +29,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for traits::FulfillmentError<'tcx> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
|
impl<'tcx> fmt::Debug for traits::FulfillmentErrorCode<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
use traits::FulfillmentErrorCode::*;
|
use traits::FulfillmentErrorCode::*;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::traits::FulfillmentError;
|
||||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
use rustc_infer::infer::{InferCtxt, RegionResolutionError};
|
use rustc_infer::infer::{InferCtxt, RegionResolutionError};
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
@ -27,7 +28,8 @@ fn resolve_regions(
|
|||||||
),
|
),
|
||||||
ty,
|
ty,
|
||||||
)
|
)
|
||||||
.map_err(|_| NoSolution)
|
// TODO:
|
||||||
|
.map_err(|_: Vec<FulfillmentError<'tcx>>| NoSolution)
|
||||||
} else {
|
} else {
|
||||||
Ok(ty)
|
Ok(ty)
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
@ -5,14 +6,17 @@
|
|||||||
use rustc_infer::traits::query::NoSolution;
|
use rustc_infer::traits::query::NoSolution;
|
||||||
use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
|
use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause};
|
||||||
use rustc_infer::traits::{
|
use rustc_infer::traits::{
|
||||||
self, FulfillmentError, FulfillmentErrorCode, MismatchedProjectionTypes, Obligation,
|
self, FromSolverError, FulfillmentErrorCode, FulfillmentErrorLike, MismatchedProjectionTypes,
|
||||||
ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError, TraitEngine,
|
Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, SelectionError,
|
||||||
|
TraitEngine,
|
||||||
};
|
};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
|
use crate::traits::FulfillmentError;
|
||||||
|
|
||||||
use super::eval_ctxt::GenerateProofTree;
|
use super::eval_ctxt::GenerateProofTree;
|
||||||
use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor};
|
use super::inspect::{self, ProofTreeInferCtxtExt, ProofTreeVisitor};
|
||||||
use super::{Certainty, InferCtxtEvalExt};
|
use super::{Certainty, InferCtxtEvalExt};
|
||||||
@ -28,7 +32,7 @@
|
|||||||
///
|
///
|
||||||
/// It is also likely that we want to use slightly different datastructures
|
/// It is also likely that we want to use slightly different datastructures
|
||||||
/// here as this will have to deal with far more root goals than `evaluate_all`.
|
/// here as this will have to deal with far more root goals than `evaluate_all`.
|
||||||
pub struct FulfillmentCtxt<'tcx> {
|
pub struct FulfillmentCtxt<'tcx, E: FulfillmentErrorLike<'tcx>> {
|
||||||
obligations: ObligationStorage<'tcx>,
|
obligations: ObligationStorage<'tcx>,
|
||||||
|
|
||||||
/// The snapshot in which this context was created. Using the context
|
/// The snapshot in which this context was created. Using the context
|
||||||
@ -36,6 +40,7 @@ pub struct FulfillmentCtxt<'tcx> {
|
|||||||
/// gets rolled back. Because of this we explicitly check that we only
|
/// gets rolled back. Because of this we explicitly check that we only
|
||||||
/// use the context in exactly this snapshot.
|
/// use the context in exactly this snapshot.
|
||||||
usable_in_snapshot: usize,
|
usable_in_snapshot: usize,
|
||||||
|
_errors: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@ -89,8 +94,8 @@ fn on_fulfillment_overflow(&mut self, infcx: &InferCtxt<'tcx>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> FulfillmentCtxt<'tcx> {
|
impl<'tcx, E: FulfillmentErrorLike<'tcx>> FulfillmentCtxt<'tcx, E> {
|
||||||
pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx> {
|
pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx, E> {
|
||||||
assert!(
|
assert!(
|
||||||
infcx.next_trait_solver(),
|
infcx.next_trait_solver(),
|
||||||
"new trait solver fulfillment context created when \
|
"new trait solver fulfillment context created when \
|
||||||
@ -99,6 +104,7 @@ pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx> {
|
|||||||
FulfillmentCtxt {
|
FulfillmentCtxt {
|
||||||
obligations: Default::default(),
|
obligations: Default::default(),
|
||||||
usable_in_snapshot: infcx.num_open_snapshots(),
|
usable_in_snapshot: infcx.num_open_snapshots(),
|
||||||
|
_errors: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +124,9 @@ fn inspect_evaluated_obligation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
|
impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> TraitEngine<'tcx, E>
|
||||||
|
for FulfillmentCtxt<'tcx, E>
|
||||||
|
{
|
||||||
#[instrument(level = "trace", skip(self, infcx))]
|
#[instrument(level = "trace", skip(self, infcx))]
|
||||||
fn register_predicate_obligation(
|
fn register_predicate_obligation(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -129,24 +137,22 @@ fn register_predicate_obligation(
|
|||||||
self.obligations.register(obligation);
|
self.obligations.register(obligation);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
|
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
|
||||||
let mut errors: Vec<_> = self
|
self.obligations
|
||||||
.obligations
|
|
||||||
.pending
|
.pending
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.map(|obligation| fulfillment_error_for_stalled(infcx, obligation))
|
.map(|obligation| NextSolverError::Ambiguity(obligation))
|
||||||
.collect();
|
.chain(
|
||||||
|
self.obligations
|
||||||
errors.extend(self.obligations.overflowed.drain(..).map(|obligation| FulfillmentError {
|
.overflowed
|
||||||
obligation: find_best_leaf_obligation(infcx, &obligation, true),
|
.drain(..)
|
||||||
code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
|
.map(|obligation| NextSolverError::Overflow(obligation)),
|
||||||
root_obligation: obligation,
|
)
|
||||||
}));
|
.map(|e| E::from_solver_error(infcx, e))
|
||||||
|
.collect()
|
||||||
errors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
|
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
|
||||||
assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
|
assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
for i in 0.. {
|
for i in 0.. {
|
||||||
@ -164,7 +170,10 @@ fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentE
|
|||||||
let (changed, certainty) = match result {
|
let (changed, certainty) = match result {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(NoSolution) => {
|
Err(NoSolution) => {
|
||||||
errors.push(fulfillment_error_for_no_solution(infcx, obligation));
|
errors.push(E::from_solver_error(
|
||||||
|
infcx,
|
||||||
|
NextSolverError::TrueError(obligation),
|
||||||
|
));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -195,6 +204,28 @@ fn drain_unstalled_obligations(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum NextSolverError<'tcx> {
|
||||||
|
TrueError(PredicateObligation<'tcx>),
|
||||||
|
Ambiguity(PredicateObligation<'tcx>),
|
||||||
|
Overflow(PredicateObligation<'tcx>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for FulfillmentError<'tcx> {
|
||||||
|
fn from_solver_error(infcx: &InferCtxt<'tcx>, error: NextSolverError<'tcx>) -> Self {
|
||||||
|
match error {
|
||||||
|
NextSolverError::TrueError(obligation) => {
|
||||||
|
fulfillment_error_for_no_solution(infcx, obligation)
|
||||||
|
}
|
||||||
|
NextSolverError::Ambiguity(obligation) => {
|
||||||
|
fulfillment_error_for_stalled(infcx, obligation)
|
||||||
|
}
|
||||||
|
NextSolverError::Overflow(obligation) => {
|
||||||
|
fulfillment_error_for_overflow(infcx, obligation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn fulfillment_error_for_no_solution<'tcx>(
|
fn fulfillment_error_for_no_solution<'tcx>(
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
root_obligation: PredicateObligation<'tcx>,
|
root_obligation: PredicateObligation<'tcx>,
|
||||||
@ -280,6 +311,17 @@ fn fulfillment_error_for_stalled<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fulfillment_error_for_overflow<'tcx>(
|
||||||
|
infcx: &InferCtxt<'tcx>,
|
||||||
|
root_obligation: PredicateObligation<'tcx>,
|
||||||
|
) -> FulfillmentError<'tcx> {
|
||||||
|
FulfillmentError {
|
||||||
|
obligation: find_best_leaf_obligation(infcx, &root_obligation, true),
|
||||||
|
code: FulfillmentErrorCode::Ambiguity { overflow: Some(true) },
|
||||||
|
root_obligation,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn find_best_leaf_obligation<'tcx>(
|
fn find_best_leaf_obligation<'tcx>(
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
obligation: &PredicateObligation<'tcx>,
|
obligation: &PredicateObligation<'tcx>,
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
mod trait_goals;
|
mod trait_goals;
|
||||||
|
|
||||||
pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt};
|
pub use eval_ctxt::{EvalCtxt, GenerateProofTree, InferCtxtEvalExt, InferCtxtSelectExt};
|
||||||
pub use fulfill::FulfillmentCtxt;
|
pub use fulfill::{FulfillmentCtxt, NextSolverError};
|
||||||
pub(crate) use normalize::deeply_normalize_for_diagnostics;
|
pub(crate) use normalize::deeply_normalize_for_diagnostics;
|
||||||
pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
|
pub use normalize::{deeply_normalize, deeply_normalize_with_skipped_universes};
|
||||||
|
|
||||||
|
@ -1,23 +1,29 @@
|
|||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::traits::error_reporting::{OverflowCause, TypeErrCtxtExt};
|
use crate::traits::error_reporting::{OverflowCause, TypeErrCtxtExt};
|
||||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||||
use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
|
use crate::traits::{BoundVarReplacer, FulfillmentError, PlaceholderReplacer};
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_infer::infer::at::At;
|
use rustc_infer::infer::at::At;
|
||||||
use rustc_infer::infer::InferCtxt;
|
use rustc_infer::infer::InferCtxt;
|
||||||
use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
|
use rustc_infer::traits::{FromSolverError, FulfillmentErrorLike, Obligation, TraitEngine};
|
||||||
use rustc_middle::traits::ObligationCause;
|
use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex};
|
use rustc_middle::ty::{self, Ty, TyCtxt, UniverseIndex};
|
||||||
use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
|
use rustc_middle::ty::{FallibleTypeFolder, TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
|
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
|
||||||
|
|
||||||
use super::FulfillmentCtxt;
|
use super::{FulfillmentCtxt, NextSolverError};
|
||||||
|
|
||||||
/// Deeply normalize all aliases in `value`. This does not handle inference and expects
|
/// Deeply normalize all aliases in `value`. This does not handle inference and expects
|
||||||
/// its input to be already fully resolved.
|
/// its input to be already fully resolved.
|
||||||
pub fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
pub fn deeply_normalize<
|
||||||
|
'tcx,
|
||||||
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||||
|
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
|
||||||
|
>(
|
||||||
at: At<'_, 'tcx>,
|
at: At<'_, 'tcx>,
|
||||||
value: T,
|
value: T,
|
||||||
) -> Result<T, Vec<FulfillmentError<'tcx>>> {
|
) -> Result<T, Vec<E>> {
|
||||||
assert!(!value.has_escaping_bound_vars());
|
assert!(!value.has_escaping_bound_vars());
|
||||||
deeply_normalize_with_skipped_universes(at, value, vec![])
|
deeply_normalize_with_skipped_universes(at, value, vec![])
|
||||||
}
|
}
|
||||||
@ -28,29 +34,32 @@ pub fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
|||||||
/// Additionally takes a list of universes which represents the binders which have been
|
/// Additionally takes a list of universes which represents the binders which have been
|
||||||
/// entered before passing `value` to the function. This is currently needed for
|
/// entered before passing `value` to the function. This is currently needed for
|
||||||
/// `normalize_erasing_regions`, which skips binders as it walks through a type.
|
/// `normalize_erasing_regions`, which skips binders as it walks through a type.
|
||||||
pub fn deeply_normalize_with_skipped_universes<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
pub fn deeply_normalize_with_skipped_universes<
|
||||||
|
'tcx,
|
||||||
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||||
|
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
|
||||||
|
>(
|
||||||
at: At<'_, 'tcx>,
|
at: At<'_, 'tcx>,
|
||||||
value: T,
|
value: T,
|
||||||
universes: Vec<Option<UniverseIndex>>,
|
universes: Vec<Option<UniverseIndex>>,
|
||||||
) -> Result<T, Vec<FulfillmentError<'tcx>>> {
|
) -> Result<T, Vec<E>> {
|
||||||
let fulfill_cx = FulfillmentCtxt::new(at.infcx);
|
let fulfill_cx = FulfillmentCtxt::new(at.infcx);
|
||||||
let mut folder = NormalizationFolder { at, fulfill_cx, depth: 0, universes };
|
let mut folder =
|
||||||
|
NormalizationFolder { at, fulfill_cx, depth: 0, universes, _errors: PhantomData };
|
||||||
|
|
||||||
value.try_fold_with(&mut folder)
|
value.try_fold_with(&mut folder)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NormalizationFolder<'me, 'tcx> {
|
struct NormalizationFolder<'me, 'tcx, E: FulfillmentErrorLike<'tcx>> {
|
||||||
at: At<'me, 'tcx>,
|
at: At<'me, 'tcx>,
|
||||||
fulfill_cx: FulfillmentCtxt<'tcx>,
|
fulfill_cx: FulfillmentCtxt<'tcx, E>,
|
||||||
depth: usize,
|
depth: usize,
|
||||||
universes: Vec<Option<UniverseIndex>>,
|
universes: Vec<Option<UniverseIndex>>,
|
||||||
|
_errors: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> NormalizationFolder<'_, 'tcx> {
|
impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> NormalizationFolder<'_, 'tcx, E> {
|
||||||
fn normalize_alias_ty(
|
fn normalize_alias_ty(&mut self, alias_ty: Ty<'tcx>) -> Result<Ty<'tcx>, Vec<E>> {
|
||||||
&mut self,
|
|
||||||
alias_ty: Ty<'tcx>,
|
|
||||||
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
|
|
||||||
assert!(matches!(alias_ty.kind(), ty::Alias(..)));
|
assert!(matches!(alias_ty.kind(), ty::Alias(..)));
|
||||||
|
|
||||||
let infcx = self.at.infcx;
|
let infcx = self.at.infcx;
|
||||||
@ -101,7 +110,7 @@ fn normalize_unevaluated_const(
|
|||||||
&mut self,
|
&mut self,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
uv: ty::UnevaluatedConst<'tcx>,
|
uv: ty::UnevaluatedConst<'tcx>,
|
||||||
) -> Result<ty::Const<'tcx>, Vec<FulfillmentError<'tcx>>> {
|
) -> Result<ty::Const<'tcx>, Vec<E>> {
|
||||||
let infcx = self.at.infcx;
|
let infcx = self.at.infcx;
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
let recursion_limit = tcx.recursion_limit();
|
let recursion_limit = tcx.recursion_limit();
|
||||||
@ -141,8 +150,10 @@ fn normalize_unevaluated_const(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
|
impl<'tcx, E: FromSolverError<'tcx, NextSolverError<'tcx>>> FallibleTypeFolder<TyCtxt<'tcx>>
|
||||||
type Error = Vec<FulfillmentError<'tcx>>;
|
for NormalizationFolder<'_, 'tcx, E>
|
||||||
|
{
|
||||||
|
type Error = Vec<E>;
|
||||||
|
|
||||||
fn interner(&self) -> TyCtxt<'tcx> {
|
fn interner(&self) -> TyCtxt<'tcx> {
|
||||||
self.at.infcx.tcx
|
self.at.infcx.tcx
|
||||||
@ -242,7 +253,8 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
|||||||
ty,
|
ty,
|
||||||
vec![None; ty.outer_exclusive_binder().as_usize()],
|
vec![None; ty.outer_exclusive_binder().as_usize()],
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|_| ty.super_fold_with(self))
|
// TODO:
|
||||||
|
.unwrap_or_else(|_: Vec<FulfillmentError<'tcx>>| ty.super_fold_with(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
@ -251,6 +263,7 @@ fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
|||||||
ct,
|
ct,
|
||||||
vec![None; ct.outer_exclusive_binder().as_usize()],
|
vec![None; ct.outer_exclusive_binder().as_usize()],
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|_| ct.super_fold_with(self))
|
// TODO:
|
||||||
|
.unwrap_or_else(|_: Vec<FulfillmentError<'tcx>>| ct.super_fold_with(self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
use crate::traits::select::IntercrateAmbiguityCause;
|
use crate::traits::select::IntercrateAmbiguityCause;
|
||||||
use crate::traits::NormalizeExt;
|
use crate::traits::NormalizeExt;
|
||||||
use crate::traits::SkipLeakCheck;
|
use crate::traits::SkipLeakCheck;
|
||||||
|
use crate::traits::{util, FulfillmentErrorCode};
|
||||||
use crate::traits::{
|
use crate::traits::{
|
||||||
Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext,
|
Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext,
|
||||||
};
|
};
|
||||||
@ -19,7 +20,6 @@
|
|||||||
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};
|
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
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};
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
use super::FulfillmentContext;
|
use super::FulfillmentContext;
|
||||||
use super::TraitEngine;
|
use super::{FromSolverError, TraitEngine};
|
||||||
use crate::regions::InferCtxtRegionExt;
|
use crate::regions::InferCtxtRegionExt;
|
||||||
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
|
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
|
||||||
|
use crate::solve::NextSolverError;
|
||||||
use crate::traits::error_reporting::TypeErrCtxtExt;
|
use crate::traits::error_reporting::TypeErrCtxtExt;
|
||||||
|
use crate::traits::fulfill::OldSolverError;
|
||||||
use crate::traits::NormalizeExt;
|
use crate::traits::NormalizeExt;
|
||||||
use crate::traits::StructurallyNormalizeExt;
|
use crate::traits::StructurallyNormalizeExt;
|
||||||
|
use crate::traits::{FulfillmentError, Obligation, ObligationCause, PredicateObligation};
|
||||||
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};
|
||||||
@ -18,7 +21,6 @@
|
|||||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
use rustc_infer::infer::RegionResolutionError;
|
use rustc_infer::infer::RegionResolutionError;
|
||||||
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
||||||
use rustc_infer::traits::{FulfillmentError, Obligation, ObligationCause, PredicateObligation};
|
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
use rustc_middle::arena::ArenaAllocatable;
|
use rustc_middle::arena::ArenaAllocatable;
|
||||||
use rustc_middle::traits::query::NoSolution;
|
use rustc_middle::traits::query::NoSolution;
|
||||||
@ -28,8 +30,12 @@
|
|||||||
use rustc_middle::ty::Variance;
|
use rustc_middle::ty::Variance;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
|
|
||||||
#[extension(pub trait TraitEngineExt<'tcx>)]
|
#[extension(pub trait TraitEngineExt<'tcx, E>)]
|
||||||
impl<'tcx> dyn TraitEngine<'tcx> {
|
impl<
|
||||||
|
'tcx,
|
||||||
|
E: FromSolverError<'tcx, NextSolverError<'tcx>> + FromSolverError<'tcx, OldSolverError<'tcx>>,
|
||||||
|
> dyn TraitEngine<'tcx, E>
|
||||||
|
{
|
||||||
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
|
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
|
||||||
if infcx.next_trait_solver() {
|
if infcx.next_trait_solver() {
|
||||||
Box::new(NextFulfillmentCtxt::new(infcx))
|
Box::new(NextFulfillmentCtxt::new(infcx))
|
||||||
@ -49,12 +55,16 @@ fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> {
|
|||||||
/// with obligations outside of hir or mir typeck.
|
/// with obligations outside of hir or mir typeck.
|
||||||
pub struct ObligationCtxt<'a, 'tcx> {
|
pub struct ObligationCtxt<'a, 'tcx> {
|
||||||
pub infcx: &'a InferCtxt<'tcx>,
|
pub infcx: &'a InferCtxt<'tcx>,
|
||||||
engine: RefCell<Box<dyn TraitEngine<'tcx>>>,
|
engine: RefCell<Box<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
||||||
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
|
pub fn new(infcx: &'a InferCtxt<'tcx>) -> Self {
|
||||||
Self { infcx, engine: RefCell::new(<dyn TraitEngine<'_>>::new(infcx)) }
|
// TODO:
|
||||||
|
Self {
|
||||||
|
infcx,
|
||||||
|
engine: RefCell::new(<dyn TraitEngine<'tcx, FulfillmentError<'tcx>>>::new(infcx)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
|
pub fn register_obligation(&self, obligation: PredicateObligation<'tcx>) {
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
|
use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome};
|
||||||
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
|
use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor};
|
||||||
use rustc_infer::infer::DefineOpaqueTypes;
|
use rustc_infer::infer::DefineOpaqueTypes;
|
||||||
use rustc_infer::traits::ProjectionCacheKey;
|
use rustc_infer::traits::{FromSolverError, FulfillmentErrorLike, ProjectionCacheKey};
|
||||||
use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
|
use rustc_infer::traits::{PolyTraitObligation, SelectionError, TraitEngine};
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::mir::interpret::ErrorHandled;
|
use rustc_middle::mir::interpret::ErrorHandled;
|
||||||
@ -50,7 +50,7 @@ fn as_cache_key(&self) -> Self::CacheKey {
|
|||||||
/// along. Once all type inference constraints have been generated, the
|
/// along. Once all type inference constraints have been generated, the
|
||||||
/// method `select_all_or_error` can be used to report any remaining
|
/// method `select_all_or_error` can be used to report any remaining
|
||||||
/// ambiguous cases as errors.
|
/// ambiguous cases as errors.
|
||||||
pub struct FulfillmentContext<'tcx> {
|
pub struct FulfillmentContext<'tcx, E: FulfillmentErrorLike<'tcx>> {
|
||||||
/// A list of all obligations that have been registered with this
|
/// A list of all obligations that have been registered with this
|
||||||
/// fulfillment context.
|
/// fulfillment context.
|
||||||
predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
|
predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
|
||||||
@ -60,6 +60,8 @@ pub struct FulfillmentContext<'tcx> {
|
|||||||
/// gets rolled back. Because of this we explicitly check that we only
|
/// gets rolled back. Because of this we explicitly check that we only
|
||||||
/// use the context in exactly this snapshot.
|
/// use the context in exactly this snapshot.
|
||||||
usable_in_snapshot: usize,
|
usable_in_snapshot: usize,
|
||||||
|
|
||||||
|
_errors: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -76,9 +78,9 @@ pub struct PendingPredicateObligation<'tcx> {
|
|||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
rustc_data_structures::static_assert_size!(PendingPredicateObligation<'_>, 72);
|
rustc_data_structures::static_assert_size!(PendingPredicateObligation<'_>, 72);
|
||||||
|
|
||||||
impl<'tcx> FulfillmentContext<'tcx> {
|
impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> FulfillmentContext<'tcx, E> {
|
||||||
/// Creates a new fulfillment context.
|
/// Creates a new fulfillment context.
|
||||||
pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx> {
|
pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx, E> {
|
||||||
assert!(
|
assert!(
|
||||||
!infcx.next_trait_solver(),
|
!infcx.next_trait_solver(),
|
||||||
"old trait solver fulfillment context created when \
|
"old trait solver fulfillment context created when \
|
||||||
@ -87,13 +89,15 @@ pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx> {
|
|||||||
FulfillmentContext {
|
FulfillmentContext {
|
||||||
predicates: ObligationForest::new(),
|
predicates: ObligationForest::new(),
|
||||||
usable_in_snapshot: infcx.num_open_snapshots(),
|
usable_in_snapshot: infcx.num_open_snapshots(),
|
||||||
|
_errors: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to select obligations using `selcx`.
|
/// Attempts to select obligations using `selcx`.
|
||||||
fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec<FulfillmentError<'tcx>> {
|
fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec<E> {
|
||||||
let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
|
let span = debug_span!("select", obligation_forest_size = ?self.predicates.len());
|
||||||
let _enter = span.enter();
|
let _enter = span.enter();
|
||||||
|
let infcx = selcx.infcx;
|
||||||
|
|
||||||
// Process pending obligations.
|
// Process pending obligations.
|
||||||
let outcome: Outcome<_, _> =
|
let outcome: Outcome<_, _> =
|
||||||
@ -102,8 +106,8 @@ fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec<FulfillmentError<
|
|||||||
// FIXME: if we kept the original cache key, we could mark projection
|
// FIXME: if we kept the original cache key, we could mark projection
|
||||||
// obligations as complete for the projection cache here.
|
// obligations as complete for the projection cache here.
|
||||||
|
|
||||||
let errors: Vec<FulfillmentError<'tcx>> =
|
let errors: Vec<E> =
|
||||||
outcome.errors.into_iter().map(to_fulfillment_error).collect();
|
outcome.errors.into_iter().map(|err| E::from_solver_error(infcx, err)).collect();
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"select({} predicates remaining, {} errors) done",
|
"select({} predicates remaining, {} errors) done",
|
||||||
@ -115,7 +119,9 @@ fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec<FulfillmentError<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
impl<'tcx, E: FromSolverError<'tcx, OldSolverError<'tcx>>> TraitEngine<'tcx, E>
|
||||||
|
for FulfillmentContext<'tcx, E>
|
||||||
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn register_predicate_obligation(
|
fn register_predicate_obligation(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -134,18 +140,15 @@ fn register_predicate_obligation(
|
|||||||
.register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
|
.register_obligation(PendingPredicateObligation { obligation, stalled_on: vec![] });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_remaining_errors(
|
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
|
||||||
&mut self,
|
|
||||||
_infcx: &InferCtxt<'tcx>,
|
|
||||||
) -> Vec<FulfillmentError<'tcx>> {
|
|
||||||
self.predicates
|
self.predicates
|
||||||
.to_errors(FulfillmentErrorCode::Ambiguity { overflow: None })
|
.to_errors(FulfillmentErrorCode::Ambiguity { overflow: None })
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(to_fulfillment_error)
|
.map(|err| E::from_solver_error(infcx, err))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
|
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
|
||||||
let selcx = SelectionContext::new(infcx);
|
let selcx = SelectionContext::new(infcx);
|
||||||
self.select(selcx)
|
self.select(selcx)
|
||||||
}
|
}
|
||||||
@ -840,13 +843,15 @@ fn args_infer_vars<'a, 'tcx>(
|
|||||||
.filter_map(TyOrConstInferVar::maybe_from_generic_arg)
|
.filter_map(TyOrConstInferVar::maybe_from_generic_arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_fulfillment_error<'tcx>(
|
pub type OldSolverError<'tcx> = Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>;
|
||||||
error: Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
|
|
||||||
) -> FulfillmentError<'tcx> {
|
impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx> {
|
||||||
let mut iter = error.backtrace.into_iter();
|
fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
|
||||||
let obligation = iter.next().unwrap().obligation;
|
let mut iter = error.backtrace.into_iter();
|
||||||
// The root obligation is the last item in the backtrace - if there's only
|
let obligation = iter.next().unwrap().obligation;
|
||||||
// one item, then it's the same as the main obligation
|
// The root obligation is the last item in the backtrace - if there's only
|
||||||
let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation);
|
// one item, then it's the same as the main obligation
|
||||||
FulfillmentError::new(obligation, error.error, root_obligation)
|
let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation);
|
||||||
|
FulfillmentError::new(obligation, error.error, root_obligation)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
|
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
|
||||||
|
|
||||||
use crate::regions::InferCtxtRegionExt;
|
use crate::regions::InferCtxtRegionExt;
|
||||||
use crate::traits::{self, ObligationCause};
|
use crate::traits::{self, FulfillmentError, ObligationCause};
|
||||||
|
|
||||||
use hir::LangItem;
|
use hir::LangItem;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::FxIndexSet;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||||
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
|
use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
|
||||||
use rustc_infer::{infer::outlives::env::OutlivesEnvironment, traits::FulfillmentError};
|
|
||||||
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
|
use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
|
||||||
|
|
||||||
use super::outlives_bounds::InferCtxtExt;
|
use super::outlives_bounds::InferCtxtExt;
|
||||||
|
@ -70,6 +70,49 @@
|
|||||||
|
|
||||||
pub use rustc_infer::traits::*;
|
pub use rustc_infer::traits::*;
|
||||||
|
|
||||||
|
pub struct FulfillmentError<'tcx> {
|
||||||
|
pub obligation: PredicateObligation<'tcx>,
|
||||||
|
pub code: FulfillmentErrorCode<'tcx>,
|
||||||
|
/// Diagnostics only: the 'root' obligation which resulted in
|
||||||
|
/// the failure to process `obligation`. This is the obligation
|
||||||
|
/// that was initially passed to `register_predicate_obligation`
|
||||||
|
pub root_obligation: PredicateObligation<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> FulfillmentError<'tcx> {
|
||||||
|
pub fn new(
|
||||||
|
obligation: PredicateObligation<'tcx>,
|
||||||
|
code: FulfillmentErrorCode<'tcx>,
|
||||||
|
root_obligation: PredicateObligation<'tcx>,
|
||||||
|
) -> FulfillmentError<'tcx> {
|
||||||
|
FulfillmentError { obligation, code, root_obligation }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_true_error(&self) -> bool {
|
||||||
|
match self.code {
|
||||||
|
FulfillmentErrorCode::Select(_)
|
||||||
|
| FulfillmentErrorCode::Project(_)
|
||||||
|
| FulfillmentErrorCode::Subtype(_, _)
|
||||||
|
| FulfillmentErrorCode::ConstEquate(_, _) => true,
|
||||||
|
FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> FulfillmentErrorLike<'tcx> for FulfillmentError<'tcx> {
|
||||||
|
fn is_true_error(&self) -> bool {
|
||||||
|
self.is_true_error()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Debug for FulfillmentError<'tcx> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "FulfillmentError({:?},{:?})", self.obligation, self.code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether to skip the leak check, as part of a future compatibility warning step.
|
/// Whether to skip the leak check, as part of a future compatibility warning step.
|
||||||
///
|
///
|
||||||
/// The "default" for skip-leak-check corresponds to the current
|
/// The "default" for skip-leak-check corresponds to the current
|
||||||
|
@ -3,11 +3,13 @@
|
|||||||
use super::error_reporting::TypeErrCtxtExt;
|
use super::error_reporting::TypeErrCtxtExt;
|
||||||
use super::SelectionContext;
|
use super::SelectionContext;
|
||||||
use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
|
use super::{project, with_replaced_escaping_bound_vars, BoundVarReplacer, PlaceholderReplacer};
|
||||||
|
use crate::solve::NextSolverError;
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_infer::infer::at::At;
|
use rustc_infer::infer::at::At;
|
||||||
use rustc_infer::infer::InferOk;
|
use rustc_infer::infer::InferOk;
|
||||||
|
use rustc_infer::traits::FromSolverError;
|
||||||
use rustc_infer::traits::PredicateObligation;
|
use rustc_infer::traits::PredicateObligation;
|
||||||
use rustc_infer::traits::{FulfillmentError, Normalized, Obligation, TraitEngine};
|
use rustc_infer::traits::{Normalized, Obligation, TraitEngine};
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal};
|
use rustc_middle::traits::{ObligationCause, ObligationCauseCode, Reveal};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder};
|
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFolder};
|
||||||
@ -44,11 +46,14 @@ fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T>
|
|||||||
/// existing fulfillment context in the old solver. Once we also eagerly prove goals with
|
/// existing fulfillment context in the old solver. Once we also eagerly prove goals with
|
||||||
/// the old solver or have removed the old solver, remove `traits::fully_normalize` and
|
/// the old solver or have removed the old solver, remove `traits::fully_normalize` and
|
||||||
/// rename this function to `At::fully_normalize`.
|
/// rename this function to `At::fully_normalize`.
|
||||||
fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
|
fn deeply_normalize<
|
||||||
|
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||||
|
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
|
||||||
|
>(
|
||||||
self,
|
self,
|
||||||
value: T,
|
value: T,
|
||||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
|
||||||
) -> Result<T, Vec<FulfillmentError<'tcx>>> {
|
) -> Result<T, Vec<E>> {
|
||||||
if self.infcx.next_trait_solver() {
|
if self.infcx.next_trait_solver() {
|
||||||
crate::solve::deeply_normalize(self, value)
|
crate::solve::deeply_normalize(self, value)
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
use crate::traits::error_reporting::TypeErrCtxtExt;
|
use crate::traits::error_reporting::TypeErrCtxtExt;
|
||||||
use crate::traits::normalize::needs_normalization;
|
use crate::traits::normalize::needs_normalization;
|
||||||
use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
|
use crate::traits::{BoundVarReplacer, PlaceholderReplacer};
|
||||||
|
use crate::traits::{FulfillmentError, Normalized};
|
||||||
use crate::traits::{ObligationCause, PredicateObligation, Reveal};
|
use crate::traits::{ObligationCause, PredicateObligation, Reveal};
|
||||||
use rustc_data_structures::sso::SsoHashMap;
|
use rustc_data_structures::sso::SsoHashMap;
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
use rustc_infer::traits::Normalized;
|
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
|
use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
|
||||||
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
|
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
|
||||||
@ -76,7 +76,10 @@ fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
|
|||||||
};
|
};
|
||||||
|
|
||||||
if self.infcx.next_trait_solver() {
|
if self.infcx.next_trait_solver() {
|
||||||
match crate::solve::deeply_normalize_with_skipped_universes(self, value, universes) {
|
// TODO:
|
||||||
|
match crate::solve::deeply_normalize_with_skipped_universes::<_, FulfillmentError<'tcx>>(
|
||||||
|
self, value, universes,
|
||||||
|
) {
|
||||||
Ok(value) => return Ok(Normalized { value, obligations: vec![] }),
|
Ok(value) => return Ok(Normalized { value, obligations: vec![] }),
|
||||||
Err(_errors) => {
|
Err(_errors) => {
|
||||||
return Err(NoSolution);
|
return Err(NoSolution);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::solve;
|
use crate::solve;
|
||||||
use crate::traits::query::NoSolution;
|
use crate::traits::query::NoSolution;
|
||||||
use crate::traits::wf;
|
use crate::traits::wf;
|
||||||
|
use crate::traits::FulfillmentError;
|
||||||
use crate::traits::ObligationCtxt;
|
use crate::traits::ObligationCtxt;
|
||||||
|
|
||||||
use rustc_infer::infer::canonical::Canonical;
|
use rustc_infer::infer::canonical::Canonical;
|
||||||
@ -266,7 +267,8 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
|
|||||||
ocx.infcx.at(&ObligationCause::dummy(), param_env),
|
ocx.infcx.at(&ObligationCause::dummy(), param_env),
|
||||||
ty_a,
|
ty_a,
|
||||||
)
|
)
|
||||||
.map_err(|_errs| NoSolution)?;
|
// TODO:
|
||||||
|
.map_err(|_errs: Vec<FulfillmentError<'tcx>>| NoSolution)?;
|
||||||
}
|
}
|
||||||
let mut components = smallvec![];
|
let mut components = smallvec![];
|
||||||
push_outlives_components(tcx, ty_a, &mut components);
|
push_outlives_components(tcx, ty_a, &mut components);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use rustc_infer::infer::at::At;
|
use rustc_infer::infer::at::At;
|
||||||
use rustc_infer::traits::{FulfillmentError, TraitEngine};
|
use rustc_infer::traits::{FulfillmentErrorLike, TraitEngine};
|
||||||
use rustc_macros::extension;
|
use rustc_macros::extension;
|
||||||
use rustc_middle::ty::{self, Ty};
|
use rustc_middle::ty::{self, Ty};
|
||||||
|
|
||||||
@ -7,11 +7,11 @@
|
|||||||
|
|
||||||
#[extension(pub trait StructurallyNormalizeExt<'tcx>)]
|
#[extension(pub trait StructurallyNormalizeExt<'tcx>)]
|
||||||
impl<'tcx> At<'_, 'tcx> {
|
impl<'tcx> At<'_, 'tcx> {
|
||||||
fn structurally_normalize(
|
fn structurally_normalize<E: FulfillmentErrorLike<'tcx>>(
|
||||||
&self,
|
&self,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
|
||||||
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
|
) -> Result<Ty<'tcx>, Vec<E>> {
|
||||||
assert!(!ty.is_ty_var(), "should have resolved vars before calling");
|
assert!(!ty.is_ty_var(), "should have resolved vars before calling");
|
||||||
|
|
||||||
if self.infcx.next_trait_solver() {
|
if self.infcx.next_trait_solver() {
|
||||||
|
Loading…
Reference in New Issue
Block a user