Auto merge of #111918 - compiler-errors:custom-type-ops-err, r=lcnr

Use `ErrorGuaranteed` more in MIR type ops

Delay bugs more eagerly and pass them through type op infra instead of delaying them at all the usage-sites.

Follow up to: https://github.com/rust-lang/rust/pull/111741#discussion_r1203840588

r? `@lcnr`
This commit is contained in:
bors 2023-05-26 06:20:21 +00:00
commit be72f2587c
21 changed files with 158 additions and 159 deletions

View File

@ -1,12 +1,12 @@
use std::fmt; use std::fmt;
use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::canonical::Canonical;
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput}; use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
use rustc_trait_selection::traits::query::{Fallible, NoSolution};
use rustc_trait_selection::traits::ObligationCause; use rustc_trait_selection::traits::ObligationCause;
use crate::diagnostics::{ToUniverseInfo, UniverseInfo}; use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
@ -30,14 +30,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
locations: Locations, locations: Locations,
category: ConstraintCategory<'tcx>, category: ConstraintCategory<'tcx>,
op: Op, op: Op,
) -> Fallible<R> ) -> Result<R, ErrorGuaranteed>
where where
Op: type_op::TypeOp<'tcx, Output = R>, Op: type_op::TypeOp<'tcx, Output = R>,
Op::ErrorInfo: ToUniverseInfo<'tcx>, Op::ErrorInfo: ToUniverseInfo<'tcx>,
{ {
let old_universe = self.infcx.universe(); let old_universe = self.infcx.universe();
let TypeOpOutput { output, constraints, error_info } = op.fully_perform(self.infcx)?; let TypeOpOutput { output, constraints, error_info } =
op.fully_perform(self.infcx, locations.span(self.body))?;
debug!(?output, ?constraints); debug!(?output, ?constraints);
@ -135,14 +136,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
) { ) {
let param_env = self.param_env; let param_env = self.param_env;
let predicate = predicate.to_predicate(self.tcx()); let predicate = predicate.to_predicate(self.tcx());
self.fully_perform_op( let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
locations, locations,
category, category,
param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)), param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
) );
.unwrap_or_else(|NoSolution| {
span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
})
} }
pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
@ -163,15 +161,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx, T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
{ {
let param_env = self.param_env; let param_env = self.param_env;
self.fully_perform_op( let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
location.to_locations(), location.to_locations(),
category, category,
param_env.and(type_op::normalize::Normalize::new(value)), param_env.and(type_op::normalize::Normalize::new(value)),
) );
.unwrap_or_else(|NoSolution| { result.unwrap_or(value)
span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);
value
})
} }
#[instrument(skip(self), level = "debug")] #[instrument(skip(self), level = "debug")]
@ -181,18 +176,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
user_ty: ty::UserType<'tcx>, user_ty: ty::UserType<'tcx>,
span: Span, span: Span,
) { ) {
self.fully_perform_op( let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
Locations::All(span), Locations::All(span),
ConstraintCategory::Boring, ConstraintCategory::Boring,
self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(mir_ty, user_ty)), self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(mir_ty, user_ty)),
) );
.unwrap_or_else(|err| {
span_mirbug!(
self,
span,
"ascribe_user_type `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
);
});
} }
/// *Incorrectly* skips the WF checks we normally do in `ascribe_user_type`. /// *Incorrectly* skips the WF checks we normally do in `ascribe_user_type`.
@ -219,7 +207,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let cause = ObligationCause::dummy_with_span(span); let cause = ObligationCause::dummy_with_span(span);
let param_env = self.param_env; let param_env = self.param_env;
self.fully_perform_op( let _: Result<_, ErrorGuaranteed> = self.fully_perform_op(
Locations::All(span), Locations::All(span),
ConstraintCategory::Boring, ConstraintCategory::Boring,
type_op::custom::CustomTypeOp::new( type_op::custom::CustomTypeOp::new(
@ -230,13 +218,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}, },
"ascribe_user_type_skip_wf", "ascribe_user_type_skip_wf",
), ),
) );
.unwrap_or_else(|err| {
span_mirbug!(
self,
span,
"ascribe_user_type_skip_wf `{mir_ty:?}=={user_ty:?}` failed with `{err:?}`",
);
});
} }
} }

View File

@ -8,7 +8,7 @@ use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::OutlivesBound; use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_middle::ty::{self, RegionVid, Ty};
use rustc_span::Span; use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
use std::rc::Rc; use std::rc::Rc;
use type_op::TypeOpOutput; use type_op::TypeOpOutput;
@ -243,18 +243,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } = self
.param_env .param_env
.and(type_op::normalize::Normalize::new(ty)) .and(type_op::normalize::Normalize::new(ty))
.fully_perform(self.infcx) .fully_perform(self.infcx, span)
.unwrap_or_else(|_| { .unwrap_or_else(|guar| TypeOpOutput {
let guar = self output: self.infcx.tcx.ty_error(guar),
.infcx constraints: None,
.tcx error_info: None,
.sess
.delay_span_bug(span, format!("failed to normalize {:?}", ty));
TypeOpOutput {
output: self.infcx.tcx.ty_error(guar),
constraints: None,
error_info: None,
}
}); });
if let Some(c) = constraints_normalize { if let Some(c) = constraints_normalize {
constraints.push(c) constraints.push(c)
@ -324,7 +317,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
let TypeOpOutput { output: bounds, constraints, .. } = self let TypeOpOutput { output: bounds, constraints, .. } = self
.param_env .param_env
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
.fully_perform(self.infcx) .fully_perform(self.infcx, DUMMY_SP)
.unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty)); .unwrap_or_else(|_| bug!("failed to compute implied bounds {:?}", ty));
debug!(?bounds, ?constraints); debug!(?bounds, ?constraints);
self.add_outlives_bounds(bounds); self.add_outlives_bounds(bounds);

View File

@ -4,6 +4,7 @@ use rustc_index::interval::IntervalSet;
use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult; use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult;
use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives; use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives;
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
@ -568,10 +569,15 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
) -> DropData<'tcx> { ) -> DropData<'tcx> {
debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,); debug!("compute_drop_data(dropped_ty={:?})", dropped_ty,);
let param_env = typeck.param_env; match typeck
let TypeOpOutput { output, constraints, .. } = .param_env
param_env.and(DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx).unwrap(); .and(DropckOutlives::new(dropped_ty))
.fully_perform(typeck.infcx, DUMMY_SP)
DropData { dropck_result: output, region_constraint_data: constraints } {
Ok(TypeOpOutput { output, constraints, .. }) => {
DropData { dropck_result: output, region_constraint_data: constraints }
}
Err(_) => DropData { dropck_result: Default::default(), region_constraint_data: None },
}
} }
} }

View File

@ -10,6 +10,7 @@ use either::Either;
use hir::OpaqueTyOrigin; use hir::OpaqueTyOrigin;
use rustc_data_structures::frozen::Frozen; use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
@ -26,6 +27,7 @@ use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::AssertKind; use rustc_middle::mir::AssertKind;
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::subst::{SubstsRef, UserSubsts}; use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
@ -41,7 +43,7 @@ use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints; use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
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::query::Fallible;
use rustc_trait_selection::traits::PredicateObligation; use rustc_trait_selection::traits::PredicateObligation;
use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
@ -216,24 +218,22 @@ pub(crate) fn type_check<'mir, 'tcx>(
let opaque_type_values = opaque_type_values let opaque_type_values = opaque_type_values
.into_iter() .into_iter()
.map(|(opaque_type_key, decl)| { .map(|(opaque_type_key, decl)| {
checker let _: Result<_, ErrorGuaranteed> = checker.fully_perform_op(
.fully_perform_op( Locations::All(body.span),
Locations::All(body.span), ConstraintCategory::OpaqueType,
ConstraintCategory::OpaqueType, CustomTypeOp::new(
CustomTypeOp::new( |ocx| {
|ocx| { ocx.infcx.register_member_constraints(
ocx.infcx.register_member_constraints( param_env,
param_env, opaque_type_key,
opaque_type_key, decl.hidden_type.ty,
decl.hidden_type.ty, decl.hidden_type.span,
decl.hidden_type.span, );
); Ok(())
Ok(()) },
}, "opaque_type_map",
"opaque_type_map", ),
), );
)
.unwrap();
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type); let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind()); trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
if hidden_type.has_non_region_infer() { if hidden_type.has_non_region_infer() {
@ -1134,7 +1134,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
sup: Ty<'tcx>, sup: Ty<'tcx>,
locations: Locations, locations: Locations,
category: ConstraintCategory<'tcx>, category: ConstraintCategory<'tcx>,
) -> Fallible<()> { ) -> Result<(), NoSolution> {
// Use this order of parameters because the sup type is usually the // Use this order of parameters because the sup type is usually the
// "expected" type in diagnostics. // "expected" type in diagnostics.
self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category) self.relate_types(sup, ty::Variance::Contravariant, sub, locations, category)
@ -1147,7 +1147,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
found: Ty<'tcx>, found: Ty<'tcx>,
locations: Locations, locations: Locations,
category: ConstraintCategory<'tcx>, category: ConstraintCategory<'tcx>,
) -> Fallible<()> { ) -> Result<(), NoSolution> {
self.relate_types(expected, ty::Variance::Invariant, found, locations, category) self.relate_types(expected, ty::Variance::Invariant, found, locations, category)
} }
@ -1159,7 +1159,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
user_ty: &UserTypeProjection, user_ty: &UserTypeProjection,
locations: Locations, locations: Locations,
category: ConstraintCategory<'tcx>, category: ConstraintCategory<'tcx>,
) -> Fallible<()> { ) -> Result<(), NoSolution> {
let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty; let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty;
trace!(?annotated_type); trace!(?annotated_type);
let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); let mut curr_projected_ty = PlaceTy::from_ty(annotated_type);
@ -2755,11 +2755,20 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
/// constraints in our `InferCtxt` /// constraints in our `InferCtxt`
type ErrorInfo = InstantiateOpaqueType<'tcx>; type ErrorInfo = InstantiateOpaqueType<'tcx>;
fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> { fn fully_perform(
let (mut output, region_constraints) = scrape_region_constraints(infcx, |ocx| { mut self,
ocx.register_obligations(self.obligations.clone()); infcx: &InferCtxt<'tcx>,
Ok(()) span: Span,
})?; ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
let (mut output, region_constraints) = scrape_region_constraints(
infcx,
|ocx| {
ocx.register_obligations(self.obligations.clone());
Ok(())
},
"InstantiateOpaqueType",
span,
)?;
self.region_constraints = Some(region_constraints); self.region_constraints = Some(region_constraints);
output.error_info = Some(self); output.error_info = Some(self);
Ok(output) Ok(output)

View File

@ -1,12 +1,13 @@
use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate}; use rustc_infer::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
use rustc_infer::infer::NllRegionVariableOrigin; use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::traits::PredicateObligations; use rustc_infer::traits::PredicateObligations;
use rustc_middle::mir::ConstraintCategory; use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::relate::TypeRelation;
use rustc_middle::ty::{self, Ty}; use rustc_middle::ty::{self, Ty};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
use rustc_span::{Span, Symbol}; use rustc_span::{Span, Symbol};
use rustc_trait_selection::traits::query::Fallible;
use crate::constraints::OutlivesConstraint; use crate::constraints::OutlivesConstraint;
use crate::diagnostics::UniverseInfo; use crate::diagnostics::UniverseInfo;
@ -30,7 +31,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
b: Ty<'tcx>, b: Ty<'tcx>,
locations: Locations, locations: Locations,
category: ConstraintCategory<'tcx>, category: ConstraintCategory<'tcx>,
) -> Fallible<()> { ) -> Result<(), NoSolution> {
TypeRelating::new( TypeRelating::new(
self.infcx, self.infcx,
NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)), NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)),
@ -47,7 +48,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
b: ty::SubstsRef<'tcx>, b: ty::SubstsRef<'tcx>,
locations: Locations, locations: Locations,
category: ConstraintCategory<'tcx>, category: ConstraintCategory<'tcx>,
) -> Fallible<()> { ) -> Result<(), NoSolution> {
TypeRelating::new( TypeRelating::new(
self.infcx, self.infcx,
NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()), NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()),
@ -185,7 +186,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
} }
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) { fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
match self.type_checker.fully_perform_op( let _: Result<_, ErrorGuaranteed> = self.type_checker.fully_perform_op(
self.locations, self.locations,
self.category, self.category,
InstantiateOpaqueType { InstantiateOpaqueType {
@ -194,16 +195,6 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
base_universe: None, base_universe: None,
region_constraints: None, region_constraints: None,
}, },
) { );
Ok(()) => {}
Err(_) => {
// It's a bit redundant to delay a bug here, but I'd rather
// delay more bugs than accidentally not delay a bug at all.
self.type_checker.tcx().sess.delay_span_bug(
self.locations.span(self.type_checker.body),
"errors selecting obligation during MIR typeck",
);
}
};
} }
} }

View File

@ -15,7 +15,7 @@ use crate::infer::canonical::{
use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate}; use crate::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::region_constraints::{Constraint, RegionConstraintData};
use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, NllRegionVariableOrigin}; use crate::infer::{DefineOpaqueTypes, InferCtxt, InferOk, InferResult, NllRegionVariableOrigin};
use crate::traits::query::{Fallible, NoSolution}; use crate::traits::query::NoSolution;
use crate::traits::{Obligation, ObligationCause, PredicateObligation}; use crate::traits::{Obligation, ObligationCause, PredicateObligation};
use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt}; use crate::traits::{PredicateObligations, TraitEngine, TraitEngineExt};
use rustc_data_structures::captures::Captures; use rustc_data_structures::captures::Captures;
@ -57,7 +57,7 @@ impl<'tcx> InferCtxt<'tcx> {
inference_vars: CanonicalVarValues<'tcx>, inference_vars: CanonicalVarValues<'tcx>,
answer: T, answer: T,
fulfill_cx: &mut dyn TraitEngine<'tcx>, fulfill_cx: &mut dyn TraitEngine<'tcx>,
) -> Fallible<CanonicalQueryResponse<'tcx, T>> ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
where where
T: Debug + TypeFoldable<TyCtxt<'tcx>>, T: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>, Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,

View File

@ -95,8 +95,6 @@ pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
#[derive(Copy, Clone, Debug, HashStable, PartialEq, Eq)] #[derive(Copy, Clone, Debug, HashStable, PartialEq, Eq)]
pub struct NoSolution; pub struct NoSolution;
pub type Fallible<T> = Result<T, NoSolution>;
impl<'tcx> From<TypeError<'tcx>> for NoSolution { impl<'tcx> From<TypeError<'tcx>> for NoSolution {
fn from(_: TypeError<'tcx>) -> NoSolution { fn from(_: TypeError<'tcx>) -> NoSolution {
NoSolution NoSolution

View File

@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
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};
use rustc_middle::traits::query::Fallible; use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_middle::ty::{GenericArg, ToPredicate}; use rustc_middle::ty::{GenericArg, ToPredicate};
use rustc_span::DUMMY_SP; use rustc_span::DUMMY_SP;
@ -82,8 +82,8 @@ pub trait InferCtxtBuilderExt<'tcx> {
fn enter_canonical_trait_query<K, R>( fn enter_canonical_trait_query<K, R>(
&mut self, &mut self,
canonical_key: &Canonical<'tcx, K>, canonical_key: &Canonical<'tcx, K>,
operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>, operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
) -> Fallible<CanonicalQueryResponse<'tcx, R>> ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
where where
K: TypeFoldable<TyCtxt<'tcx>>, K: TypeFoldable<TyCtxt<'tcx>>,
R: Debug + TypeFoldable<TyCtxt<'tcx>>, R: Debug + TypeFoldable<TyCtxt<'tcx>>,
@ -110,8 +110,8 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
fn enter_canonical_trait_query<K, R>( fn enter_canonical_trait_query<K, R>(
&mut self, &mut self,
canonical_key: &Canonical<'tcx, K>, canonical_key: &Canonical<'tcx, K>,
operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Fallible<R>, operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>,
) -> Fallible<CanonicalQueryResponse<'tcx, R>> ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution>
where where
K: TypeFoldable<TyCtxt<'tcx>>, K: TypeFoldable<TyCtxt<'tcx>>,
R: Debug + TypeFoldable<TyCtxt<'tcx>>, R: Debug + TypeFoldable<TyCtxt<'tcx>>,

View File

@ -14,11 +14,11 @@ use rustc_infer::infer::canonical::{
}; };
use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
use rustc_infer::traits::query::Fallible;
use rustc_infer::traits::{ use rustc_infer::traits::{
FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _, FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
}; };
use rustc_middle::arena::ArenaAllocatable; use rustc_middle::arena::ArenaAllocatable;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::error::TypeError; use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::ToPredicate; use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::TypeFoldable;
@ -235,7 +235,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
&self, &self,
inference_vars: CanonicalVarValues<'tcx>, inference_vars: CanonicalVarValues<'tcx>,
answer: T, answer: T,
) -> Fallible<CanonicalQueryResponse<'tcx, T>> ) -> Result<CanonicalQueryResponse<'tcx, T>, NoSolution>
where where
T: Debug + TypeFoldable<TyCtxt<'tcx>>, T: Debug + TypeFoldable<TyCtxt<'tcx>>,
Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>, Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,

View File

@ -1,8 +1,8 @@
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput}; use crate::traits::query::type_op::{self, TypeOp, TypeOpOutput};
use crate::traits::query::NoSolution;
use crate::traits::{ObligationCause, ObligationCtxt}; use crate::traits::{ObligationCause, ObligationCtxt};
use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::resolve::OpportunisticRegionResolver; use rustc_infer::infer::resolve::OpportunisticRegionResolver;
use rustc_middle::ty::{self, ParamEnv, Ty, TypeFolder, TypeVisitableExt}; use rustc_middle::ty::{self, ParamEnv, Ty, TypeFolder, TypeVisitableExt};
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
@ -69,16 +69,12 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
} }
let span = self.tcx.def_span(body_id); let span = self.tcx.def_span(body_id);
let result = param_env let result: Result<_, ErrorGuaranteed> = param_env
.and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty }) .and(type_op::implied_outlives_bounds::ImpliedOutlivesBounds { ty })
.fully_perform(self); .fully_perform(self, span);
let result = match result { let result = match result {
Ok(r) => r, Ok(r) => r,
Err(NoSolution) => { Err(_) => {
self.tcx.sess.delay_span_bug(
span,
"implied_outlives_bounds failed to solve all obligations",
);
return vec![]; return vec![];
} }
}; };

View File

@ -1,5 +1,5 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse}; use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::Fallible; use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
pub use rustc_middle::traits::query::type_op::AscribeUserType; pub use rustc_middle::traits::query::type_op::AscribeUserType;
@ -17,7 +17,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
fn perform_query( fn perform_query(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalQueryResponse<'tcx, ()>> { ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
tcx.type_op_ascribe_user_type(canonicalized) tcx.type_op_ascribe_user_type(canonicalized)
} }
} }

View File

@ -1,11 +1,12 @@
use crate::infer::canonical::query_response; use crate::infer::canonical::query_response;
use crate::infer::InferCtxt; use crate::infer::InferCtxt;
use crate::traits::query::type_op::TypeOpOutput; use crate::traits::query::type_op::TypeOpOutput;
use crate::traits::query::Fallible;
use crate::traits::ObligationCtxt; use crate::traits::ObligationCtxt;
use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_infer::infer::region_constraints::RegionConstraintData;
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
use rustc_span::source_map::DUMMY_SP; use rustc_span::source_map::DUMMY_SP;
use rustc_span::Span;
use std::fmt; use std::fmt;
@ -17,7 +18,7 @@ pub struct CustomTypeOp<F> {
impl<F> CustomTypeOp<F> { impl<F> CustomTypeOp<F> {
pub fn new<'tcx, R>(closure: F, description: &'static str) -> Self pub fn new<'tcx, R>(closure: F, description: &'static str) -> Self
where where
F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>, F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
{ {
CustomTypeOp { closure, description } CustomTypeOp { closure, description }
} }
@ -25,7 +26,7 @@ impl<F> CustomTypeOp<F> {
impl<'tcx, F, R: fmt::Debug> super::TypeOp<'tcx> for CustomTypeOp<F> impl<'tcx, F, R: fmt::Debug> super::TypeOp<'tcx> for CustomTypeOp<F>
where where
F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>, F: FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
{ {
type Output = R; type Output = R;
/// We can't do any custom error reporting for `CustomTypeOp`, so /// We can't do any custom error reporting for `CustomTypeOp`, so
@ -35,12 +36,16 @@ where
/// Processes the operation and all resulting obligations, /// Processes the operation and all resulting obligations,
/// returning the final result along with any region constraints /// returning the final result along with any region constraints
/// (they will be given over to the NLL region solver). /// (they will be given over to the NLL region solver).
fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> { fn fully_perform(
self,
infcx: &InferCtxt<'tcx>,
span: Span,
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
if cfg!(debug_assertions) { if cfg!(debug_assertions) {
info!("fully_perform({:?})", self); info!("fully_perform({:?})", self);
} }
Ok(scrape_region_constraints(infcx, self.closure)?.0) Ok(scrape_region_constraints(infcx, self.closure, self.description, span)?.0)
} }
} }
@ -54,8 +59,10 @@ impl<F> fmt::Debug for CustomTypeOp<F> {
/// constraints that result, creating query-region-constraints. /// constraints that result, creating query-region-constraints.
pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>( pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Fallible<R>, op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
) -> Fallible<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>)> { name: &'static str,
span: Span,
) -> Result<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>), ErrorGuaranteed> {
// During NLL, we expect that nobody will register region // During NLL, we expect that nobody will register region
// obligations **except** as part of a custom type op (and, at the // obligations **except** as part of a custom type op (and, at the
// end of each custom type op, we scrape out the region // end of each custom type op, we scrape out the region
@ -70,16 +77,17 @@ pub fn scrape_region_constraints<'tcx, Op: super::TypeOp<'tcx, Output = R>, R>(
let value = infcx.commit_if_ok(|_| { let value = infcx.commit_if_ok(|_| {
let ocx = ObligationCtxt::new_in_snapshot(infcx); let ocx = ObligationCtxt::new_in_snapshot(infcx);
let value = op(&ocx)?; let value = op(&ocx).map_err(|_| {
infcx.tcx.sess.delay_span_bug(span, format!("error performing operation: {name}"))
})?;
let errors = ocx.select_all_or_error(); let errors = ocx.select_all_or_error();
if errors.is_empty() { if errors.is_empty() {
Ok(value) Ok(value)
} else { } else {
infcx.tcx.sess.delay_span_bug( Err(infcx.tcx.sess.delay_span_bug(
DUMMY_SP, DUMMY_SP,
format!("errors selecting obligation during MIR typeck: {:?}", errors), format!("errors selecting obligation during MIR typeck: {:?}", errors),
); ))
Err(NoSolution)
} }
})?; })?;

View File

@ -1,5 +1,5 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse}; use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::Fallible; use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
pub use rustc_middle::traits::query::type_op::Eq; pub use rustc_middle::traits::query::type_op::Eq;
@ -17,7 +17,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for Eq<'tcx> {
fn perform_query( fn perform_query(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalQueryResponse<'tcx, ()>> { ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
tcx.type_op_eq(canonicalized) tcx.type_op_eq(canonicalized)
} }
} }

View File

@ -1,6 +1,6 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse}; use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::Fallible;
use rustc_infer::traits::query::OutlivesBound; use rustc_infer::traits::query::OutlivesBound;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt}; use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt};
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
@ -28,7 +28,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
fn perform_query( fn perform_query(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> { ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
// FIXME this `unchecked_map` is only necessary because the // FIXME this `unchecked_map` is only necessary because the
// query is defined as taking a `ParamEnvAnd<Ty>`; it should // query is defined as taking a `ParamEnvAnd<Ty>`; it should
// take an `ImpliedOutlivesBounds` instead // take an `ImpliedOutlivesBounds` instead

View File

@ -2,13 +2,14 @@ use crate::infer::canonical::{
Canonical, CanonicalQueryResponse, OriginalQueryValues, QueryRegionConstraints, Canonical, CanonicalQueryResponse, OriginalQueryValues, QueryRegionConstraints,
}; };
use crate::infer::{InferCtxt, InferOk}; use crate::infer::{InferCtxt, InferOk};
use crate::traits::query::Fallible;
use crate::traits::ObligationCause; use crate::traits::ObligationCause;
use rustc_errors::ErrorGuaranteed;
use rustc_infer::infer::canonical::Certainty; use rustc_infer::infer::canonical::Certainty;
use rustc_infer::traits::query::NoSolution;
use rustc_infer::traits::PredicateObligations; use rustc_infer::traits::PredicateObligations;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
use rustc_span::Span;
use std::fmt; use std::fmt;
pub mod ascribe_user_type; pub mod ascribe_user_type;
@ -32,7 +33,11 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
/// Processes the operation and all resulting obligations, /// Processes the operation and all resulting obligations,
/// returning the final result along with any region constraints /// returning the final result along with any region constraints
/// (they will be given over to the NLL region solver). /// (they will be given over to the NLL region solver).
fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>>; fn fully_perform(
self,
infcx: &InferCtxt<'tcx>,
span: Span,
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed>;
} }
/// The output from performing a type op /// The output from performing a type op
@ -74,18 +79,21 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
fn perform_query( fn perform_query(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>>; ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution>;
fn fully_perform_into( fn fully_perform_into(
query_key: ParamEnvAnd<'tcx, Self>, query_key: ParamEnvAnd<'tcx, Self>,
infcx: &InferCtxt<'tcx>, infcx: &InferCtxt<'tcx>,
output_query_region_constraints: &mut QueryRegionConstraints<'tcx>, output_query_region_constraints: &mut QueryRegionConstraints<'tcx>,
) -> Fallible<( ) -> Result<
Self::QueryResponse, (
Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>, Self::QueryResponse,
PredicateObligations<'tcx>, Option<Canonical<'tcx, ParamEnvAnd<'tcx, Self>>>,
Certainty, PredicateObligations<'tcx>,
)> { Certainty,
),
NoSolution,
> {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) { if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &query_key) {
return Ok((result, None, vec![], Certainty::Proven)); return Ok((result, None, vec![], Certainty::Proven));
} }
@ -120,10 +128,16 @@ where
type Output = Q::QueryResponse; type Output = Q::QueryResponse;
type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>; type ErrorInfo = Canonical<'tcx, ParamEnvAnd<'tcx, Q>>;
fn fully_perform(self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> { fn fully_perform(
self,
infcx: &InferCtxt<'tcx>,
span: Span,
) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
let mut region_constraints = QueryRegionConstraints::default(); let mut region_constraints = QueryRegionConstraints::default();
let (output, error_info, mut obligations, _) = let (output, error_info, mut obligations, _) =
Q::fully_perform_into(self, infcx, &mut region_constraints)?; Q::fully_perform_into(self, infcx, &mut region_constraints).map_err(|_| {
infcx.tcx.sess.delay_span_bug(span, format!("error performing {self:?}"))
})?;
// Typically, instantiating NLL query results does not // Typically, instantiating NLL query results does not
// create obligations. However, in some cases there // create obligations. However, in some cases there
@ -151,7 +165,10 @@ where
} }
} }
if !progress { if !progress {
return Err(NoSolution); return Err(infcx.tcx.sess.delay_span_bug(
span,
format!("ambiguity processing {obligations:?} from {self:?}"),
));
} }
} }

View File

@ -1,5 +1,5 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse}; use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::Fallible; use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use std::fmt; use std::fmt;
@ -19,7 +19,7 @@ where
fn perform_query( fn perform_query(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> { ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
T::type_op_method(tcx, canonicalized) T::type_op_method(tcx, canonicalized)
} }
} }
@ -28,14 +28,14 @@ pub trait Normalizable<'tcx>: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tc
fn type_op_method( fn type_op_method(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
) -> Fallible<CanonicalQueryResponse<'tcx, Self>>; ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution>;
} }
impl<'tcx> Normalizable<'tcx> for Ty<'tcx> { impl<'tcx> Normalizable<'tcx> for Ty<'tcx> {
fn type_op_method( fn type_op_method(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
) -> Fallible<CanonicalQueryResponse<'tcx, Self>> { ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
tcx.type_op_normalize_ty(canonicalized) tcx.type_op_normalize_ty(canonicalized)
} }
} }
@ -44,7 +44,7 @@ impl<'tcx> Normalizable<'tcx> for ty::Predicate<'tcx> {
fn type_op_method( fn type_op_method(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
) -> Fallible<CanonicalQueryResponse<'tcx, Self>> { ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
tcx.type_op_normalize_predicate(canonicalized) tcx.type_op_normalize_predicate(canonicalized)
} }
} }
@ -53,7 +53,7 @@ impl<'tcx> Normalizable<'tcx> for ty::PolyFnSig<'tcx> {
fn type_op_method( fn type_op_method(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
) -> Fallible<CanonicalQueryResponse<'tcx, Self>> { ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
tcx.type_op_normalize_poly_fn_sig(canonicalized) tcx.type_op_normalize_poly_fn_sig(canonicalized)
} }
} }
@ -62,7 +62,7 @@ impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> {
fn type_op_method( fn type_op_method(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
) -> Fallible<CanonicalQueryResponse<'tcx, Self>> { ) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
tcx.type_op_normalize_fn_sig(canonicalized) tcx.type_op_normalize_fn_sig(canonicalized)
} }
} }

View File

@ -1,6 +1,6 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse}; use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::dropck_outlives::{trivial_dropck_outlives, DropckOutlivesResult}; use crate::traits::query::dropck_outlives::{trivial_dropck_outlives, DropckOutlivesResult};
use crate::traits::query::Fallible; use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt}; use rustc_middle::ty::{ParamEnvAnd, Ty, TyCtxt};
#[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)] #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
@ -27,7 +27,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
fn perform_query( fn perform_query(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalQueryResponse<'tcx, Self::QueryResponse>> { ) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
// Subtle: note that we are not invoking // Subtle: note that we are not invoking
// `infcx.at(...).dropck_outlives(...)` here, but rather the // `infcx.at(...).dropck_outlives(...)` here, but rather the
// underlying `dropck_outlives` query. This same underlying // underlying `dropck_outlives` query. This same underlying

View File

@ -1,5 +1,5 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse}; use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::Fallible; use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt}; use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt};
pub use rustc_middle::traits::query::type_op::ProvePredicate; pub use rustc_middle::traits::query::type_op::ProvePredicate;
@ -33,7 +33,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
fn perform_query( fn perform_query(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalQueryResponse<'tcx, ()>> { ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
tcx.type_op_prove_predicate(canonicalized) tcx.type_op_prove_predicate(canonicalized)
} }
} }

View File

@ -1,5 +1,5 @@
use crate::infer::canonical::{Canonical, CanonicalQueryResponse}; use crate::infer::canonical::{Canonical, CanonicalQueryResponse};
use crate::traits::query::Fallible; use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt}; use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
pub use rustc_middle::traits::query::type_op::Subtype; pub use rustc_middle::traits::query::type_op::Subtype;
@ -14,7 +14,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for Subtype<'tcx> {
fn perform_query( fn perform_query(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>, canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Self>>,
) -> Fallible<CanonicalQueryResponse<'tcx, ()>> { ) -> Result<CanonicalQueryResponse<'tcx, ()>, NoSolution> {
tcx.type_op_subtype(canonicalized) tcx.type_op_subtype(canonicalized)
} }
} }

View File

@ -11,7 +11,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::source_map::DUMMY_SP; use rustc_span::source_map::DUMMY_SP;
use rustc_trait_selection::infer::InferCtxtBuilderExt; use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
use rustc_trait_selection::traits::wf; use rustc_trait_selection::traits::wf;
use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::ObligationCtxt;
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
@ -37,7 +37,7 @@ fn compute_implied_outlives_bounds<'tcx>(
ocx: &ObligationCtxt<'_, 'tcx>, ocx: &ObligationCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> Fallible<Vec<OutlivesBound<'tcx>>> { ) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
let tcx = ocx.infcx.tcx; let tcx = ocx.infcx.tcx;
// Sometimes when we ask what it takes for T: WF, we get back that // Sometimes when we ask what it takes for T: WF, we get back that

View File

@ -2,6 +2,7 @@ use rustc_hir as hir;
use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode}; use rustc_middle::traits::{DefiningAnchor, ObligationCauseCode};
use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{ParamEnvAnd, Predicate}; use rustc_middle::ty::{ParamEnvAnd, Predicate};
@ -15,7 +16,6 @@ use rustc_trait_selection::traits::query::type_op::eq::Eq;
use rustc_trait_selection::traits::query::type_op::normalize::Normalize; use rustc_trait_selection::traits::query::type_op::normalize::Normalize;
use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate; use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate;
use rustc_trait_selection::traits::query::type_op::subtype::Subtype; use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
use rustc_trait_selection::traits::query::{Fallible, NoSolution};
use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt}; use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt};
use std::fmt; use std::fmt;
@ -160,7 +160,7 @@ fn type_op_eq<'tcx>(
fn type_op_normalize<'tcx, T>( fn type_op_normalize<'tcx, T>(
ocx: &ObligationCtxt<'_, 'tcx>, ocx: &ObligationCtxt<'_, 'tcx>,
key: ParamEnvAnd<'tcx, Normalize<T>>, key: ParamEnvAnd<'tcx, Normalize<T>>,
) -> Fallible<T> ) -> Result<T, NoSolution>
where where
T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx>, T: fmt::Debug + TypeFoldable<TyCtxt<'tcx>> + Lift<'tcx>,
{ {