mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-30 00:23:41 +00:00
Auto merge of #85313 - jackh726:region_eq, r=nikomatsakis
Unify Regions with RegionVids in UnificationTable A few test output changes; might be able to revert those but figured I would open this for perf and comments. r? `@nikomatsakis`
This commit is contained in:
commit
70b9d1e102
@ -3,7 +3,6 @@
|
||||
use self::CombineMapType::*;
|
||||
use self::UndoLog::*;
|
||||
|
||||
use super::unify_key;
|
||||
use super::{
|
||||
InferCtxtUndoLogs, MiscVariable, RegionVariableOrigin, Rollback, Snapshot, SubregionOrigin,
|
||||
};
|
||||
@ -12,9 +11,9 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_data_structures::undo_log::UndoLogs;
|
||||
use rustc_data_structures::unify as ut;
|
||||
use rustc_data_structures::unify::UnifyKey;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
|
||||
use rustc_middle::ty::ReStatic;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{ReLateBound, ReVar};
|
||||
@ -54,7 +53,7 @@ pub struct RegionConstraintStorage<'tcx> {
|
||||
/// code is iterating to a fixed point, because otherwise we sometimes
|
||||
/// would wind up with a fresh stream of region variables that have been
|
||||
/// equated but appear distinct.
|
||||
pub(super) unification_table: ut::UnificationTableStorage<ty::RegionVid>,
|
||||
pub(super) unification_table: ut::UnificationTableStorage<RegionVidKey<'tcx>>,
|
||||
|
||||
/// a flag set to true when we perform any unifications; this is used
|
||||
/// to micro-optimize `take_and_reset_data`
|
||||
@ -407,8 +406,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
// `RegionConstraintData` contains the relationship here.
|
||||
if *any_unifications {
|
||||
*any_unifications = false;
|
||||
self.unification_table()
|
||||
.reset_unifications(|vid| unify_key::RegionVidKey { min_vid: vid });
|
||||
self.unification_table().reset_unifications(|_| UnifiedRegion(None));
|
||||
}
|
||||
|
||||
data
|
||||
@ -435,8 +433,8 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
) -> RegionVid {
|
||||
let vid = self.var_infos.push(RegionVariableInfo { origin, universe });
|
||||
|
||||
let u_vid = self.unification_table().new_key(unify_key::RegionVidKey { min_vid: vid });
|
||||
assert_eq!(vid, u_vid);
|
||||
let u_vid = self.unification_table().new_key(UnifiedRegion(None));
|
||||
assert_eq!(vid, u_vid.vid);
|
||||
self.undo_log.push(AddVar(vid));
|
||||
debug!("created new region variable {:?} in {:?} with origin {:?}", vid, universe, origin);
|
||||
vid
|
||||
@ -498,10 +496,18 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
self.make_subregion(origin.clone(), sub, sup);
|
||||
self.make_subregion(origin, sup, sub);
|
||||
|
||||
if let (ty::ReVar(sub), ty::ReVar(sup)) = (*sub, *sup) {
|
||||
debug!("make_eqregion: uniying {:?} with {:?}", sub, sup);
|
||||
self.unification_table().union(sub, sup);
|
||||
self.any_unifications = true;
|
||||
match (sub, sup) {
|
||||
(&ty::ReVar(sub), &ty::ReVar(sup)) => {
|
||||
debug!("make_eqregion: unifying {:?} with {:?}", sub, sup);
|
||||
self.unification_table().union(sub, sup);
|
||||
self.any_unifications = true;
|
||||
}
|
||||
(&ty::ReVar(vid), value) | (value, &ty::ReVar(vid)) => {
|
||||
debug!("make_eqregion: unifying {:?} with {:?}", vid, value);
|
||||
self.unification_table().union_value(vid, UnifiedRegion(Some(value)));
|
||||
self.any_unifications = true;
|
||||
}
|
||||
(_, _) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -617,8 +623,29 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn opportunistic_resolve_var(&mut self, rid: RegionVid) -> ty::RegionVid {
|
||||
self.unification_table().probe_value(rid).min_vid
|
||||
/// Resolves the passed RegionVid to the root RegionVid in the unification table
|
||||
pub fn opportunistic_resolve_var(&mut self, rid: ty::RegionVid) -> ty::RegionVid {
|
||||
self.unification_table().find(rid).vid
|
||||
}
|
||||
|
||||
/// If the Region is a `ReVar`, then resolves it either to the root value in
|
||||
/// the unification table, if it exists, or to the root `ReVar` in the table.
|
||||
/// If the Region is not a `ReVar`, just returns the Region itself.
|
||||
pub fn opportunistic_resolve_region(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
region: ty::Region<'tcx>,
|
||||
) -> ty::Region<'tcx> {
|
||||
match region {
|
||||
ty::ReVar(rid) => {
|
||||
let unified_region = self.unification_table().probe_value(*rid);
|
||||
unified_region.0.unwrap_or_else(|| {
|
||||
let root = self.unification_table().find(*rid).vid;
|
||||
tcx.reuse_or_mk_region(region, ty::ReVar(root))
|
||||
})
|
||||
}
|
||||
_ => region,
|
||||
}
|
||||
}
|
||||
|
||||
fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {
|
||||
@ -673,8 +700,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
&self,
|
||||
value_count: usize,
|
||||
) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) {
|
||||
let range = RegionVid::from_index(value_count as u32)
|
||||
..RegionVid::from_index(self.unification_table.len() as u32);
|
||||
let range = RegionVid::from(value_count)..RegionVid::from(self.unification_table.len());
|
||||
(
|
||||
range.clone(),
|
||||
(range.start.index()..range.end.index())
|
||||
@ -696,7 +722,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, ty::RegionVid> {
|
||||
fn unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, RegionVidKey<'tcx>> {
|
||||
ut::UnificationTable::with_log(&mut self.storage.unification_table, self.undo_log)
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ use std::marker::PhantomData;
|
||||
use rustc_data_structures::snapshot_vec as sv;
|
||||
use rustc_data_structures::undo_log::{Rollback, UndoLogs};
|
||||
use rustc_data_structures::unify as ut;
|
||||
use rustc_middle::infer::unify_key::RegionVidKey;
|
||||
use rustc_middle::ty;
|
||||
|
||||
use crate::{
|
||||
@ -22,7 +23,7 @@ pub(crate) enum UndoLog<'tcx> {
|
||||
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
|
||||
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
|
||||
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
|
||||
RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>),
|
||||
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
|
||||
ProjectionCache(traits::UndoLog<'tcx>),
|
||||
PushRegionObligation,
|
||||
}
|
||||
@ -55,7 +56,7 @@ impl_from! {
|
||||
|
||||
ConstUnificationTable(sv::UndoLog<ut::Delegate<ty::ConstVid<'tcx>>>),
|
||||
|
||||
RegionUnificationTable(sv::UndoLog<ut::Delegate<ty::RegionVid>>),
|
||||
RegionUnificationTable(sv::UndoLog<ut::Delegate<RegionVidKey<'tcx>>>),
|
||||
ProjectionCache(traits::UndoLog<'tcx>),
|
||||
}
|
||||
|
||||
|
@ -16,37 +16,48 @@ pub trait ToType {
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||
pub struct RegionVidKey {
|
||||
/// The minimum region vid in the unification set. This is needed
|
||||
/// to have a canonical name for a type to prevent infinite
|
||||
/// recursion.
|
||||
pub min_vid: ty::RegionVid,
|
||||
pub struct UnifiedRegion<'tcx>(pub Option<ty::Region<'tcx>>);
|
||||
|
||||
#[derive(PartialEq, Copy, Clone, Debug)]
|
||||
pub struct RegionVidKey<'tcx> {
|
||||
pub vid: ty::RegionVid,
|
||||
pub phantom: PhantomData<UnifiedRegion<'tcx>>,
|
||||
}
|
||||
|
||||
impl UnifyValue for RegionVidKey {
|
||||
impl<'tcx> From<ty::RegionVid> for RegionVidKey<'tcx> {
|
||||
fn from(vid: ty::RegionVid) -> Self {
|
||||
RegionVidKey { vid, phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UnifyKey for RegionVidKey<'tcx> {
|
||||
type Value = UnifiedRegion<'tcx>;
|
||||
fn index(&self) -> u32 {
|
||||
self.vid.as_u32()
|
||||
}
|
||||
fn from_index(i: u32) -> Self {
|
||||
RegionVidKey::from(ty::RegionVid::from_u32(i))
|
||||
}
|
||||
fn tag() -> &'static str {
|
||||
"RegionVidKey"
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UnifyValue for UnifiedRegion<'tcx> {
|
||||
type Error = NoError;
|
||||
|
||||
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
|
||||
let min_vid = if value1.min_vid.index() < value2.min_vid.index() {
|
||||
value1.min_vid
|
||||
} else {
|
||||
value2.min_vid
|
||||
};
|
||||
Ok(match (value1.0, value2.0) {
|
||||
// Here we can just pick one value, because the full constraints graph
|
||||
// will be handled later. Ideally, we might want a `MultipleValues`
|
||||
// variant or something. For now though, this is fine.
|
||||
(Some(_), Some(_)) => *value1,
|
||||
|
||||
Ok(RegionVidKey { min_vid })
|
||||
}
|
||||
}
|
||||
(Some(_), _) => *value1,
|
||||
(_, Some(_)) => *value2,
|
||||
|
||||
impl UnifyKey for ty::RegionVid {
|
||||
type Value = RegionVidKey;
|
||||
fn index(&self) -> u32 {
|
||||
u32::from(*self)
|
||||
}
|
||||
fn from_index(i: u32) -> ty::RegionVid {
|
||||
ty::RegionVid::from(i)
|
||||
}
|
||||
fn tag() -> &'static str {
|
||||
"RegionVid"
|
||||
(None, None) => *value1,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,4 +26,6 @@ fn main() {
|
||||
// Should only be a few notes.
|
||||
is_send::<X<C<'static>>>();
|
||||
//~^ ERROR overflow evaluating
|
||||
//~| 2 redundant requirements hidden
|
||||
//~| required because of
|
||||
}
|
||||
|
@ -7,11 +7,13 @@ LL | fn is_send<S: NotAuto>() {}
|
||||
LL | is_send::<X<C<'static>>>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: required because of the requirements on the impl of `NotAuto` for `X<C<'static>>`
|
||||
note: required because of the requirements on the impl of `NotAuto` for `X<C<'_>>`
|
||||
--> $DIR/lifetime.rs:19:12
|
||||
|
|
||||
LL | impl<T: Y> NotAuto for X<T> where T::P: NotAuto {}
|
||||
| ^^^^^^^ ^^^^
|
||||
= note: 2 redundant requirements hidden
|
||||
= note: required because of the requirements on the impl of `NotAuto` for `X<C<'static>>`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user