From: bors Date: Fri, 4 May 2018 02:58:37 +0000 (+0000) Subject: Auto merge of #50433 - nrc:update, r=alexcrichton X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=841e0ccb4cabaaf20041e3ba5c3e927cb95d86ce;hp=4952426c50cf4379afa3d1eb3647f30afeb5d690;p=rust.git Auto merge of #50433 - nrc:update, r=alexcrichton Update RLS and Rustfmt (and Cargo) Updates RLS and Rustfmt (the latter fixing tests). Cargo is updated too (to fix RLS tests), but that is covered by https://github.com/rust-lang/rust/pull/50417, so probably won't do much. r? @alexcrichton --- diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 096aed85f55..ccba5a09cf6 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -407,7 +407,7 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { drop(variables); self.relate(&u, &u) } - TypeVariableValue::Unknown { .. } => { + TypeVariableValue::Unknown { universe } => { match self.ambient_variance { // Invariant: no need to make a fresh type variable. ty::Invariant => return Ok(t), @@ -424,7 +424,7 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { } let origin = *variables.var_origin(vid); - let new_var_id = variables.new_var(false, origin); + let new_var_id = variables.new_var(universe, false, origin); let u = self.tcx().mk_var(new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index c35cdf91fe7..b8437e39ddc 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -62,7 +62,7 @@ pub fn higher_ranked_sub(&mut self, a: &Binder, b: &Binder, a_is_expect // Second, we instantiate each bound region in the supertype with a // fresh concrete region. let (b_prime, skol_map) = - self.infcx.skolemize_late_bound_regions(b, snapshot); + self.infcx.skolemize_late_bound_regions(b); debug!("a_prime={:?}", a_prime); debug!("b_prime={:?}", b_prime); @@ -114,7 +114,7 @@ pub fn higher_ranked_match(&mut self, // First, we instantiate each bound region in the matcher // with a skolemized region. let ((a_match, a_value), skol_map) = - self.infcx.skolemize_late_bound_regions(a_pair, snapshot); + self.infcx.skolemize_late_bound_regions(a_pair); debug!("higher_ranked_match: a_match={:?}", a_match); debug!("higher_ranked_match: skol_map={:?}", skol_map); @@ -587,14 +587,13 @@ fn region_vars_confined_to_snapshot(&self, /// /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html pub fn skolemize_late_bound_regions(&self, - binder: &ty::Binder, - snapshot: &CombinedSnapshot<'a, 'tcx>) + binder: &ty::Binder) -> (T, SkolemizationMap<'tcx>) where T : TypeFoldable<'tcx> { let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| { - self.borrow_region_constraints() - .push_skolemized(self.tcx, br, &snapshot.region_constraints_snapshot) + self.universe.set(self.universe().subuniverse()); + self.tcx.mk_region(ty::ReSkolemized(self.universe(), br)) }); debug!("skolemize_bound_regions(binder={:?}, result={:?}, map={:?})", @@ -779,7 +778,8 @@ pub fn pop_skolemized(&self, debug!("pop_skolemized({:?})", skol_map); let skol_regions: FxHashSet<_> = skol_map.values().cloned().collect(); self.borrow_region_constraints() - .pop_skolemized(self.tcx, &skol_regions, &snapshot.region_constraints_snapshot); + .pop_skolemized(self.universe(), &skol_regions, &snapshot.region_constraints_snapshot); + self.universe.set(snapshot.universe); if !skol_map.is_empty() { self.projection_cache.borrow_mut().rollback_skolemized( &snapshot.projection_cache_snapshot); diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 00b2ac7449f..5984a831e6f 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -15,7 +15,7 @@ use infer::region_constraints::Constraint; use infer::region_constraints::GenericKind; use infer::region_constraints::RegionConstraintData; -use infer::region_constraints::VarOrigins; +use infer::region_constraints::VarInfos; use infer::region_constraints::VerifyBound; use middle::free_region::RegionRelations; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; @@ -37,7 +37,7 @@ /// all the variables as well as a set of errors that must be reported. pub fn resolve<'tcx>( region_rels: &RegionRelations<'_, '_, 'tcx>, - var_origins: VarOrigins, + var_infos: VarInfos, data: RegionConstraintData<'tcx>, ) -> ( LexicalRegionResolutions<'tcx>, @@ -47,7 +47,7 @@ pub fn resolve<'tcx>( let mut errors = vec![]; let mut resolver = LexicalResolver { region_rels, - var_origins, + var_infos, data, }; let values = resolver.infer_variable_values(&mut errors); @@ -103,7 +103,7 @@ struct RegionAndOrigin<'tcx> { struct LexicalResolver<'cx, 'gcx: 'tcx, 'tcx: 'cx> { region_rels: &'cx RegionRelations<'cx, 'gcx, 'tcx>, - var_origins: VarOrigins, + var_infos: VarInfos, data: RegionConstraintData<'tcx>, } @@ -132,7 +132,7 @@ fn infer_variable_values( } fn num_vars(&self) -> usize { - self.var_origins.len() + self.var_infos.len() } /// Initially, the value for all variables is set to `'empty`, the @@ -279,7 +279,7 @@ fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> (&ReVar(v_id), _) | (_, &ReVar(v_id)) => { span_bug!( - self.var_origins[v_id].span(), + self.var_infos[v_id].origin.span(), "lub_concrete_regions invoked with non-concrete \ regions: {:?}, {:?}", a, @@ -576,7 +576,7 @@ fn region_order_key(x: &RegionAndOrigin) -> u8 { if !self.region_rels .is_subregion_of(lower_bound.region, upper_bound.region) { - let origin = self.var_origins[node_idx].clone(); + let origin = self.var_infos[node_idx].origin.clone(); debug!( "region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \ sup: {:?}", @@ -598,7 +598,7 @@ fn region_order_key(x: &RegionAndOrigin) -> u8 { } span_bug!( - self.var_origins[node_idx].span(), + self.var_infos[node_idx].origin.span(), "collect_error_for_expanding_node() could not find \ error for var {:?}, lower_bounds={:?}, \ upper_bounds={:?}", diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 553926dba8f..c62e7f8d9b6 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -42,7 +42,7 @@ use self::combine::CombineFields; use self::higher_ranked::HrMatchResult; use self::region_constraints::{RegionConstraintCollector, RegionSnapshot}; -use self::region_constraints::{GenericKind, VerifyBound, RegionConstraintData, VarOrigins}; +use self::region_constraints::{GenericKind, VerifyBound, RegionConstraintData, VarInfos}; use self::lexical_region_resolve::LexicalRegionResolutions; use self::outlives::env::OutlivesEnvironment; use self::type_variable::TypeVariableOrigin; @@ -183,6 +183,17 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { // obligations within. This is expected to be done 'late enough' // that all type inference variables have been bound and so forth. pub region_obligations: RefCell)>>, + + /// What is the innermost universe we have created? Starts out as + /// `UniverseIndex::root()` but grows from there as we enter + /// universal quantifiers. + /// + /// NB: At present, we exclude the universal quantifiers on the + /// item we are type-checking, and just consider those names as + /// part of the root universe. So this would only get incremented + /// when we enter into a higher-ranked (`for<..>`) type or trait + /// bound. + universe: Cell, } /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized @@ -455,6 +466,7 @@ pub fn enter(&'tcx mut self, f: F) -> R err_count_on_creation: tcx.sess.err_count(), in_snapshot: Cell::new(false), region_obligations: RefCell::new(vec![]), + universe: Cell::new(ty::UniverseIndex::ROOT), })) } } @@ -489,6 +501,7 @@ pub struct CombinedSnapshot<'a, 'tcx:'a> { float_snapshot: ut::Snapshot>, region_constraints_snapshot: RegionSnapshot, region_obligations_snapshot: usize, + universe: ty::UniverseIndex, was_in_snapshot: bool, _in_progress_tables: Option>>, } @@ -618,6 +631,7 @@ fn start_snapshot(&self) -> CombinedSnapshot<'a, 'tcx> { float_snapshot: self.float_unification_table.borrow_mut().snapshot(), region_constraints_snapshot: self.borrow_region_constraints().start_snapshot(), region_obligations_snapshot: self.region_obligations.borrow().len(), + universe: self.universe(), was_in_snapshot: in_snapshot, // Borrow tables "in progress" (i.e. during typeck) // to ban writes from within a snapshot to them. @@ -635,10 +649,12 @@ fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'a, 'tcx>) { float_snapshot, region_constraints_snapshot, region_obligations_snapshot, + universe, was_in_snapshot, _in_progress_tables } = snapshot; self.in_snapshot.set(was_in_snapshot); + self.universe.set(universe); self.projection_cache .borrow_mut() @@ -667,6 +683,7 @@ fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) { float_snapshot, region_constraints_snapshot, region_obligations_snapshot: _, + universe: _, was_in_snapshot, _in_progress_tables } = snapshot; @@ -811,7 +828,7 @@ pub fn subtype_predicate(&self, Some(self.commit_if_ok(|snapshot| { let (ty::SubtypePredicate { a_is_expected, a, b}, skol_map) = - self.skolemize_late_bound_regions(predicate, snapshot); + self.skolemize_late_bound_regions(predicate); let cause_span = cause.span; let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; @@ -828,7 +845,7 @@ pub fn region_outlives_predicate(&self, { self.commit_if_ok(|snapshot| { let (ty::OutlivesPredicate(r_a, r_b), skol_map) = - self.skolemize_late_bound_regions(predicate, snapshot); + self.skolemize_late_bound_regions(predicate); let origin = SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span)); @@ -841,7 +858,7 @@ pub fn region_outlives_predicate(&self, pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid { self.type_variables .borrow_mut() - .new_var(diverging, origin) + .new_var(self.universe(), diverging, origin) } pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { @@ -872,12 +889,14 @@ pub fn next_float_var_id(&self) -> FloatVid { /// during diagnostics / error-reporting. pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region<'tcx> { - self.tcx.mk_region(ty::ReVar(self.borrow_region_constraints().new_region_var(origin))) + let region_var = self.borrow_region_constraints() + .new_region_var(self.universe(), origin); + self.tcx.mk_region(ty::ReVar(region_var)) } /// Number of region variables created so far. pub fn num_region_vars(&self) -> usize { - self.borrow_region_constraints().var_origins().len() + self.borrow_region_constraints().num_region_vars() } /// Just a convenient wrapper of `next_region_var` for using during NLL. @@ -909,7 +928,8 @@ pub fn type_var_for_def(&self, -> Ty<'tcx> { let ty_var_id = self.type_variables .borrow_mut() - .new_var(false, + .new_var(self.universe(), + false, TypeVariableOrigin::TypeParameterDefinition(span, def.name)); self.tcx.mk_var(ty_var_id) @@ -1004,12 +1024,12 @@ fn resolve_regions_and_report_errors_inner( region_context, region_map, outlives_env.free_region_map()); - let (var_origins, data) = self.region_constraints.borrow_mut() + let (var_infos, data) = self.region_constraints.borrow_mut() .take() .expect("regions already resolved") - .into_origins_and_data(); + .into_infos_and_data(); let (lexical_region_resolutions, errors) = - lexical_region_resolve::resolve(region_rels, var_origins, data); + lexical_region_resolve::resolve(region_rels, var_infos, data); let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); assert!(old_value.is_none()); @@ -1057,13 +1077,13 @@ pub fn with_region_constraints( /// hence that `resolve_regions_and_report_errors` can never be /// called. This is used only during NLL processing to "hand off" ownership /// of the set of region vairables into the NLL region context. - pub fn take_region_var_origins(&self) -> VarOrigins { - let (var_origins, data) = self.region_constraints.borrow_mut() + pub fn take_region_var_origins(&self) -> VarInfos { + let (var_infos, data) = self.region_constraints.borrow_mut() .take() .expect("regions already resolved") - .into_origins_and_data(); + .into_infos_and_data(); assert!(data.is_empty()); - var_origins + var_infos } pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { @@ -1356,6 +1376,10 @@ pub fn clear_caches(&self) { self.evaluation_cache.clear(); self.projection_cache.borrow_mut().clear(); } + + fn universe(&self) -> ty::UniverseIndex { + self.universe.get() + } } impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> { diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 4113a2dd417..c388fa21371 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -22,18 +22,16 @@ use ty::{self, Ty, TyCtxt}; use ty::{Region, RegionVid}; use ty::ReStatic; -use ty::{BrFresh, ReLateBound, ReSkolemized, ReVar}; +use ty::{BrFresh, ReLateBound, ReVar}; use std::collections::BTreeMap; -use std::fmt; -use std::mem; -use std::u32; +use std::{cmp, fmt, mem, u32}; mod taint; pub struct RegionConstraintCollector<'tcx> { /// For each `RegionVid`, the corresponding `RegionVariableOrigin`. - var_origins: IndexVec, + var_infos: IndexVec, data: RegionConstraintData<'tcx>, @@ -47,9 +45,6 @@ pub struct RegionConstraintCollector<'tcx> { /// exist). This prevents us from making many such regions. glbs: CombineMap<'tcx>, - /// Number of skolemized variables currently active. - skolemization_count: u32, - /// Global counter used during the GLB algorithm to create unique /// names for fresh bound regions bound_count: u32, @@ -76,7 +71,7 @@ pub struct RegionConstraintCollector<'tcx> { unification_table: ut::UnificationTable>, } -pub type VarOrigins = IndexVec; +pub type VarInfos = IndexVec; /// The full set of region constraints gathered up by the collector. /// Describes constraints between the region variables and other @@ -230,10 +225,15 @@ enum CombineMapType { type CombineMap<'tcx> = FxHashMap, RegionVid>; +#[derive(Debug, Clone, Copy)] +pub struct RegionVariableInfo { + pub origin: RegionVariableOrigin, + pub universe: ty::UniverseIndex, +} + pub struct RegionSnapshot { length: usize, region_snapshot: ut::Snapshot>, - skolemization_count: u32, } /// When working with skolemized regions, we often wish to find all of @@ -273,19 +273,18 @@ pub fn both() -> Self { impl<'tcx> RegionConstraintCollector<'tcx> { pub fn new() -> RegionConstraintCollector<'tcx> { RegionConstraintCollector { - var_origins: VarOrigins::default(), + var_infos: VarInfos::default(), data: RegionConstraintData::default(), lubs: FxHashMap(), glbs: FxHashMap(), - skolemization_count: 0, bound_count: 0, undo_log: Vec::new(), unification_table: ut::UnificationTable::new(), } } - pub fn var_origins(&self) -> &VarOrigins { - &self.var_origins + pub fn num_region_vars(&self) -> usize { + self.var_infos.len() } pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> { @@ -295,9 +294,9 @@ pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> { /// Once all the constraints have been gathered, extract out the final data. /// /// Not legal during a snapshot. - pub fn into_origins_and_data(self) -> (VarOrigins, RegionConstraintData<'tcx>) { + pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) { assert!(!self.in_snapshot()); - (self.var_origins, self.data) + (self.var_infos, self.data) } /// Takes (and clears) the current set of constraints. Note that @@ -319,18 +318,15 @@ pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> { // should think carefully about whether it needs to be cleared // or updated in some way. let RegionConstraintCollector { - var_origins, + var_infos, data, lubs, glbs, - skolemization_count, bound_count: _, undo_log: _, unification_table, } = self; - assert_eq!(*skolemization_count, 0); - // Clear the tables of (lubs, glbs), so that we will create // fresh regions if we do a LUB operation. As it happens, // LUB/GLB are not performed by the MIR type-checker, which is @@ -343,7 +339,7 @@ pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> { // also insert `a <= b` and a `b <= a` edges, so the // `RegionConstraintData` contains the relationship here. *unification_table = ut::UnificationTable::new(); - for vid in var_origins.indices() { + for vid in var_infos.indices() { unification_table.new_key(unify_key::RegionVidKey { min_vid: vid }); } @@ -365,7 +361,6 @@ pub fn start_snapshot(&mut self) -> RegionSnapshot { RegionSnapshot { length, region_snapshot: self.unification_table.snapshot(), - skolemization_count: self.skolemization_count, } } @@ -373,12 +368,6 @@ pub fn commit(&mut self, snapshot: RegionSnapshot) { debug!("RegionConstraintCollector: commit({})", snapshot.length); assert!(self.undo_log.len() > snapshot.length); assert!(self.undo_log[snapshot.length] == OpenSnapshot); - assert!( - self.skolemization_count == snapshot.skolemization_count, - "failed to pop skolemized regions: {} now vs {} at start", - self.skolemization_count, - snapshot.skolemization_count - ); if snapshot.length == 0 { self.undo_log.truncate(0); @@ -398,7 +387,6 @@ pub fn rollback_to(&mut self, snapshot: RegionSnapshot) { } let c = self.undo_log.pop().unwrap(); assert!(c == OpenSnapshot); - self.skolemization_count = snapshot.skolemization_count; self.unification_table.rollback_to(snapshot.region_snapshot); } @@ -411,8 +399,8 @@ fn rollback_undo_entry(&mut self, undo_entry: UndoLogEntry<'tcx>) { // nothing to do here } AddVar(vid) => { - self.var_origins.pop().unwrap(); - assert_eq!(self.var_origins.len(), vid.index() as usize); + self.var_infos.pop().unwrap(); + assert_eq!(self.var_infos.len(), vid.index() as usize); } AddConstraint(ref constraint) => { self.data.constraints.remove(constraint); @@ -433,8 +421,13 @@ fn rollback_undo_entry(&mut self, undo_entry: UndoLogEntry<'tcx>) { } } - pub fn new_region_var(&mut self, origin: RegionVariableOrigin) -> RegionVid { - let vid = self.var_origins.push(origin.clone()); + pub fn new_region_var(&mut self, + universe: ty::UniverseIndex, + origin: RegionVariableOrigin) -> RegionVid { + let vid = self.var_infos.push(RegionVariableInfo { + origin, + universe, + }); let u_vid = self.unification_table .new_key(unify_key::RegionVidKey { min_vid: vid }); @@ -450,44 +443,14 @@ pub fn new_region_var(&mut self, origin: RegionVariableOrigin) -> RegionVid { return vid; } - /// Returns the origin for the given variable. - pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin { - self.var_origins[vid].clone() + /// Returns the universe for the given variable. + pub fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex { + self.var_infos[vid].universe } - /// Creates a new skolemized region. Skolemized regions are fresh - /// regions used when performing higher-ranked computations. They - /// must be used in a very particular way and are never supposed - /// to "escape" out into error messages or the code at large. - /// - /// The idea is to always create a snapshot. Skolemized regions - /// can be created in the context of this snapshot, but before the - /// snapshot is committed or rolled back, they must be popped - /// (using `pop_skolemized_regions`), so that their numbers can be - /// recycled. Normally you don't have to think about this: you use - /// the APIs in `higher_ranked/mod.rs`, such as - /// `skolemize_late_bound_regions` and `plug_leaks`, which will - /// guide you on this path (ensure that the `SkolemizationMap` is - /// consumed and you are good). For more info on how skolemization - /// for HRTBs works, see the [rustc guide]. - /// - /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html - /// - /// The `snapshot` argument to this function is not really used; - /// it's just there to make it explicit which snapshot bounds the - /// skolemized region that results. It should always be the top-most snapshot. - pub fn push_skolemized( - &mut self, - tcx: TyCtxt<'_, '_, 'tcx>, - br: ty::BoundRegion, - snapshot: &RegionSnapshot, - ) -> Region<'tcx> { - assert!(self.in_snapshot()); - assert!(self.undo_log[snapshot.length] == OpenSnapshot); - - let sc = self.skolemization_count; - self.skolemization_count = sc + 1; - tcx.mk_region(ReSkolemized(ty::SkolemizedRegionVid { index: sc }, br)) + /// Returns the origin for the given variable. + pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin { + self.var_infos[vid].origin } /// Removes all the edges to/from the skolemized regions that are @@ -496,7 +459,7 @@ pub fn push_skolemized( /// created in that time. pub fn pop_skolemized( &mut self, - _tcx: TyCtxt<'_, '_, 'tcx>, + skolemization_count: ty::UniverseIndex, skols: &FxHashSet>, snapshot: &RegionSnapshot, ) { @@ -505,36 +468,28 @@ pub fn pop_skolemized( assert!(self.in_snapshot()); assert!(self.undo_log[snapshot.length] == OpenSnapshot); assert!( - self.skolemization_count as usize >= skols.len(), + skolemization_count.as_usize() >= skols.len(), "popping more skolemized variables than actually exist, \ - sc now = {}, skols.len = {}", - self.skolemization_count, + sc now = {:?}, skols.len = {:?}", + skolemization_count, skols.len() ); - let last_to_pop = self.skolemization_count; - let first_to_pop = last_to_pop - (skols.len() as u32); + let last_to_pop = skolemization_count.subuniverse(); + let first_to_pop = ty::UniverseIndex::from(last_to_pop.as_u32() - skols.len() as u32); - assert!( - first_to_pop >= snapshot.skolemization_count, - "popping more regions than snapshot contains, \ - sc now = {}, sc then = {}, skols.len = {}", - self.skolemization_count, - snapshot.skolemization_count, - skols.len() - ); debug_assert! { skols.iter() .all(|&k| match *k { - ty::ReSkolemized(index, _) => - index.index >= first_to_pop && - index.index < last_to_pop, + ty::ReSkolemized(universe, _) => + universe >= first_to_pop && + universe < last_to_pop, _ => false }), - "invalid skolemization keys or keys out of range ({}..{}): {:?}", - snapshot.skolemization_count, - self.skolemization_count, + "invalid skolemization keys or keys out of range ({:?}..{:?}): {:?}", + first_to_pop, + last_to_pop, skols } @@ -551,7 +506,6 @@ pub fn pop_skolemized( self.rollback_undo_entry(undo_entry); } - self.skolemization_count = snapshot.skolemization_count; return; fn kill_constraint<'tcx>( @@ -805,7 +759,10 @@ fn combine_vars( if let Some(&c) = self.combine_map(t).get(&vars) { return tcx.mk_region(ReVar(c)); } - let c = self.new_region_var(MiscVariable(origin.span())); + let a_universe = self.universe(a); + let b_universe = self.universe(b); + let c_universe = cmp::max(a_universe, b_universe); + let c = self.new_region_var(c_universe, MiscVariable(origin.span())); self.combine_map(t).insert(vars, c); if self.in_snapshot() { self.undo_log.push(AddCombination(t, vars)); @@ -821,6 +778,24 @@ fn combine_vars( new_r } + fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex { + match *region { + ty::ReScope(..) | + ty::ReStatic | + ty::ReEmpty | + ty::ReErased | + ty::ReFree(..) | + ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT, + ty::ReSkolemized(universe, _) => universe, + ty::ReClosureBound(vid) | + ty::ReVar(vid) => self.var_universe(vid), + ty::ReLateBound(..) => + bug!("universe(): encountered bound region {:?}", region), + ty::ReCanonical(..) => + bug!("region_universe(): encountered canonical region {:?}", region), + } + } + pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec { self.undo_log[mark.length..] .iter() @@ -865,12 +840,7 @@ pub fn tainted( impl fmt::Debug for RegionSnapshot { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "RegionSnapshot(length={},skolemization={})", - self.length, - self.skolemization_count - ) + write!(f, "RegionSnapshot(length={})", self.length) } } diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 5e96f4eb576..d40e1b3760f 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -78,10 +78,12 @@ struct TypeVariableData { #[derive(Copy, Clone, Debug)] pub enum TypeVariableValue<'tcx> { Known { value: Ty<'tcx> }, - Unknown, + Unknown { universe: ty::UniverseIndex }, } impl<'tcx> TypeVariableValue<'tcx> { + /// If this value is known, returns the type it is known to be. + /// Otherwise, `None`. pub fn known(&self) -> Option> { match *self { TypeVariableValue::Unknown { .. } => None, @@ -181,10 +183,11 @@ pub fn instantiate(&mut self, vid: ty::TyVid, ty: Ty<'tcx>) { /// The code in this module doesn't care, but it can be useful /// for improving error messages. pub fn new_var(&mut self, + universe: ty::UniverseIndex, diverging: bool, origin: TypeVariableOrigin) -> ty::TyVid { - let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown); + let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown { universe }); let sub_key = self.sub_relations.new_key(()); assert_eq!(eq_key.vid, sub_key); @@ -437,7 +440,16 @@ fn unify_values(value1: &Self, value2: &Self) -> Result { (&TypeVariableValue::Unknown { .. }, &TypeVariableValue::Known { .. }) => Ok(*value2), // If both sides are *unknown*, it hardly matters, does it? - (&TypeVariableValue::Unknown, &TypeVariableValue::Unknown) => Ok(*value1), + (&TypeVariableValue::Unknown { universe: universe1 }, + &TypeVariableValue::Unknown { universe: universe2 }) => { + // If we unify two unbound variables, ?T and ?U, then whatever + // value they wind up taking (which must be the same value) must + // be nameable by both universes. Therefore, the resulting + // universe is the minimum of the two universes, because that is + // the one which contains the fewest names in scope. + let universe = cmp::min(universe1, universe2); + Ok(TypeVariableValue::Unknown { universe }) + } } } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 1f1fdfafe33..45fa588bbf5 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -188,7 +188,7 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( let infcx = selcx.infcx(); infcx.commit_if_ok(|snapshot| { let (skol_predicate, skol_map) = - infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot); + infcx.skolemize_late_bound_regions(&obligation.predicate); let skol_obligation = obligation.with(skol_predicate); let r = match project_and_unify_type(selcx, &skol_obligation) { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 4ba3655bb64..54b2cf28082 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1509,7 +1509,7 @@ fn match_projection_obligation_against_definition_bounds( let poly_trait_predicate = self.infcx().resolve_type_vars_if_possible(&obligation.predicate); let (skol_trait_predicate, skol_map) = - self.infcx().skolemize_late_bound_regions(&poly_trait_predicate, snapshot); + self.infcx().skolemize_late_bound_regions(&poly_trait_predicate); debug!("match_projection_obligation_against_definition_bounds: \ skol_trait_predicate={:?} skol_map={:?}", skol_trait_predicate, @@ -2338,7 +2338,7 @@ fn collect_predicates_for_types(&mut self, self.in_snapshot(|this, snapshot| { let (skol_ty, skol_map) = - this.infcx().skolemize_late_bound_regions(&ty, snapshot); + this.infcx().skolemize_late_bound_regions(&ty); let Normalized { value: normalized_ty, mut obligations } = project::normalize_with_depth(this, param_env, @@ -2559,7 +2559,7 @@ fn vtable_auto_impl(&mut self, let trait_obligations = self.in_snapshot(|this, snapshot| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); let (trait_ref, skol_map) = - this.infcx().skolemize_late_bound_regions(&poly_trait_ref, snapshot); + this.infcx().skolemize_late_bound_regions(&poly_trait_ref); let cause = obligation.derived_cause(ImplDerivedObligation); this.impl_or_trait_obligations(cause, obligation.recursion_depth + 1, @@ -3142,8 +3142,7 @@ fn match_impl(&mut self, } let (skol_obligation, skol_map) = self.infcx().skolemize_late_bound_regions( - &obligation.predicate, - snapshot); + &obligation.predicate); let skol_obligation_trait_ref = skol_obligation.trait_ref; let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4fdc247686f..c4fe112a9e9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -69,7 +69,7 @@ pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const}; pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region}; pub use self::sty::RegionKind; -pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid}; +pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid}; pub use self::sty::BoundRegion::*; pub use self::sty::InferTy::*; pub use self::sty::RegionKind::*; @@ -1370,15 +1370,13 @@ pub fn is_empty(&self) -> bool { /// type name in a non-zero universe is a skolemized type -- an /// idealized representative of "types in general" that we use for /// checking generic functions. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct UniverseIndex(u32); impl UniverseIndex { /// The root universe, where things that the user defined are /// visible. - pub fn root() -> UniverseIndex { - UniverseIndex(0) - } + pub const ROOT: Self = UniverseIndex(0); /// A "subuniverse" corresponds to being inside a `forall` quantifier. /// So, for example, suppose we have this type in universe `U`: @@ -1392,7 +1390,21 @@ pub fn root() -> UniverseIndex { /// region `'a`, but that region was not nameable from `U` because /// it was not in scope there. pub fn subuniverse(self) -> UniverseIndex { - UniverseIndex(self.0 + 1) + UniverseIndex(self.0.checked_add(1).unwrap()) + } + + pub fn as_u32(&self) -> u32 { + self.0 + } + + pub fn as_usize(&self) -> usize { + self.0 as usize + } +} + +impl From for UniverseIndex { + fn from(index: u32) -> Self { + UniverseIndex(index) } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0d655562214..382db571b52 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1021,7 +1021,7 @@ pub enum RegionKind { /// A skolemized region - basically the higher-ranked version of ReFree. /// Should not exist after typeck. - ReSkolemized(SkolemizedRegionVid, BoundRegion), + ReSkolemized(ty::UniverseIndex, BoundRegion), /// Empty lifetime is for data that is never accessed. /// Bottom in the region lattice. We treat ReEmpty somewhat @@ -1075,11 +1075,6 @@ pub struct FloatVid { DEBUG_FORMAT = custom, }); -#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)] -pub struct SkolemizedRegionVid { - pub index: u32, -} - #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum InferTy { TyVar(TyVid), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index b777f513e6d..894a18b79cc 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -808,8 +808,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "'?{}", c.index()) } - ty::ReSkolemized(id, ref bound_region) => { - write!(f, "ReSkolemized({}, {:?})", id.index, bound_region) + ty::ReSkolemized(universe, ref bound_region) => { + write!(f, "ReSkolemized({:?}, {:?})", universe, bound_region) } ty::ReEmpty => write!(f, "ReEmpty"), diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 08391401cc6..4d1f3e2b430 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -16,7 +16,7 @@ use rustc::infer::RegionVariableOrigin; use rustc::infer::SubregionOrigin; use rustc::infer::error_reporting::nice_region_error::NiceRegionError; -use rustc::infer::region_constraints::{GenericKind, VarOrigins}; +use rustc::infer::region_constraints::{GenericKind, VarInfos}; use rustc::mir::{ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location, Mir}; use rustc::traits::ObligationCause; @@ -256,19 +256,19 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// of those will be constant regions representing the free /// regions defined in `universal_regions`. pub(crate) fn new( - var_origins: VarOrigins, + var_infos: VarInfos, universal_regions: UniversalRegions<'tcx>, mir: &Mir<'tcx>, ) -> Self { - let num_region_variables = var_origins.len(); + let num_region_variables = var_infos.len(); let num_universal_regions = universal_regions.len(); let elements = &Rc::new(RegionValueElements::new(mir, num_universal_regions)); // Create a RegionDefinition for each inference variable. - let definitions = var_origins + let definitions = var_infos .into_iter() - .map(|origin| RegionDefinition::new(origin)) + .map(|info| RegionDefinition::new(info.origin)) .collect(); let mut result = Self {