1
Fork 0

Auto merge of #111925 - Manishearth:rollup-z6z6l2v, r=Manishearth

Rollup of 5 pull requests

Successful merges:

 - #111741 (Use `ObligationCtxt` in custom type ops)
 - #111840 (Expose more information in `get_body_with_borrowck_facts`)
 - #111876 (Roll compiler_builtins to 0.1.92)
 - #111912 (Use `Option::is_some_and` and `Result::is_ok_and` in the compiler  )
 - #111915 (libtest: Improve error when missing `-Zunstable-options`)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-05-25 00:33:43 +00:00
commit 7664dfe433
115 changed files with 417 additions and 378 deletions

View file

@ -30,7 +30,7 @@ pub struct BorrowSet<'tcx> {
/// Map from local to all the borrows on that local.
pub local_map: FxIndexMap<mir::Local, FxIndexSet<BorrowIndex>>,
pub(crate) locals_state_at_exit: LocalsStateAtExit,
pub locals_state_at_exit: LocalsStateAtExit,
}
impl<'tcx> Index<BorrowIndex> for BorrowSet<'tcx> {
@ -153,7 +153,7 @@ impl<'tcx> BorrowSet<'tcx> {
self.activation_map.get(&location).map_or(&[], |activations| &activations[..])
}
pub(crate) fn len(&self) -> usize {
pub fn len(&self) -> usize {
self.location_map.len()
}

View file

@ -3,22 +3,95 @@
//! This file provides API for compiler consumers.
use rustc_hir::def_id::LocalDefId;
use rustc_index::IndexSlice;
use rustc_index::{IndexSlice, IndexVec};
use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
use rustc_middle::mir::Body;
use rustc_middle::mir::{Body, Promoted};
use rustc_middle::ty::TyCtxt;
use std::rc::Rc;
use crate::borrow_set::BorrowSet;
pub use super::{
constraints::OutlivesConstraint,
dataflow::{calculate_borrows_out_of_scope_at_location, BorrowIndex, Borrows},
facts::{AllFacts as PoloniusInput, RustcFacts},
location::{LocationTable, RichLocation},
nll::PoloniusOutput,
BodyWithBorrowckFacts,
place_ext::PlaceExt,
places_conflict::{places_conflict, PlaceConflictBias},
region_infer::RegionInferenceContext,
};
/// This function computes Polonius facts for the given body. It makes a copy of
/// the body because it needs to regenerate the region identifiers. This function
/// should never be invoked during a typical compilation session due to performance
/// issues with Polonius.
/// Options determining the output behavior of [`get_body_with_borrowck_facts`].
///
/// If executing under `-Z polonius` the choice here has no effect, and everything as if
/// [`PoloniusOutputFacts`](ConsumerOptions::PoloniusOutputFacts) had been selected
/// will be retrieved.
#[derive(Debug, Copy, Clone)]
pub enum ConsumerOptions {
/// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet)
/// and [`RegionInferenceContext`]. If you would like the body only, use
/// [`TyCtxt::mir_promoted`].
///
/// These can be used in conjunction with [`calculate_borrows_out_of_scope_at_location`].
RegionInferenceContext,
/// The recommended option. Retrieves the maximal amount of information
/// without significant slowdowns.
///
/// Implies [`RegionInferenceContext`](ConsumerOptions::RegionInferenceContext),
/// and additionally retrieve the [`LocationTable`] and [`PoloniusInput`] that
/// would be given to Polonius. Critically, this does not run Polonius, which
/// one may want to avoid due to performance issues on large bodies.
PoloniusInputFacts,
/// Implies [`PoloniusInputFacts`](ConsumerOptions::PoloniusInputFacts),
/// and additionally runs Polonius to calculate the [`PoloniusOutput`].
PoloniusOutputFacts,
}
impl ConsumerOptions {
/// Should the Polonius input facts be computed?
pub(crate) fn polonius_input(&self) -> bool {
matches!(self, Self::PoloniusInputFacts | Self::PoloniusOutputFacts)
}
/// Should we run Polonius and collect the output facts?
pub(crate) fn polonius_output(&self) -> bool {
matches!(self, Self::PoloniusOutputFacts)
}
}
/// A `Body` with information computed by the borrow checker. This struct is
/// intended to be consumed by compiler consumers.
///
/// We need to include the MIR body here because the region identifiers must
/// match the ones in the Polonius facts.
pub struct BodyWithBorrowckFacts<'tcx> {
/// A mir body that contains region identifiers.
pub body: Body<'tcx>,
/// The mir bodies of promoteds.
pub promoted: IndexVec<Promoted, Body<'tcx>>,
/// The set of borrows occurring in `body` with data about them.
pub borrow_set: Rc<BorrowSet<'tcx>>,
/// Context generated during borrowck, intended to be passed to
/// [`calculate_borrows_out_of_scope_at_location`].
pub region_inference_context: Rc<RegionInferenceContext<'tcx>>,
/// The table that maps Polonius points to locations in the table.
/// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
/// or [`ConsumerOptions::PoloniusOutputFacts`].
pub location_table: Option<LocationTable>,
/// Polonius input facts.
/// Populated when using [`ConsumerOptions::PoloniusInputFacts`]
/// or [`ConsumerOptions::PoloniusOutputFacts`].
pub input_facts: Option<Box<PoloniusInput>>,
/// Polonius output facts. Populated when using
/// [`ConsumerOptions::PoloniusOutputFacts`].
pub output_facts: Option<Rc<PoloniusOutput>>,
}
/// This function computes borrowck facts for the given body. The [`ConsumerOptions`]
/// determine which facts are returned. This function makes a copy of the body because
/// it needs to regenerate the region identifiers. It should never be invoked during a
/// typical compilation session due to the unnecessary overhead of returning
/// [`BodyWithBorrowckFacts`].
///
/// Note:
/// * This function will panic if the required body was already stolen. This
@ -28,10 +101,14 @@ pub use super::{
/// that shows how to do this at `tests/run-make/obtain-borrowck/`.
///
/// * Polonius is highly unstable, so expect regular changes in its signature or other details.
pub fn get_body_with_borrowck_facts(tcx: TyCtxt<'_>, def: LocalDefId) -> BodyWithBorrowckFacts<'_> {
pub fn get_body_with_borrowck_facts(
tcx: TyCtxt<'_>,
def: LocalDefId,
options: ConsumerOptions,
) -> BodyWithBorrowckFacts<'_> {
let (input_body, promoted) = tcx.mir_promoted(def);
let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build();
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexSlice<_, _> = &promoted.borrow();
*super::do_mir_borrowck(&infcx, input_body, promoted, true).1.unwrap()
*super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()
}

View file

@ -228,27 +228,32 @@ impl<'tcx> OutOfScopePrecomputer<'_, 'tcx> {
}
}
pub fn calculate_borrows_out_of_scope_at_location<'tcx>(
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
borrow_set: &BorrowSet<'tcx>,
) -> FxIndexMap<Location, Vec<BorrowIndex>> {
let mut prec = OutOfScopePrecomputer::new(body, regioncx);
for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
let borrow_region = borrow_data.region;
let location = borrow_data.reserve_location;
prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
}
prec.borrows_out_of_scope_at_location
}
impl<'a, 'tcx> Borrows<'a, 'tcx> {
pub(crate) fn new(
pub fn new(
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
nonlexical_regioncx: &'a RegionInferenceContext<'tcx>,
borrow_set: &'a BorrowSet<'tcx>,
) -> Self {
let mut prec = OutOfScopePrecomputer::new(body, nonlexical_regioncx);
for (borrow_index, borrow_data) in borrow_set.iter_enumerated() {
let borrow_region = borrow_data.region;
let location = borrow_data.reserve_location;
prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
}
Borrows {
tcx,
body,
borrow_set,
borrows_out_of_scope_at_location: prec.borrows_out_of_scope_at_location,
}
let borrows_out_of_scope_at_location =
calculate_borrows_out_of_scope_at_location(body, nonlexical_regioncx, borrow_set);
Borrows { tcx, body, borrow_set, borrows_out_of_scope_at_location }
}
pub fn location(&self, idx: BorrowIndex) -> &Location {

View file

@ -128,7 +128,7 @@ impl<'tcx> ToUniverseInfo<'tcx>
}
}
impl<'tcx, F, G> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F, G>> {
impl<'tcx, F> ToUniverseInfo<'tcx> for Canonical<'tcx, type_op::custom::CustomTypeOp<F>> {
fn to_universe_info(self, _base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
// We can't rerun custom type ops.
UniverseInfo::other()

View file

@ -118,7 +118,7 @@ impl<'tcx> BorrowExplanation<'tcx> {
let path_span = path_span.unwrap();
// path_span is only present in the case of closure capture
assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture));
if !borrow_span.map_or(false, |sp| sp.overlaps(var_or_use_span)) {
if !borrow_span.is_some_and(|sp| sp.overlaps(var_or_use_span)) {
let path_label = "used here by closure";
let capture_kind_label = message;
err.span_label(
@ -224,12 +224,9 @@ impl<'tcx> BorrowExplanation<'tcx> {
if info.tail_result_is_ignored {
// #85581: If the first mutable borrow's scope contains
// the second borrow, this suggestion isn't helpful.
if !multiple_borrow_span
.map(|(old, new)| {
old.to(info.span.shrink_to_hi()).contains(new)
})
.unwrap_or(false)
{
if !multiple_borrow_span.is_some_and(|(old, new)| {
old.to(info.span.shrink_to_hi()).contains(new)
}) {
err.span_suggestion_verbose(
info.span.shrink_to_hi(),
"consider adding semicolon after the expression so its \

View file

@ -1156,7 +1156,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ty::Adt(def, ..) => Some(def.did()),
_ => None,
});
let is_option_or_result = parent_self_ty.map_or(false, |def_id| {
let is_option_or_result = parent_self_ty.is_some_and(|def_id| {
matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
});
if is_option_or_result && maybe_reinitialized_locations_is_empty {

View file

@ -289,8 +289,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.body
.local_decls
.get(local)
.map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local]))
.unwrap_or(false) =>
.is_some_and(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) =>
{
let decl = &self.body.local_decls[local];
err.span_label(span, format!("cannot {act}"));
@ -443,7 +442,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
.sess
.source_map()
.span_to_snippet(span)
.map_or(false, |snippet| snippet.starts_with("&mut ")) =>
.is_ok_and(|snippet| snippet.starts_with("&mut ")) =>
{
err.span_label(span, format!("cannot {act}"));
err.span_suggestion(

View file

@ -125,8 +125,7 @@ impl OutlivesSuggestionBuilder {
|(r, _)| {
self.constraints_to_add
.get(r)
.map(|r_outlived| r_outlived.as_slice().contains(fr))
.unwrap_or(false)
.is_some_and(|r_outlived| r_outlived.as_slice().contains(fr))
},
);

View file

@ -61,7 +61,7 @@ use crate::session_diagnostics::VarNeedNotMut;
use self::diagnostics::{AccessKind, RegionName};
use self::location::LocationTable;
use self::prefixes::PrefixSet;
use facts::AllFacts;
use consumers::{BodyWithBorrowckFacts, ConsumerOptions};
use self::path_utils::*;
@ -143,7 +143,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
let input_body: &Body<'_> = &input_body.borrow();
let promoted: &IndexSlice<_, _> = &promoted.borrow();
let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, false).0;
let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
debug!("mir_borrowck done");
tcx.arena.alloc(opt_closure_req)
@ -151,15 +151,15 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
/// Perform the actual borrow checking.
///
/// If `return_body_with_facts` is true, then return the body with non-erased
/// region ids on which the borrow checking was performed together with Polonius
/// facts.
/// Use `consumer_options: None` for the default behavior of returning
/// [`BorrowCheckResult`] only. Otherwise, return [`BodyWithBorrowckFacts`] according
/// to the given [`ConsumerOptions`].
#[instrument(skip(infcx, input_body, input_promoted), fields(id=?input_body.source.def_id()), level = "debug")]
fn do_mir_borrowck<'tcx>(
infcx: &InferCtxt<'tcx>,
input_body: &Body<'tcx>,
input_promoted: &IndexSlice<Promoted, Body<'tcx>>,
return_body_with_facts: bool,
consumer_options: Option<ConsumerOptions>,
) -> (BorrowCheckResult<'tcx>, Option<Box<BodyWithBorrowckFacts<'tcx>>>) {
let def = input_body.source.def_id().expect_local();
debug!(?def);
@ -240,8 +240,6 @@ fn do_mir_borrowck<'tcx>(
let borrow_set =
Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data));
let use_polonius = return_body_with_facts || infcx.tcx.sess.opts.unstable_opts.polonius;
// Compute non-lexical lifetimes.
let nll::NllOutput {
regioncx,
@ -261,7 +259,7 @@ fn do_mir_borrowck<'tcx>(
&mdpe.move_data,
&borrow_set,
&upvars,
use_polonius,
consumer_options,
);
// Dump MIR results into a file, if that is enabled. This let us
@ -441,13 +439,16 @@ fn do_mir_borrowck<'tcx>(
tainted_by_errors,
};
let body_with_facts = if return_body_with_facts {
let output_facts = mbcx.polonius_output.expect("Polonius output was not computed");
let body_with_facts = if consumer_options.is_some() {
let output_facts = mbcx.polonius_output;
Some(Box::new(BodyWithBorrowckFacts {
body: body_owned,
input_facts: *polonius_input.expect("Polonius input facts were not generated"),
promoted,
borrow_set,
region_inference_context: regioncx,
location_table: polonius_input.as_ref().map(|_| location_table_owned),
input_facts: polonius_input,
output_facts,
location_table: location_table_owned,
}))
} else {
None
@ -458,22 +459,6 @@ fn do_mir_borrowck<'tcx>(
(result, body_with_facts)
}
/// A `Body` with information computed by the borrow checker. This struct is
/// intended to be consumed by compiler consumers.
///
/// We need to include the MIR body here because the region identifiers must
/// match the ones in the Polonius facts.
pub struct BodyWithBorrowckFacts<'tcx> {
/// A mir body that contains region identifiers.
pub body: Body<'tcx>,
/// Polonius input facts.
pub input_facts: AllFacts,
/// Polonius output facts.
pub output_facts: Rc<self::nll::PoloniusOutput>,
/// The table that maps Polonius points to locations in the table.
pub location_table: LocationTable,
}
pub struct BorrowckInferCtxt<'cx, 'tcx> {
pub(crate) infcx: &'cx InferCtxt<'tcx>,
pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,

View file

@ -27,6 +27,7 @@ use rustc_mir_dataflow::ResultsCursor;
use crate::{
borrow_set::BorrowSet,
constraint_generation,
consumers::ConsumerOptions,
diagnostics::RegionErrors,
facts::{AllFacts, AllFactsExt, RustcFacts},
invalidation,
@ -165,10 +166,14 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
move_data: &MoveData<'tcx>,
borrow_set: &BorrowSet<'tcx>,
upvars: &[Upvar<'tcx>],
use_polonius: bool,
consumer_options: Option<ConsumerOptions>,
) -> NllOutput<'tcx> {
let polonius_input = consumer_options.map(|c| c.polonius_input()).unwrap_or_default()
|| infcx.tcx.sess.opts.unstable_opts.polonius;
let polonius_output = consumer_options.map(|c| c.polonius_output()).unwrap_or_default()
|| infcx.tcx.sess.opts.unstable_opts.polonius;
let mut all_facts =
(use_polonius || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
(polonius_input || AllFacts::enabled(infcx.tcx)).then_some(AllFacts::default());
let universal_regions = Rc::new(universal_regions);
@ -189,7 +194,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
move_data,
elements,
upvars,
use_polonius,
polonius_input,
);
if let Some(all_facts) = &mut all_facts {
@ -284,7 +289,7 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
all_facts.write_to_dir(dir_path, location_table).unwrap();
}
if use_polonius {
if polonius_output {
let algorithm =
env::var("POLONIUS_ALGORITHM").unwrap_or_else(|_| String::from("Hybrid"));
let algorithm = Algorithm::from_str(&algorithm).unwrap();

View file

@ -7,7 +7,7 @@ use rustc_middle::mir::{Body, Mutability, Place};
use rustc_middle::ty::{self, TyCtxt};
/// Extension methods for the `Place` type.
pub(crate) trait PlaceExt<'tcx> {
pub trait PlaceExt<'tcx> {
/// Returns `true` if we can safely ignore borrows of this place.
/// This is true whenever there is no action that the user can do
/// to the place `self` that would invalidate the borrow. This is true

View file

@ -16,7 +16,7 @@ use std::iter;
/// being run in the calling context, the conservative choice is to assume the compared indices
/// are disjoint (and therefore, do not overlap).
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum PlaceConflictBias {
pub enum PlaceConflictBias {
Overlap,
NoOverlap,
}
@ -24,7 +24,7 @@ pub(crate) enum PlaceConflictBias {
/// Helper function for checking if places conflict with a mutable borrow and deep access depth.
/// This is used to check for places conflicting outside of the borrow checking code (such as in
/// dataflow).
pub(crate) fn places_conflict<'tcx>(
pub fn places_conflict<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
borrow_place: Place<'tcx>,

View file

@ -585,6 +585,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
self.universal_regions.to_region_vid(r)
}
/// Returns an iterator over all the outlives constraints.
pub fn outlives_constraints(&self) -> impl Iterator<Item = OutlivesConstraint<'tcx>> + '_ {
self.constraints.outlives().iter().copied()
}
/// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`.
pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diagnostic) {
self.universal_regions.annotate(tcx, err)
@ -712,7 +717,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
#[instrument(skip(self, _body), level = "debug")]
fn propagate_constraints(&mut self, _body: &Body<'tcx>) {
debug!("constraints={:#?}", {
let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
let mut constraints: Vec<_> = self.outlives_constraints().collect();
constraints.sort_by_key(|c| (c.sup, c.sub));
constraints
.into_iter()

View file

@ -159,7 +159,7 @@ impl<N: Idx> LivenessValues<N> {
/// Returns `true` if the region `r` contains the given element.
pub(crate) fn contains(&self, row: N, location: Location) -> bool {
let index = self.elements.point_from_location(location);
self.points.row(row).map_or(false, |r| r.contains(index))
self.points.row(row).is_some_and(|r| r.contains(index))
}
/// Returns an iterator of all the elements contained by the region `r`

View file

@ -1,13 +1,13 @@
use std::fmt;
use rustc_infer::infer::{canonical::Canonical, InferOk};
use rustc_infer::infer::canonical::Canonical;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_span::def_id::DefId;
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
use rustc_trait_selection::traits::query::{Fallible, NoSolution};
use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
use rustc_trait_selection::traits::ObligationCause;
use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
@ -219,20 +219,17 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let cause = ObligationCause::dummy_with_span(span);
let param_env = self.param_env;
let op = |infcx: &'_ _| {
let ocx = ObligationCtxt::new_in_snapshot(infcx);
let user_ty = ocx.normalize(&cause, param_env, user_ty);
ocx.eq(&cause, param_env, user_ty, mir_ty)?;
if !ocx.select_all_or_error().is_empty() {
return Err(NoSolution);
}
Ok(InferOk { value: (), obligations: vec![] })
};
self.fully_perform_op(
Locations::All(span),
ConstraintCategory::Boring,
type_op::custom::CustomTypeOp::new(op, || "ascribe_user_type_skip_wf".to_string()),
type_op::custom::CustomTypeOp::new(
|ocx| {
let user_ty = ocx.normalize(&cause, param_env, user_ty);
ocx.eq(&cause, param_env, user_ty, mir_ty)?;
Ok(())
},
"ascribe_user_type_skip_wf",
),
)
.unwrap_or_else(|err| {
span_mirbug!(

View file

@ -20,7 +20,7 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::region_constraints::RegionConstraintData;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::{
InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
InferCtxt, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
};
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
@ -211,16 +211,16 @@ pub(crate) fn type_check<'mir, 'tcx>(
Locations::All(body.span),
ConstraintCategory::OpaqueType,
CustomTypeOp::new(
|infcx| {
infcx.register_member_constraints(
|ocx| {
ocx.infcx.register_member_constraints(
param_env,
opaque_type_key,
decl.hidden_type.ty,
decl.hidden_type.span,
);
Ok(InferOk { value: (), obligations: vec![] })
Ok(())
},
|| "opaque_type_map".to_string(),
"opaque_type_map",
),
)
.unwrap();
@ -2695,8 +2695,9 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
type ErrorInfo = InstantiateOpaqueType<'tcx>;
fn fully_perform(mut self, infcx: &InferCtxt<'tcx>) -> Fallible<TypeOpOutput<'tcx, Self>> {
let (mut output, region_constraints) = scrape_region_constraints(infcx, || {
Ok(InferOk { value: (), obligations: self.obligations.clone() })
let (mut output, region_constraints) = scrape_region_constraints(infcx, |ocx| {
ocx.register_obligations(self.obligations.clone());
Ok(())
})?;
self.region_constraints = Some(region_constraints);
output.error_info = Some(self);

View file

@ -185,17 +185,25 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
}
fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.type_checker
.fully_perform_op(
self.locations,
self.category,
InstantiateOpaqueType {
obligations,
// These fields are filled in during execution of the operation
base_universe: None,
region_constraints: None,
},
)
.unwrap();
match self.type_checker.fully_perform_op(
self.locations,
self.category,
InstantiateOpaqueType {
obligations,
// These fields are filled in during execution of the operation
base_universe: 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",
);
}
};
}
}