Auto merge of #110275 - matthiaskrgr:rollup-8ntb3o5, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #110072 (Stabilize IsTerminal) - #110195 (Erase lifetimes above `ty::INNERMOST` when probing ambiguous types) - #110218 (Remove `ToRegionVid`) - #110220 (cleanup our region error API) - #110234 (Fix btree `CursorMut::insert_after` check) - #110262 (Update unwind_safe.rs) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
fab99073b0
@ -1,6 +1,5 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
use crate::nll::ToRegionVid;
|
||||
use crate::path_utils::allow_two_phase_borrow;
|
||||
use crate::place_ext::PlaceExt;
|
||||
use crate::BorrowIndex;
|
||||
@ -204,7 +203,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
let region = region.to_region_vid();
|
||||
let region = region.as_var();
|
||||
|
||||
let borrow = BorrowData {
|
||||
kind,
|
||||
@ -279,7 +278,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
|
||||
let borrow_data = &self.location_map[&location];
|
||||
assert_eq!(borrow_data.reserve_location, location);
|
||||
assert_eq!(borrow_data.kind, kind);
|
||||
assert_eq!(borrow_data.region, region.to_region_vid());
|
||||
assert_eq!(borrow_data.region, region.as_var());
|
||||
assert_eq!(borrow_data.borrowed_place, place);
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,8 @@ use rustc_middle::ty::visit::TypeVisitable;
|
||||
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
|
||||
|
||||
use crate::{
|
||||
borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, nll::ToRegionVid,
|
||||
places_conflict, region_infer::values::LivenessValues,
|
||||
borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, places_conflict,
|
||||
region_infer::values::LivenessValues,
|
||||
};
|
||||
|
||||
pub(super) fn generate_constraints<'tcx>(
|
||||
@ -170,7 +170,7 @@ impl<'cx, 'tcx> ConstraintGeneration<'cx, 'tcx> {
|
||||
debug!("add_regular_live_constraint(live_ty={:?}, location={:?})", live_ty, location);
|
||||
|
||||
self.infcx.tcx.for_each_free_region(&live_ty, |live_region| {
|
||||
let vid = live_region.to_region_vid();
|
||||
let vid = live_region.as_var();
|
||||
self.liveness_constraints.add_element(vid, location);
|
||||
});
|
||||
}
|
||||
|
@ -11,9 +11,7 @@ use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill}
|
||||
use rustc_mir_dataflow::{Analysis, Direction, Results};
|
||||
use std::fmt;
|
||||
|
||||
use crate::{
|
||||
places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext, ToRegionVid,
|
||||
};
|
||||
use crate::{places_conflict, BorrowSet, PlaceConflictBias, PlaceExt, RegionInferenceContext};
|
||||
|
||||
/// A tuple with named fields that can hold either the results or the transient state of the
|
||||
/// dataflow analyses used by the borrow checker.
|
||||
@ -242,7 +240,7 @@ impl<'a, 'tcx> Borrows<'a, '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.to_region_vid();
|
||||
let borrow_region = borrow_data.region;
|
||||
let location = borrow_data.reserve_location;
|
||||
|
||||
prec.precompute_borrows_out_of_scope(borrow_index, borrow_region, location);
|
||||
|
@ -6,7 +6,6 @@ use std::rc::Rc;
|
||||
|
||||
use crate::{
|
||||
def_use::{self, DefUse},
|
||||
nll::ToRegionVid,
|
||||
region_infer::{Cause, RegionInferenceContext},
|
||||
};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
@ -117,7 +116,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'tcx> {
|
||||
|
||||
let mut found_it = false;
|
||||
self.tcx.for_each_free_region(&local_ty, |r| {
|
||||
if r.to_region_vid() == self.region_vid {
|
||||
if r.as_var() == self.region_vid {
|
||||
found_it = true;
|
||||
}
|
||||
});
|
||||
|
@ -10,7 +10,7 @@ use rustc_middle::ty::{self, RegionVid, Ty};
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use crate::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt};
|
||||
use crate::{universal_regions::DefiningTy, MirBorrowckCtxt};
|
||||
|
||||
/// A name for a particular region used in emitting diagnostics. This name could be a generated
|
||||
/// name like `'1`, a name used by the user like `'a`, or a name like `'static`.
|
||||
@ -497,7 +497,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
// &
|
||||
// - let's call the lifetime of this reference `'1`
|
||||
(ty::Ref(region, referent_ty, _), hir::TyKind::Ref(_lifetime, referent_hir_ty)) => {
|
||||
if region.to_region_vid() == needle_fr {
|
||||
if region.as_var() == needle_fr {
|
||||
// Just grab the first character, the `&`.
|
||||
let source_map = self.infcx.tcx.sess.source_map();
|
||||
let ampersand_span = source_map.start_point(hir_ty.span);
|
||||
@ -598,7 +598,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
for (kind, hir_arg) in iter::zip(substs, args.args) {
|
||||
match (kind.unpack(), hir_arg) {
|
||||
(GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => {
|
||||
if r.to_region_vid() == needle_fr {
|
||||
if r.as_var() == needle_fr {
|
||||
return Some(lt);
|
||||
}
|
||||
}
|
||||
@ -666,7 +666,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
|
||||
let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
|
||||
debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty);
|
||||
if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) {
|
||||
if !tcx.any_free_region_meets(&return_ty, |r| r.as_var() == fr) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -803,7 +803,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||
|
||||
let tcx = self.infcx.tcx;
|
||||
|
||||
if !tcx.any_free_region_meets(&yield_ty, |r| r.to_region_vid() == fr) {
|
||||
if !tcx.any_free_region_meets(&yield_ty, |r| r.as_var() == fr) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
use crate::region_infer::RegionInferenceContext;
|
||||
use crate::Upvar;
|
||||
use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext};
|
||||
use rustc_index::vec::{Idx, IndexSlice};
|
||||
use rustc_middle::mir::{Body, Local};
|
||||
use rustc_middle::ty::{RegionVid, TyCtxt};
|
||||
@ -46,7 +46,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| {
|
||||
debug!("get_upvar_index_for_region: upvar_ty={upvar_ty:?}");
|
||||
tcx.any_free_region_meets(&upvar_ty, |r| {
|
||||
let r = r.to_region_vid();
|
||||
let r = r.as_var();
|
||||
debug!("get_upvar_index_for_region: r={r:?} fr={fr:?}");
|
||||
r == fr
|
||||
})
|
||||
@ -96,7 +96,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position(
|
||||
|arg_ty| {
|
||||
debug!("get_argument_index_for_region: arg_ty = {arg_ty:?}");
|
||||
tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr)
|
||||
tcx.any_free_region_meets(arg_ty, |r| r.as_var() == fr)
|
||||
},
|
||||
)?;
|
||||
|
||||
|
@ -94,7 +94,7 @@ pub mod consumers;
|
||||
|
||||
use borrow_set::{BorrowData, BorrowSet};
|
||||
use dataflow::{BorrowIndex, BorrowckFlowState as Flows, BorrowckResults, Borrows};
|
||||
use nll::{PoloniusOutput, ToRegionVid};
|
||||
use nll::PoloniusOutput;
|
||||
use place_ext::PlaceExt;
|
||||
use places_conflict::{places_conflict, PlaceConflictBias};
|
||||
use region_infer::RegionInferenceContext;
|
||||
@ -507,9 +507,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
|
||||
F: Fn() -> RegionCtxt,
|
||||
{
|
||||
let next_region = self.infcx.next_region_var(origin);
|
||||
let vid = next_region
|
||||
.as_var()
|
||||
.unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region));
|
||||
let vid = next_region.as_var();
|
||||
|
||||
if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() {
|
||||
debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin);
|
||||
@ -531,9 +529,7 @@ impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
|
||||
F: Fn() -> RegionCtxt,
|
||||
{
|
||||
let next_region = self.infcx.next_nll_region_var(origin.clone());
|
||||
let vid = next_region
|
||||
.as_var()
|
||||
.unwrap_or_else(|| bug!("expected RegionKind::RegionVar on {:?}", next_region));
|
||||
let vid = next_region.as_var();
|
||||
|
||||
if cfg!(debug_assertions) && !self.inside_canonicalization_ctxt() {
|
||||
debug!("inserting vid {:?} with origin {:?} into var_to_origin", vid, origin);
|
||||
|
@ -10,7 +10,7 @@ use rustc_middle::mir::{
|
||||
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
|
||||
Promoted,
|
||||
};
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid, TyCtxt};
|
||||
use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt};
|
||||
use rustc_span::symbol::sym;
|
||||
use std::env;
|
||||
use std::io;
|
||||
@ -444,27 +444,6 @@ fn for_each_region_constraint<'tcx>(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Right now, we piggy back on the `ReVar` to store our NLL inference
|
||||
/// regions. These are indexed with `RegionVid`. This method will
|
||||
/// assert that the region is a `ReVar` and extract its internal index.
|
||||
/// This is reasonable because in our MIR we replace all universal regions
|
||||
/// with inference variables.
|
||||
pub trait ToRegionVid {
|
||||
fn to_region_vid(self) -> RegionVid;
|
||||
}
|
||||
|
||||
impl<'tcx> ToRegionVid for Region<'tcx> {
|
||||
fn to_region_vid(self) -> RegionVid {
|
||||
if let ty::ReVar(vid) = *self { vid } else { bug!("region is not an ReVar: {:?}", self) }
|
||||
}
|
||||
}
|
||||
|
||||
impl ToRegionVid for RegionVid {
|
||||
fn to_region_vid(self) -> RegionVid {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait ConstraintDescription {
|
||||
fn description(&self) -> &'static str;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ use crate::{
|
||||
},
|
||||
diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo},
|
||||
member_constraints::{MemberConstraintSet, NllMemberConstraintIndex},
|
||||
nll::{PoloniusOutput, ToRegionVid},
|
||||
nll::PoloniusOutput,
|
||||
region_infer::reverse_sccs::ReverseSccGraph,
|
||||
region_infer::values::{
|
||||
LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues,
|
||||
@ -593,14 +593,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// Returns `true` if the region `r` contains the point `p`.
|
||||
///
|
||||
/// Panics if called before `solve()` executes,
|
||||
pub(crate) fn region_contains(&self, r: impl ToRegionVid, p: impl ToElementIndex) -> bool {
|
||||
let scc = self.constraint_sccs.scc(r.to_region_vid());
|
||||
pub(crate) fn region_contains(&self, r: RegionVid, p: impl ToElementIndex) -> bool {
|
||||
let scc = self.constraint_sccs.scc(r);
|
||||
self.scc_values.contains(scc, p)
|
||||
}
|
||||
|
||||
/// Returns access to the value of `r` for debugging purposes.
|
||||
pub(crate) fn region_value_str(&self, r: RegionVid) -> String {
|
||||
let scc = self.constraint_sccs.scc(r.to_region_vid());
|
||||
let scc = self.constraint_sccs.scc(r);
|
||||
self.scc_values.region_value_str(scc)
|
||||
}
|
||||
|
||||
@ -608,24 +608,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
&'a self,
|
||||
r: RegionVid,
|
||||
) -> impl Iterator<Item = ty::PlaceholderRegion> + 'a {
|
||||
let scc = self.constraint_sccs.scc(r.to_region_vid());
|
||||
let scc = self.constraint_sccs.scc(r);
|
||||
self.scc_values.placeholders_contained_in(scc)
|
||||
}
|
||||
|
||||
/// Returns access to the value of `r` for debugging purposes.
|
||||
pub(crate) fn region_universe(&self, r: RegionVid) -> ty::UniverseIndex {
|
||||
let scc = self.constraint_sccs.scc(r.to_region_vid());
|
||||
let scc = self.constraint_sccs.scc(r);
|
||||
self.scc_universes[scc]
|
||||
}
|
||||
|
||||
/// Once region solving has completed, this function will return
|
||||
/// the member constraints that were applied to the value of a given
|
||||
/// region `r`. See `AppliedMemberConstraint`.
|
||||
pub(crate) fn applied_member_constraints(
|
||||
&self,
|
||||
r: impl ToRegionVid,
|
||||
) -> &[AppliedMemberConstraint] {
|
||||
let scc = self.constraint_sccs.scc(r.to_region_vid());
|
||||
pub(crate) fn applied_member_constraints(&self, r: RegionVid) -> &[AppliedMemberConstraint] {
|
||||
let scc = self.constraint_sccs.scc(r);
|
||||
binary_search_util::binary_search_slice(
|
||||
&self.member_constraints_applied,
|
||||
|applied| applied.member_region_scc,
|
||||
@ -1133,7 +1130,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
let r_vid = self.to_region_vid(r);
|
||||
let r_scc = self.constraint_sccs.scc(r_vid);
|
||||
|
||||
// The challenge if this. We have some region variable `r`
|
||||
// The challenge is this. We have some region variable `r`
|
||||
// whose value is a set of CFG points and universal
|
||||
// regions. We want to find if that set is *equivalent* to
|
||||
// any of the named regions found in the closure.
|
||||
@ -2234,7 +2231,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
r: RegionVid,
|
||||
body: &Body<'_>,
|
||||
) -> Option<Location> {
|
||||
let scc = self.constraint_sccs.scc(r.to_region_vid());
|
||||
let scc = self.constraint_sccs.scc(r);
|
||||
let locations = self.scc_values.locations_outlived_by(scc);
|
||||
for location in locations {
|
||||
let bb = &body[location.block];
|
||||
|
@ -12,7 +12,6 @@ use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use crate::{
|
||||
constraints::OutlivesConstraint,
|
||||
nll::ToRegionVid,
|
||||
region_infer::TypeTest,
|
||||
type_check::{Locations, MirTypeckRegionConstraints},
|
||||
universal_regions::UniversalRegions,
|
||||
@ -198,7 +197,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||
|
||||
fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
|
||||
if let ty::RePlaceholder(placeholder) = *r {
|
||||
self.constraints.placeholder_region(self.infcx, placeholder).to_region_vid()
|
||||
self.constraints.placeholder_region(self.infcx, placeholder).as_var()
|
||||
} else {
|
||||
self.universal_regions.to_region_vid(r)
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ use crate::{
|
||||
constraints::OutlivesConstraintSet,
|
||||
facts::{AllFacts, AllFactsExt},
|
||||
location::LocationTable,
|
||||
nll::ToRegionVid,
|
||||
region_infer::values::RegionValueElements,
|
||||
universal_regions::UniversalRegions,
|
||||
};
|
||||
@ -80,9 +79,7 @@ fn compute_relevant_live_locals<'tcx>(
|
||||
) -> (Vec<Local>, Vec<Local>) {
|
||||
let (boring_locals, relevant_live_locals): (Vec<_>, Vec<_>) =
|
||||
body.local_decls.iter_enumerated().partition_map(|(local, local_decl)| {
|
||||
if tcx.all_free_regions_meet(&local_decl.ty, |r| {
|
||||
free_regions.contains(&r.to_region_vid())
|
||||
}) {
|
||||
if tcx.all_free_regions_meet(&local_decl.ty, |r| free_regions.contains(&r.as_var())) {
|
||||
Either::Left(local)
|
||||
} else {
|
||||
Either::Right(local)
|
||||
|
@ -56,7 +56,6 @@ use crate::{
|
||||
facts::AllFacts,
|
||||
location::LocationTable,
|
||||
member_constraints::MemberConstraintSet,
|
||||
nll::ToRegionVid,
|
||||
path_utils,
|
||||
region_infer::values::{
|
||||
LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
|
||||
@ -2419,7 +2418,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
if let Some(all_facts) = all_facts {
|
||||
let _prof_timer = self.infcx.tcx.prof.generic_activity("polonius_fact_generation");
|
||||
if let Some(borrow_index) = borrow_set.get_index_of(&location) {
|
||||
let region_vid = borrow_region.to_region_vid();
|
||||
let region_vid = borrow_region.as_var();
|
||||
all_facts.loan_issued_at.push((
|
||||
region_vid,
|
||||
borrow_index,
|
||||
@ -2465,8 +2464,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
match base_ty.kind() {
|
||||
ty::Ref(ref_region, _, mutbl) => {
|
||||
constraints.outlives_constraints.push(OutlivesConstraint {
|
||||
sup: ref_region.to_region_vid(),
|
||||
sub: borrow_region.to_region_vid(),
|
||||
sup: ref_region.as_var(),
|
||||
sub: borrow_region.as_var(),
|
||||
locations: location.to_locations(),
|
||||
span: location.to_locations().span(body),
|
||||
category,
|
||||
|
@ -131,13 +131,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
|
||||
ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(sym::env),
|
||||
};
|
||||
|
||||
let reg_var =
|
||||
reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg));
|
||||
|
||||
if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() {
|
||||
let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut();
|
||||
debug!(?reg_var);
|
||||
var_to_origin.insert(reg_var, RegionCtxt::Placeholder(reg_info));
|
||||
var_to_origin.insert(reg.as_var(), RegionCtxt::Placeholder(reg_info));
|
||||
}
|
||||
|
||||
reg
|
||||
@ -150,12 +146,9 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
|
||||
universe,
|
||||
);
|
||||
|
||||
let reg_var =
|
||||
reg.as_var().unwrap_or_else(|| bug!("expected region {:?} to be of kind ReVar", reg));
|
||||
|
||||
if cfg!(debug_assertions) && !self.type_checker.infcx.inside_canonicalization_ctxt() {
|
||||
let mut var_to_origin = self.type_checker.infcx.reg_var_to_origin.borrow_mut();
|
||||
var_to_origin.insert(reg_var, RegionCtxt::Existential(None));
|
||||
var_to_origin.insert(reg.as_var(), RegionCtxt::Existential(None));
|
||||
}
|
||||
|
||||
reg
|
||||
|
@ -28,7 +28,6 @@ use rustc_span::symbol::{kw, sym};
|
||||
use rustc_span::Symbol;
|
||||
use std::iter;
|
||||
|
||||
use crate::nll::ToRegionVid;
|
||||
use crate::renumber::{BoundRegionInfo, RegionCtxt};
|
||||
use crate::BorrowckInferCtxt;
|
||||
|
||||
@ -406,7 +405,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
|
||||
// Create the "global" region that is always free in all contexts: 'static.
|
||||
let fr_static =
|
||||
self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(kw::Static)).to_region_vid();
|
||||
self.infcx.next_nll_region_var(FR, || RegionCtxt::Free(kw::Static)).as_var();
|
||||
|
||||
// We've now added all the global regions. The next ones we
|
||||
// add will be external.
|
||||
@ -446,7 +445,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
};
|
||||
|
||||
debug!(?region_vid);
|
||||
indices.insert_late_bound_region(r, region_vid.to_region_vid());
|
||||
indices.insert_late_bound_region(r, region_vid.as_var());
|
||||
}
|
||||
},
|
||||
);
|
||||
@ -480,7 +479,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
};
|
||||
|
||||
debug!(?region_vid);
|
||||
indices.insert_late_bound_region(r, region_vid.to_region_vid());
|
||||
indices.insert_late_bound_region(r, region_vid.as_var());
|
||||
}
|
||||
});
|
||||
|
||||
@ -499,7 +498,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
let reg_vid = self
|
||||
.infcx
|
||||
.next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("c-variadic")))
|
||||
.to_region_vid();
|
||||
.as_var();
|
||||
|
||||
let region = self.infcx.tcx.mk_re_var(reg_vid);
|
||||
let va_list_ty =
|
||||
@ -514,7 +513,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
let fr_fn_body = self
|
||||
.infcx
|
||||
.next_nll_region_var(FR, || RegionCtxt::Free(Symbol::intern("fn_body")))
|
||||
.to_region_vid();
|
||||
.as_var();
|
||||
|
||||
let num_universals = self.infcx.num_region_vars();
|
||||
|
||||
@ -635,7 +634,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
|
||||
|
||||
let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
|
||||
let subst_mapping =
|
||||
iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.to_region_vid()));
|
||||
iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.as_var()));
|
||||
|
||||
UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static }
|
||||
}
|
||||
@ -789,7 +788,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
|
||||
self.next_nll_region_var(origin, || RegionCtxt::Bound(BoundRegionInfo::Name(name)))
|
||||
};
|
||||
|
||||
indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid());
|
||||
indices.insert_late_bound_region(liberated_region, region_vid.as_var());
|
||||
debug!(?liberated_region, ?region_vid);
|
||||
region_vid
|
||||
});
|
||||
@ -822,7 +821,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
|
||||
};
|
||||
|
||||
debug!(?region_vid);
|
||||
indices.insert_late_bound_region(r, region_vid.to_region_vid());
|
||||
indices.insert_late_bound_region(r, region_vid.as_var());
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -843,7 +842,7 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> {
|
||||
})
|
||||
};
|
||||
|
||||
indices.insert_late_bound_region(r, region_vid.to_region_vid());
|
||||
indices.insert_late_bound_region(r, region_vid.as_var());
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -861,7 +860,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
|
||||
}
|
||||
|
||||
/// Converts `r` into a local inference variable: `r` can either
|
||||
/// by a `ReVar` (i.e., already a reference to an inference
|
||||
/// be a `ReVar` (i.e., already a reference to an inference
|
||||
/// variable) or it can be `'static` or some early-bound
|
||||
/// region. This is useful when taking the results from
|
||||
/// type-checking and trait-matching, which may sometimes
|
||||
@ -870,7 +869,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
|
||||
/// fully initialized.
|
||||
pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid {
|
||||
if let ty::ReVar(..) = *r {
|
||||
r.to_region_vid()
|
||||
r.as_var()
|
||||
} else if r.is_error() {
|
||||
// We use the `'static` `RegionVid` because `ReError` doesn't actually exist in the
|
||||
// `UniversalRegionIndices`. This is fine because 1) it is a fallback only used if
|
||||
|
@ -5,7 +5,6 @@
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(is_terminal)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(decl_macro)]
|
||||
#![recursion_limit = "256"]
|
||||
|
@ -6,7 +6,6 @@
|
||||
#![feature(array_windows)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(is_terminal)]
|
||||
#![feature(adt_const_params)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
|
@ -2520,24 +2520,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
tcx,
|
||||
infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id),
|
||||
);
|
||||
// I guess we don't need to make a universe unless we need it,
|
||||
// but also we're on the error path, so it doesn't matter here.
|
||||
let universe = infcx.create_next_universe();
|
||||
let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased);
|
||||
// FIXME: Don't bother dealing with non-lifetime binders here...
|
||||
if value.has_escaping_bound_vars() {
|
||||
return false;
|
||||
}
|
||||
infcx
|
||||
.can_eq(
|
||||
ty::ParamEnv::empty(),
|
||||
impl_.self_ty(),
|
||||
tcx.replace_escaping_bound_vars_uncached(qself_ty, ty::fold::FnMutDelegate {
|
||||
regions: &mut |_| tcx.lifetimes.re_erased,
|
||||
types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType {
|
||||
universe,
|
||||
bound: bv,
|
||||
}),
|
||||
consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst {
|
||||
universe,
|
||||
bound: bv,
|
||||
}, ty),
|
||||
})
|
||||
value,
|
||||
)
|
||||
})
|
||||
&& tcx.impl_polarity(impl_def_id) != ty::ImplPolarity::Negative
|
||||
|
@ -452,11 +452,8 @@ fn check_opaque_meets_bounds<'tcx>(
|
||||
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
|
||||
// Can have different predicates to their defining use
|
||||
hir::OpaqueTyOrigin::TyAlias => {
|
||||
let outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(
|
||||
defining_use_anchor,
|
||||
&outlives_environment,
|
||||
);
|
||||
let outlives_env = OutlivesEnvironment::new(param_env);
|
||||
let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);
|
||||
}
|
||||
}
|
||||
// Clean up after ourselves
|
||||
|
@ -332,10 +332,6 @@ fn compare_method_predicate_entailment<'tcx>(
|
||||
param_env,
|
||||
infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys.clone()),
|
||||
);
|
||||
infcx.process_registered_region_obligations(
|
||||
outlives_env.region_bound_pairs(),
|
||||
outlives_env.param_env,
|
||||
);
|
||||
let errors = infcx.resolve_regions(&outlives_env);
|
||||
if !errors.is_empty() {
|
||||
// FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT
|
||||
@ -722,18 +718,18 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
|
||||
return Err(reported);
|
||||
}
|
||||
|
||||
let collected_types = collector.types;
|
||||
|
||||
// Finally, resolve all regions. This catches wily misuses of
|
||||
// lifetime parameters.
|
||||
let outlives_environment = OutlivesEnvironment::with_bounds(
|
||||
let outlives_env = OutlivesEnvironment::with_bounds(
|
||||
param_env,
|
||||
infcx.implied_bounds_tys(param_env, impl_m_def_id, wf_tys),
|
||||
);
|
||||
infcx
|
||||
.err_ctxt()
|
||||
.check_region_obligations_and_report_errors(impl_m_def_id, &outlives_environment)?;
|
||||
ocx.resolve_regions_and_report_errors(impl_m_def_id, &outlives_env)?;
|
||||
|
||||
let mut collected_tys = FxHashMap::default();
|
||||
for (def_id, (ty, substs)) in collector.types {
|
||||
for (def_id, (ty, substs)) in collected_types {
|
||||
match infcx.fully_resolve(ty) {
|
||||
Ok(ty) => {
|
||||
// `ty` contains free regions that we created earlier while liberating the
|
||||
@ -1742,11 +1738,8 @@ pub(super) fn compare_impl_const_raw(
|
||||
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors));
|
||||
}
|
||||
|
||||
let outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
infcx
|
||||
.err_ctxt()
|
||||
.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?;
|
||||
Ok(())
|
||||
let outlives_env = OutlivesEnvironment::new(param_env);
|
||||
ocx.resolve_regions_and_report_errors(impl_const_item_def, &outlives_env)
|
||||
}
|
||||
|
||||
pub(super) fn compare_impl_ty<'tcx>(
|
||||
@ -1845,13 +1838,8 @@ fn compare_type_predicate_entailment<'tcx>(
|
||||
|
||||
// Finally, resolve all regions. This catches wily misuses of
|
||||
// lifetime parameters.
|
||||
let outlives_environment = OutlivesEnvironment::new(param_env);
|
||||
infcx.err_ctxt().check_region_obligations_and_report_errors(
|
||||
impl_ty.def_id.expect_local(),
|
||||
&outlives_environment,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
let outlives_env = OutlivesEnvironment::new(param_env);
|
||||
ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
|
||||
}
|
||||
|
||||
/// Validate that `ProjectionCandidate`s created for this associated type will
|
||||
@ -2063,14 +2051,8 @@ pub(super) fn check_type_bounds<'tcx>(
|
||||
// Finally, resolve all regions. This catches wily misuses of
|
||||
// lifetime parameters.
|
||||
let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_def_id, assumed_wf_types);
|
||||
let outlives_environment = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||
|
||||
infcx.err_ctxt().check_region_obligations_and_report_errors(
|
||||
impl_ty.def_id.expect_local(),
|
||||
&outlives_environment,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||
ocx.resolve_regions_and_report_errors(impl_ty_def_id, &outlives_env)
|
||||
}
|
||||
|
||||
fn assoc_item_kind_str(impl_item: &ty::AssocItem) -> &'static str {
|
||||
|
@ -114,11 +114,9 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
||||
return;
|
||||
}
|
||||
|
||||
let outlives_environment = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||
|
||||
let _ = infcx
|
||||
.err_ctxt()
|
||||
.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
|
||||
let _ = wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env);
|
||||
}
|
||||
|
||||
fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) {
|
||||
@ -680,12 +678,7 @@ fn resolve_regions_with_wf_tys<'tcx>(
|
||||
|
||||
add_constraints(&infcx, region_bound_pairs);
|
||||
|
||||
infcx.process_registered_region_obligations(
|
||||
outlives_environment.region_bound_pairs(),
|
||||
param_env,
|
||||
);
|
||||
let errors = infcx.resolve_regions(&outlives_environment);
|
||||
|
||||
debug!(?errors, "errors");
|
||||
|
||||
// If we were able to prove that the type outlives the region without
|
||||
|
@ -354,9 +354,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
|
||||
|
||||
// Finally, resolve all regions.
|
||||
let outlives_env = OutlivesEnvironment::new(param_env);
|
||||
let _ = infcx
|
||||
.err_ctxt()
|
||||
.check_region_obligations_and_report_errors(impl_did, &outlives_env);
|
||||
let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -592,7 +590,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
|
||||
|
||||
// Finally, resolve all regions.
|
||||
let outlives_env = OutlivesEnvironment::new(param_env);
|
||||
let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(impl_did, &outlives_env);
|
||||
let _ = ocx.resolve_regions_and_report_errors(impl_did, &outlives_env);
|
||||
|
||||
CoerceUnsizedInfo { custom_kind: kind }
|
||||
}
|
||||
|
@ -8,10 +8,7 @@ use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::ty::print::with_forced_trimmed_paths;
|
||||
use rustc_middle::ty::subst::InternalSubsts;
|
||||
use rustc_middle::ty::util::IntTypeExt;
|
||||
use rustc_middle::ty::{
|
||||
self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitableExt,
|
||||
};
|
||||
use rustc_middle::ty::{self, ImplTraitInTraitData, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
@ -874,28 +871,6 @@ fn infer_placeholder_type<'a>(
|
||||
item_ident: Ident,
|
||||
kind: &'static str,
|
||||
) -> Ty<'a> {
|
||||
// Attempts to make the type nameable by turning FnDefs into FnPtrs.
|
||||
struct MakeNameable<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MakeNameable<'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let ty = match *ty.kind() {
|
||||
ty::FnDef(def_id, substs) => {
|
||||
self.tcx.mk_fn_ptr(self.tcx.fn_sig(def_id).subst(self.tcx, substs))
|
||||
}
|
||||
_ => ty,
|
||||
};
|
||||
|
||||
ty.super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
let ty = tcx.diagnostic_only_typeck(def_id).node_type(body_id.hir_id);
|
||||
|
||||
// If this came from a free `const` or `static mut?` item,
|
||||
|
@ -180,8 +180,7 @@ fn get_impl_substs(
|
||||
|
||||
let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
|
||||
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||
let _ =
|
||||
infcx.err_ctxt().check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
|
||||
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
|
||||
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
|
||||
let span = tcx.def_span(impl1_def_id);
|
||||
tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
|
||||
|
@ -12,9 +12,7 @@ use rustc_middle::ty::adjustment::{
|
||||
Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability,
|
||||
};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{
|
||||
self, IsSuggestable, Ty, TyCtxt, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_session::errors::ExprParenthesesNeeded;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{sym, Ident};
|
||||
@ -965,21 +963,3 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TypeParamEraser<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, Span);
|
||||
|
||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TypeParamEraser<'_, 'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.0.tcx
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
match ty.kind() {
|
||||
ty::Param(_) => self.0.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::MiscVariable,
|
||||
span: self.1,
|
||||
}),
|
||||
_ => ty.super_fold_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ use rustc_middle::ty::{
|
||||
self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
|
||||
TypeVisitable, TypeVisitableExt,
|
||||
};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
|
||||
use rustc_target::spec::abi;
|
||||
use std::ops::{ControlFlow, Deref};
|
||||
@ -113,7 +114,11 @@ fn escape_literal(s: &str) -> String {
|
||||
|
||||
/// A helper for building type related errors. The `typeck_results`
|
||||
/// field is only populated during an in-progress typeck.
|
||||
/// Get an instance by calling `InferCtxt::err` or `FnCtxt::infer_err`.
|
||||
/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
|
||||
///
|
||||
/// You must only create this if you intend to actually emit an error.
|
||||
/// This provides a lot of utility methods which should not be used
|
||||
/// during the happy path.
|
||||
pub struct TypeErrCtxt<'a, 'tcx> {
|
||||
pub infcx: &'a InferCtxt<'tcx>,
|
||||
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
|
||||
@ -125,6 +130,19 @@ pub struct TypeErrCtxt<'a, 'tcx> {
|
||||
Box<dyn Fn(Ty<'tcx>) -> Vec<(Ty<'tcx>, Vec<PredicateObligation<'tcx>>)> + 'a>,
|
||||
}
|
||||
|
||||
impl Drop for TypeErrCtxt<'_, '_> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(_) = self.infcx.tcx.sess.has_errors_or_delayed_span_bugs() {
|
||||
// ok, emitted an error.
|
||||
} else {
|
||||
self.infcx
|
||||
.tcx
|
||||
.sess
|
||||
.delay_span_bug(DUMMY_SP, "used a `TypeErrCtxt` without failing compilation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeErrCtxt<'_, '_> {
|
||||
/// This is just to avoid a potential footgun of accidentally
|
||||
/// dropping `typeck_results` by calling `InferCtxt::err_ctxt`
|
||||
@ -409,7 +427,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
errors: &[RegionResolutionError<'tcx>],
|
||||
) {
|
||||
) -> ErrorGuaranteed {
|
||||
if let Some(guaranteed) = self.infcx.tainted_by_errors() {
|
||||
return guaranteed;
|
||||
}
|
||||
|
||||
debug!("report_region_errors(): {} errors to start", errors.len());
|
||||
|
||||
// try to pre-process the errors, which will group some of them
|
||||
@ -489,6 +511,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.tcx
|
||||
.sess
|
||||
.delay_span_bug(self.tcx.def_span(generic_param_scope), "expected region errors")
|
||||
}
|
||||
|
||||
// This method goes through all the errors and try to group certain types
|
||||
|
@ -45,8 +45,7 @@ use self::combine::CombineFields;
|
||||
use self::error_reporting::TypeErrCtxt;
|
||||
use self::free_regions::RegionRelations;
|
||||
use self::lexical_region_resolve::LexicalRegionResolutions;
|
||||
use self::outlives::env::OutlivesEnvironment;
|
||||
use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound};
|
||||
use self::region_constraints::{GenericKind, VarInfos, VerifyBound};
|
||||
use self::region_constraints::{
|
||||
RegionConstraintCollector, RegionConstraintStorage, RegionSnapshot,
|
||||
};
|
||||
@ -1213,95 +1212,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
self.tainted_by_errors.set(Some(e));
|
||||
}
|
||||
|
||||
pub fn skip_region_resolution(&self) {
|
||||
let (var_infos, _) = {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let inner = &mut *inner;
|
||||
// Note: `inner.region_obligations` may not be empty, because we
|
||||
// didn't necessarily call `process_registered_region_obligations`.
|
||||
// This is okay, because that doesn't introduce new vars.
|
||||
inner
|
||||
.region_constraint_storage
|
||||
.take()
|
||||
.expect("regions already resolved")
|
||||
.with_log(&mut inner.undo_log)
|
||||
.into_infos_and_data()
|
||||
};
|
||||
|
||||
let lexical_region_resolutions = LexicalRegionResolutions {
|
||||
values: rustc_index::vec::IndexVec::from_elem_n(
|
||||
crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
|
||||
var_infos.len(),
|
||||
),
|
||||
};
|
||||
|
||||
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
|
||||
assert!(old_value.is_none());
|
||||
}
|
||||
|
||||
/// Process the region constraints and return any errors that
|
||||
/// result. After this, no more unification operations should be
|
||||
/// done -- or the compiler will panic -- but it is legal to use
|
||||
/// `resolve_vars_if_possible` as well as `fully_resolve`.
|
||||
pub fn resolve_regions(
|
||||
&self,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
) -> Vec<RegionResolutionError<'tcx>> {
|
||||
let (var_infos, data) = {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let inner = &mut *inner;
|
||||
assert!(
|
||||
self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
|
||||
"region_obligations not empty: {:#?}",
|
||||
inner.region_obligations
|
||||
);
|
||||
inner
|
||||
.region_constraint_storage
|
||||
.take()
|
||||
.expect("regions already resolved")
|
||||
.with_log(&mut inner.undo_log)
|
||||
.into_infos_and_data()
|
||||
};
|
||||
|
||||
let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
|
||||
|
||||
let (lexical_region_resolutions, errors) =
|
||||
lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data);
|
||||
|
||||
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
|
||||
assert!(old_value.is_none());
|
||||
|
||||
errors
|
||||
}
|
||||
/// Obtains (and clears) the current set of region
|
||||
/// constraints. The inference context is still usable: further
|
||||
/// unifications will simply add new constraints.
|
||||
///
|
||||
/// This method is not meant to be used with normal lexical region
|
||||
/// resolution. Rather, it is used in the NLL mode as a kind of
|
||||
/// interim hack: basically we run normal type-check and generate
|
||||
/// region constraints as normal, but then we take them and
|
||||
/// translate them into the form that the NLL solver
|
||||
/// understands. See the NLL module for mode details.
|
||||
pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
|
||||
assert!(
|
||||
self.inner.borrow().region_obligations.is_empty(),
|
||||
"region_obligations not empty: {:#?}",
|
||||
self.inner.borrow().region_obligations
|
||||
);
|
||||
|
||||
self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
|
||||
}
|
||||
|
||||
/// Gives temporary access to the region constraint data.
|
||||
pub fn with_region_constraints<R>(
|
||||
&self,
|
||||
op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
|
||||
) -> R {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
op(inner.unwrap_region_constraints().data())
|
||||
}
|
||||
|
||||
pub fn region_var_origin(&self, vid: ty::RegionVid) -> RegionVariableOrigin {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let inner = &mut *inner;
|
||||
@ -1754,56 +1664,6 @@ impl<'cx, 'tcx> Drop for CanonicalizationCtxtGuard<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
/// Processes registered region obliations and resolves regions, reporting
|
||||
/// any errors if any were raised. Prefer using this function over manually
|
||||
/// calling `resolve_regions_and_report_errors`.
|
||||
pub fn check_region_obligations_and_report_errors(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
self.process_registered_region_obligations(
|
||||
outlives_env.region_bound_pairs(),
|
||||
outlives_env.param_env,
|
||||
);
|
||||
|
||||
self.resolve_regions_and_report_errors(generic_param_scope, outlives_env)
|
||||
}
|
||||
|
||||
/// Process the region constraints and report any errors that
|
||||
/// result. After this, no more unification operations should be
|
||||
/// done -- or the compiler will panic -- but it is legal to use
|
||||
/// `resolve_vars_if_possible` as well as `fully_resolve`.
|
||||
///
|
||||
/// Make sure to call [`InferCtxt::process_registered_region_obligations`]
|
||||
/// first, or preferably use [`TypeErrCtxt::check_region_obligations_and_report_errors`]
|
||||
/// to do both of these operations together.
|
||||
pub fn resolve_regions_and_report_errors(
|
||||
&self,
|
||||
generic_param_scope: LocalDefId,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let errors = self.resolve_regions(outlives_env);
|
||||
|
||||
if let None = self.tainted_by_errors() {
|
||||
// As a heuristic, just skip reporting region errors
|
||||
// altogether if other errors have been reported while
|
||||
// this infcx was in use. This is totally hokey but
|
||||
// otherwise we have a hard time separating legit region
|
||||
// errors from silly ones.
|
||||
self.report_region_errors(generic_param_scope, &errors);
|
||||
}
|
||||
|
||||
if errors.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(self
|
||||
.tcx
|
||||
.sess
|
||||
.delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted"))
|
||||
}
|
||||
}
|
||||
|
||||
// [Note-Type-error-reporting]
|
||||
// An invariant is that anytime the expected or actual type is Error (the special
|
||||
// error type, meaning that an error occurred when typechecking this expression),
|
||||
|
@ -1,4 +1,11 @@
|
||||
//! Various code related to computing outlives relations.
|
||||
use self::env::OutlivesEnvironment;
|
||||
use super::region_constraints::RegionConstraintData;
|
||||
use super::{InferCtxt, RegionResolutionError};
|
||||
use crate::infer::free_regions::RegionRelations;
|
||||
use crate::infer::lexical_region_resolve::{self, LexicalRegionResolutions};
|
||||
use rustc_middle::traits::query::OutlivesBound;
|
||||
use rustc_middle::ty;
|
||||
|
||||
pub mod components;
|
||||
pub mod env;
|
||||
@ -6,9 +13,6 @@ pub mod obligations;
|
||||
pub mod test_type_match;
|
||||
pub mod verify;
|
||||
|
||||
use rustc_middle::traits::query::OutlivesBound;
|
||||
use rustc_middle::ty;
|
||||
|
||||
#[instrument(level = "debug", skip(param_env), ret)]
|
||||
pub fn explicit_outlives_bounds<'tcx>(
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
@ -39,3 +43,98 @@ pub fn explicit_outlives_bounds<'tcx>(
|
||||
))) => Some(OutlivesBound::RegionSubRegion(r_b, r_a)),
|
||||
})
|
||||
}
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn skip_region_resolution(&self) {
|
||||
let (var_infos, _) = {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let inner = &mut *inner;
|
||||
// Note: `inner.region_obligations` may not be empty, because we
|
||||
// didn't necessarily call `process_registered_region_obligations`.
|
||||
// This is okay, because that doesn't introduce new vars.
|
||||
inner
|
||||
.region_constraint_storage
|
||||
.take()
|
||||
.expect("regions already resolved")
|
||||
.with_log(&mut inner.undo_log)
|
||||
.into_infos_and_data()
|
||||
};
|
||||
|
||||
let lexical_region_resolutions = LexicalRegionResolutions {
|
||||
values: rustc_index::vec::IndexVec::from_elem_n(
|
||||
crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
|
||||
var_infos.len(),
|
||||
),
|
||||
};
|
||||
|
||||
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
|
||||
assert!(old_value.is_none());
|
||||
}
|
||||
|
||||
/// Process the region constraints and return any errors that
|
||||
/// result. After this, no more unification operations should be
|
||||
/// done -- or the compiler will panic -- but it is legal to use
|
||||
/// `resolve_vars_if_possible` as well as `fully_resolve`.
|
||||
#[must_use]
|
||||
pub fn resolve_regions(
|
||||
&self,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
) -> Vec<RegionResolutionError<'tcx>> {
|
||||
self.process_registered_region_obligations(outlives_env);
|
||||
|
||||
let (var_infos, data) = {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
let inner = &mut *inner;
|
||||
assert!(
|
||||
self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
|
||||
"region_obligations not empty: {:#?}",
|
||||
inner.region_obligations
|
||||
);
|
||||
inner
|
||||
.region_constraint_storage
|
||||
.take()
|
||||
.expect("regions already resolved")
|
||||
.with_log(&mut inner.undo_log)
|
||||
.into_infos_and_data()
|
||||
};
|
||||
|
||||
let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
|
||||
|
||||
let (lexical_region_resolutions, errors) =
|
||||
lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data);
|
||||
|
||||
let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
|
||||
assert!(old_value.is_none());
|
||||
|
||||
errors
|
||||
}
|
||||
|
||||
/// Obtains (and clears) the current set of region
|
||||
/// constraints. The inference context is still usable: further
|
||||
/// unifications will simply add new constraints.
|
||||
///
|
||||
/// This method is not meant to be used with normal lexical region
|
||||
/// resolution. Rather, it is used in the NLL mode as a kind of
|
||||
/// interim hack: basically we run normal type-check and generate
|
||||
/// region constraints as normal, but then we take them and
|
||||
/// translate them into the form that the NLL solver
|
||||
/// understands. See the NLL module for mode details.
|
||||
pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
|
||||
assert!(
|
||||
self.inner.borrow().region_obligations.is_empty(),
|
||||
"region_obligations not empty: {:#?}",
|
||||
self.inner.borrow().region_obligations
|
||||
);
|
||||
|
||||
self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
|
||||
}
|
||||
|
||||
/// Gives temporary access to the region constraint data.
|
||||
pub fn with_region_constraints<R>(
|
||||
&self,
|
||||
op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
|
||||
) -> R {
|
||||
let mut inner = self.inner.borrow_mut();
|
||||
op(inner.unwrap_region_constraints().data())
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,8 @@ use rustc_middle::ty::subst::GenericArgKind;
|
||||
use rustc_middle::ty::{self, Region, SubstsRef, Ty, TyCtxt, TypeVisitableExt};
|
||||
use smallvec::smallvec;
|
||||
|
||||
use super::env::OutlivesEnvironment;
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
/// Registers that the given region obligation must be resolved
|
||||
/// from within the scope of `body_id`. These regions are enqueued
|
||||
@ -112,39 +114,17 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
std::mem::take(&mut self.inner.borrow_mut().region_obligations)
|
||||
}
|
||||
|
||||
/// NOTE: Prefer using `TypeErrCtxt::check_region_obligations_and_report_errors`
|
||||
/// instead of calling this directly.
|
||||
///
|
||||
/// Process the region obligations that must be proven (during
|
||||
/// `regionck`) for the given `body_id`, given information about
|
||||
/// the region bounds in scope and so forth. This function must be
|
||||
/// invoked for all relevant body-ids before region inference is
|
||||
/// done (or else an assert will fire).
|
||||
/// the region bounds in scope and so forth.
|
||||
///
|
||||
/// See the `region_obligations` field of `InferCtxt` for some
|
||||
/// comments about how this function fits into the overall expected
|
||||
/// flow of the inferencer. The key point is that it is
|
||||
/// invoked after all type-inference variables have been bound --
|
||||
/// towards the end of regionck. This also ensures that the
|
||||
/// region-bound-pairs are available (see comments above regarding
|
||||
/// closures).
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `region_bound_pairs_map`: the set of region bounds implied by
|
||||
/// the parameters and where-clauses. In particular, each pair
|
||||
/// `('a, K)` in this list tells us that the bounds in scope
|
||||
/// indicate that `K: 'a`, where `K` is either a generic
|
||||
/// parameter like `T` or a projection like `T::Item`.
|
||||
/// - `param_env` is the parameter environment for the enclosing function.
|
||||
/// - `body_id` is the body-id whose region obligations are being
|
||||
/// processed.
|
||||
#[instrument(level = "debug", skip(self, region_bound_pairs))]
|
||||
pub fn process_registered_region_obligations(
|
||||
&self,
|
||||
region_bound_pairs: &RegionBoundPairs<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
) {
|
||||
/// right before lexical region resolution.
|
||||
#[instrument(level = "debug", skip(self, outlives_env))]
|
||||
pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) {
|
||||
assert!(
|
||||
!self.in_snapshot.get(),
|
||||
"cannot process registered region obligations in a snapshot"
|
||||
@ -153,15 +133,16 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
let my_region_obligations = self.take_registered_region_obligations();
|
||||
|
||||
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
|
||||
debug!(
|
||||
"process_registered_region_obligations: sup_type={:?} sub_region={:?} origin={:?}",
|
||||
sup_type, sub_region, origin
|
||||
);
|
||||
|
||||
debug!(?sup_type, ?sub_region, ?origin);
|
||||
let sup_type = self.resolve_vars_if_possible(sup_type);
|
||||
|
||||
let outlives =
|
||||
&mut TypeOutlives::new(self, self.tcx, ®ion_bound_pairs, None, param_env);
|
||||
let outlives = &mut TypeOutlives::new(
|
||||
self,
|
||||
self.tcx,
|
||||
&outlives_env.region_bound_pairs(),
|
||||
None,
|
||||
outlives_env.param_env,
|
||||
);
|
||||
let category = origin.to_constraint_category();
|
||||
outlives.type_must_outlive(origin, sup_type, sub_region, category);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ pub trait TraitEngine<'tcx>: 'tcx {
|
||||
obligation: PredicateObligation<'tcx>,
|
||||
);
|
||||
|
||||
#[must_use]
|
||||
fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
|
||||
|
||||
fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
|
||||
@ -58,6 +59,7 @@ pub trait TraitEngineExt<'tcx> {
|
||||
obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>,
|
||||
);
|
||||
|
||||
#[must_use]
|
||||
fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>;
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,6 @@
|
||||
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![feature(is_terminal)]
|
||||
|
||||
use std::env::{self, VarError};
|
||||
use std::fmt::{self, Display};
|
||||
|
@ -7,8 +7,8 @@ use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
|
||||
use crate::ty::visit::ValidateBoundVars;
|
||||
use crate::ty::InferTy::*;
|
||||
use crate::ty::{
|
||||
self, AdtDef, Discr, FallibleTypeFolder, Term, Ty, TyCtxt, TypeFlags, TypeFoldable,
|
||||
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
|
||||
self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
|
||||
TypeVisitableExt, TypeVisitor,
|
||||
};
|
||||
use crate::ty::{List, ParamEnv};
|
||||
use hir::def::DefKind;
|
||||
@ -1156,81 +1156,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
struct SkipBindersAt<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
index: ty::DebruijnIndex,
|
||||
}
|
||||
|
||||
impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for SkipBindersAt<'tcx> {
|
||||
type Error = ();
|
||||
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn try_fold_binder<T>(&mut self, t: Binder<'tcx, T>) -> Result<Binder<'tcx, T>, Self::Error>
|
||||
where
|
||||
T: ty::TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
self.index.shift_in(1);
|
||||
let value = t.try_map_bound(|t| t.try_fold_with(self));
|
||||
self.index.shift_out(1);
|
||||
value
|
||||
}
|
||||
|
||||
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
||||
if !ty.has_escaping_bound_vars() {
|
||||
Ok(ty)
|
||||
} else if let ty::Bound(index, bv) = *ty.kind() {
|
||||
if index == self.index {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(self.interner().mk_bound(index.shifted_out(1), bv))
|
||||
}
|
||||
} else {
|
||||
ty.try_super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result<ty::Region<'tcx>, Self::Error> {
|
||||
if !r.has_escaping_bound_vars() {
|
||||
Ok(r)
|
||||
} else if let ty::ReLateBound(index, bv) = r.kind() {
|
||||
if index == self.index {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(self.interner().mk_re_late_bound(index.shifted_out(1), bv))
|
||||
}
|
||||
} else {
|
||||
r.try_super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
|
||||
if !ct.has_escaping_bound_vars() {
|
||||
Ok(ct)
|
||||
} else if let ty::ConstKind::Bound(index, bv) = ct.kind() {
|
||||
if index == self.index {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(self.interner().mk_const(
|
||||
ty::ConstKind::Bound(index.shifted_out(1), bv),
|
||||
ct.ty().try_fold_with(self)?,
|
||||
))
|
||||
}
|
||||
} else {
|
||||
ct.try_super_fold_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn try_fold_predicate(
|
||||
&mut self,
|
||||
p: ty::Predicate<'tcx>,
|
||||
) -> Result<ty::Predicate<'tcx>, Self::Error> {
|
||||
if !p.has_escaping_bound_vars() { Ok(p) } else { p.try_super_fold_with(self) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the projection of an associated type.
|
||||
///
|
||||
/// For a projection, this would be `<Ty as Trait<...>>::N`.
|
||||
@ -1772,10 +1697,10 @@ impl<'tcx> Region<'tcx> {
|
||||
matches!(self.kind(), ty::ReVar(_))
|
||||
}
|
||||
|
||||
pub fn as_var(self) -> Option<RegionVid> {
|
||||
pub fn as_var(self) -> RegionVid {
|
||||
match self.kind() {
|
||||
ty::ReVar(vid) => Some(vid),
|
||||
_ => None,
|
||||
ty::ReVar(vid) => vid,
|
||||
_ => bug!("expected region {:?} to be of kind ReVar", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ use crate::infer::InferCtxt;
|
||||
use crate::traits::project::ProjectAndUnifyResult;
|
||||
use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::visit::TypeVisitableExt;
|
||||
use rustc_middle::ty::{ImplPolarity, Region, RegionVid};
|
||||
|
||||
@ -187,7 +186,8 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
panic!("Unable to fulfill trait {:?} for '{:?}': {:?}", trait_did, ty, errors);
|
||||
}
|
||||
|
||||
infcx.process_registered_region_obligations(&Default::default(), full_env);
|
||||
let outlives_env = OutlivesEnvironment::new(full_env);
|
||||
infcx.process_registered_region_obligations(&outlives_env);
|
||||
|
||||
let region_data =
|
||||
infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone();
|
||||
@ -851,23 +851,3 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
infcx.freshen(p)
|
||||
}
|
||||
}
|
||||
|
||||
/// Replaces all ReVars in a type with ty::Region's, using the provided map
|
||||
pub struct RegionReplacer<'a, 'tcx> {
|
||||
vid_to_region: &'a FxHashMap<ty::RegionVid, ty::Region<'tcx>>,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for RegionReplacer<'a, 'tcx> {
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
|
||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
||||
(match *r {
|
||||
ty::ReVar(vid) => self.vid_to_region.get(&vid).cloned(),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| r.super_fold_with(self))
|
||||
}
|
||||
}
|
||||
|
@ -405,9 +405,6 @@ fn resolve_negative_obligation<'tcx>(
|
||||
param_env,
|
||||
infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),
|
||||
);
|
||||
|
||||
infcx.process_registered_region_obligations(outlives_env.region_bound_pairs(), param_env);
|
||||
|
||||
infcx.resolve_regions(&outlives_env).is_empty()
|
||||
}
|
||||
|
||||
|
@ -6,11 +6,13 @@ use super::{ChalkFulfillmentContext, FulfillmentContext};
|
||||
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
|
||||
use crate::traits::NormalizeExt;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_infer::infer::at::ToTrace;
|
||||
use rustc_infer::infer::canonical::{
|
||||
Canonical, CanonicalQueryResponse, CanonicalVarValues, QueryResponse,
|
||||
};
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk};
|
||||
use rustc_infer::traits::query::Fallible;
|
||||
use rustc_infer::traits::{
|
||||
@ -173,14 +175,33 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
|
||||
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn select_where_possible(&self) -> Vec<FulfillmentError<'tcx>> {
|
||||
self.engine.borrow_mut().select_where_possible(self.infcx)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> {
|
||||
self.engine.borrow_mut().select_all_or_error(self.infcx)
|
||||
}
|
||||
|
||||
/// Resolves regions and reports errors.
|
||||
///
|
||||
/// Takes ownership of the context as doing trait solving afterwards
|
||||
/// will result in region constraints getting ignored.
|
||||
pub fn resolve_regions_and_report_errors(
|
||||
self,
|
||||
generic_param_scope: LocalDefId,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let errors = self.infcx.resolve_regions(&outlives_env);
|
||||
if errors.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(self.infcx.err_ctxt().report_region_errors(generic_param_scope, &errors))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assumed_wf_types(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
@ -1776,7 +1776,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
|
||||
// constrain inference variables a bit more to nested obligations from normalize so
|
||||
// we can have more helpful errors.
|
||||
ocx.select_where_possible();
|
||||
//
|
||||
// we intentionally drop errors from normalization here,
|
||||
// since the normalization is just done to improve the error message.
|
||||
let _ = ocx.select_where_possible();
|
||||
|
||||
if let Err(new_err) = ocx.eq_exp(
|
||||
&obligation.cause,
|
||||
|
@ -117,10 +117,6 @@ pub fn type_allowed_to_implement_copy<'tcx>(
|
||||
FxIndexSet::from_iter([self_type]),
|
||||
),
|
||||
);
|
||||
infcx.process_registered_region_obligations(
|
||||
outlives_env.region_bound_pairs(),
|
||||
param_env,
|
||||
);
|
||||
let errors = infcx.resolve_regions(&outlives_env);
|
||||
if !errors.is_empty() {
|
||||
infringing.push((field, ty, InfringingFieldsReason::Regions(errors)));
|
||||
|
@ -3183,7 +3183,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMut<'a, K, V, A> {
|
||||
panic!("key must be ordered above the current element");
|
||||
}
|
||||
}
|
||||
if let Some((next, _)) = self.peek_prev() {
|
||||
if let Some((next, _)) = self.peek_next() {
|
||||
if &key >= next {
|
||||
panic!("key must be ordered below the next element");
|
||||
}
|
||||
|
@ -2385,3 +2385,67 @@ fn test_cursor_mut() {
|
||||
assert_eq!(cur.key(), Some(&4));
|
||||
assert_eq!(map, BTreeMap::from([(0, '?'), (1, 'a'), (3, 'c'), (4, 'd')]));
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered above the previous element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_before_1() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_before(0, 'd');
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered above the previous element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_before_2() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_before(1, 'd');
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered below the current element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_before_3() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_before(2, 'd');
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered below the current element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_before_4() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_before(3, 'd');
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered above the current element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_after_1() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_after(1, 'd');
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered above the current element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_after_2() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_after(2, 'd');
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered below the next element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_after_3() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_after(3, 'd');
|
||||
}
|
||||
|
||||
#[should_panic(expected = "key must be ordered below the next element")]
|
||||
#[test]
|
||||
fn test_cursor_mut_insert_after_4() {
|
||||
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
|
||||
let mut cur = map.upper_bound_mut(Bound::Included(&2));
|
||||
cur.insert_after(4, 'd');
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ use crate::task::{Context, Poll};
|
||||
/// 2. This broken invariant is then later observed.
|
||||
///
|
||||
/// Typically in Rust, it is difficult to perform step (2) because catching a
|
||||
/// panic involves either spawning a thread (which in turns makes it difficult
|
||||
/// panic involves either spawning a thread (which in turn makes it difficult
|
||||
/// to later witness broken invariants) or using the `catch_unwind` function in this
|
||||
/// module. Additionally, even if an invariant is witnessed, it typically isn't a
|
||||
/// problem in Rust because there are no uninitialized values (like in C or C++).
|
||||
|
@ -268,7 +268,7 @@ pub(crate) use self::stdio::attempt_print_to_stderr;
|
||||
#[unstable(feature = "internal_output_capture", issue = "none")]
|
||||
#[doc(no_inline, hidden)]
|
||||
pub use self::stdio::set_output_capture;
|
||||
#[unstable(feature = "is_terminal", issue = "98070")]
|
||||
#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub use self::stdio::IsTerminal;
|
||||
#[unstable(feature = "print_internals", issue = "none")]
|
||||
pub use self::stdio::{_eprint, _print};
|
||||
|
@ -1047,7 +1047,7 @@ pub(crate) fn attempt_print_to_stderr(args: fmt::Arguments<'_>) {
|
||||
}
|
||||
|
||||
/// Trait to determine if a descriptor/handle refers to a terminal/tty.
|
||||
#[unstable(feature = "is_terminal", issue = "98070")]
|
||||
#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub trait IsTerminal: crate::sealed::Sealed {
|
||||
/// Returns `true` if the descriptor/handle refers to a terminal/tty.
|
||||
///
|
||||
@ -1063,6 +1063,7 @@ pub trait IsTerminal: crate::sealed::Sealed {
|
||||
/// Note that this [may change in the future][changes].
|
||||
///
|
||||
/// [changes]: io#platform-specific-behavior
|
||||
#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")]
|
||||
fn is_terminal(&self) -> bool;
|
||||
}
|
||||
|
||||
@ -1071,7 +1072,7 @@ macro_rules! impl_is_terminal {
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
impl crate::sealed::Sealed for $t {}
|
||||
|
||||
#[unstable(feature = "is_terminal", issue = "98070")]
|
||||
#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl IsTerminal for $t {
|
||||
#[inline]
|
||||
fn is_terminal(&self) -> bool {
|
||||
|
@ -254,7 +254,6 @@
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(intra_doc_pointers)]
|
||||
#![feature(is_terminal)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(linkage)]
|
||||
|
@ -201,7 +201,7 @@ macro_rules! impl_is_terminal {
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
impl crate::sealed::Sealed for $t {}
|
||||
|
||||
#[unstable(feature = "is_terminal", issue = "98070")]
|
||||
#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl crate::io::IsTerminal for $t {
|
||||
#[inline]
|
||||
fn is_terminal(&self) -> bool {
|
||||
|
@ -389,7 +389,7 @@ macro_rules! impl_is_terminal {
|
||||
#[unstable(feature = "sealed", issue = "none")]
|
||||
impl crate::sealed::Sealed for $t {}
|
||||
|
||||
#[unstable(feature = "is_terminal", issue = "98070")]
|
||||
#[stable(feature = "is_terminal", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl crate::io::IsTerminal for $t {
|
||||
#[inline]
|
||||
fn is_terminal(&self) -> bool {
|
||||
|
@ -17,7 +17,6 @@
|
||||
#![unstable(feature = "test", issue = "50297")]
|
||||
#![doc(test(attr(deny(warnings))))]
|
||||
#![feature(internal_output_capture)]
|
||||
#![feature(is_terminal)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(process_exitcode_internals)]
|
||||
#![feature(panic_can_unwind)]
|
||||
|
@ -7,7 +7,6 @@
|
||||
#![feature(assert_matches)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(drain_filter)]
|
||||
#![feature(is_terminal)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(test)]
|
||||
#![feature(never_type)]
|
||||
|
@ -7,7 +7,6 @@
|
||||
#![feature(yeet_expr)]
|
||||
#![feature(nonzero_ops)]
|
||||
#![feature(local_key_cell_methods)]
|
||||
#![feature(is_terminal)]
|
||||
#![feature(round_ties_even)]
|
||||
// Configure clippy and other lints
|
||||
#![allow(
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#![feature(io_error_more)]
|
||||
#![feature(io_error_uncategorized)]
|
||||
#![feature(is_terminal)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::{c_char, OsString};
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![feature(is_terminal)]
|
||||
|
||||
use std::io::IsTerminal;
|
||||
|
||||
fn main() {
|
||||
|
@ -11,7 +11,12 @@ error[E0223]: ambiguous associated type
|
||||
--> $DIR/missing-assoc-item.rs:6:12
|
||||
|
|
||||
LL | for<B> B::Item: Send,
|
||||
| ^^^^^^^ help: use the fully-qualified path: `<B as IntoIterator>::Item`
|
||||
| ^^^^^^^
|
||||
|
|
||||
help: if there were a trait named `Example` with associated type `Item` implemented for `B`, you could use the fully-qualified path
|
||||
|
|
||||
LL | for<B> <B as Example>::Item: Send,
|
||||
| ~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
|
12
tests/ui/typeck/issue-110052.rs
Normal file
12
tests/ui/typeck/issue-110052.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// Makes sure we deal with escaping lifetimes *above* INNERMOST when
|
||||
// suggesting trait for ambiguous associated type.
|
||||
|
||||
impl<I, V> Validator<I> for ()
|
||||
where
|
||||
for<'iter> dyn Validator<<&'iter I>::Item>:,
|
||||
//~^ ERROR ambiguous associated type
|
||||
{}
|
||||
|
||||
pub trait Validator<T> {}
|
||||
|
||||
fn main() {}
|
9
tests/ui/typeck/issue-110052.stderr
Normal file
9
tests/ui/typeck/issue-110052.stderr
Normal file
@ -0,0 +1,9 @@
|
||||
error[E0223]: ambiguous associated type
|
||||
--> $DIR/issue-110052.rs:6:30
|
||||
|
|
||||
LL | for<'iter> dyn Validator<<&'iter I>::Item>:,
|
||||
| ^^^^^^^^^^^^^^^^ help: use the fully-qualified path: `<&'iter I as IntoIterator>::Item`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0223`.
|
Loading…
x
Reference in New Issue
Block a user