Use ErrorGuaranteed more in MIR type ops
This commit is contained in:
parent
cade26637f
commit
91525a4324
8 changed files with 104 additions and 107 deletions
|
@ -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:?}`",
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 },
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -216,24 +217,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() {
|
||||||
|
@ -2755,11 +2754,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)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
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;
|
||||||
|
@ -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",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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![];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,9 +3,10 @@ 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::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_span::source_map::DUMMY_SP;
|
use rustc_span::source_map::DUMMY_SP;
|
||||||
|
use rustc_span::Span;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +60,9 @@ impl<F> fmt::Debug for CustomTypeOp<F> {
|
||||||
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>) -> Fallible<R>,
|
||||||
) -> 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)
|
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,12 @@ use crate::infer::canonical::{
|
||||||
use crate::infer::{InferCtxt, InferOk};
|
use crate::infer::{InferCtxt, InferOk};
|
||||||
use crate::traits::query::Fallible;
|
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::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
|
||||||
|
@ -120,10 +125,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 +162,10 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !progress {
|
if !progress {
|
||||||
return Err(NoSolution);
|
return Err(infcx.tcx.sess.delay_span_bug(
|
||||||
|
span,
|
||||||
|
format!("ambiguity processing {obligations:?} from {self:?}"),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue