From 443a2d4f86258e4d4234ce8ab851a491096dc058 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 19 Mar 2019 21:30:07 +0000 Subject: [PATCH 01/16] Update ena --- Cargo.lock | 11 ++++++++++- src/librustc_data_structures/Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7fd39bd1f6eb6..0443ea30be9ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -780,6 +780,14 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ena" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "env_logger" version = "0.5.13" @@ -2662,7 +2670,7 @@ name = "rustc_data_structures" version = "0.0.0" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4043,6 +4051,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455" "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" +"checksum ena 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1bc0780a33d340b98e80725a927ff9c3fe30eac92b414725968faeb49458df17" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index 6002bf69b7069..e0306ff273191 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -10,7 +10,7 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] -ena = "0.11" +ena = "0.12" log = "0.4" jobserver_crate = { version = "0.1", package = "jobserver" } lazy_static = "1" From 92b2021b0a34262f2aa823fadd462e2437ead2d8 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 20 Mar 2019 00:57:25 +0000 Subject: [PATCH 02/16] Make `vars_since_snapshot` naming consistent --- src/librustc/infer/fudge.rs | 12 ++++++------ src/librustc/infer/region_constraints/mod.rs | 2 +- src/librustc/infer/type_variable.rs | 8 +++----- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index 5f6a8802b4def..4dc4341d4c88c 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -64,12 +64,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // going to be popped, so we will have to // eliminate any references to them. - let type_variables = - self.type_variables.borrow_mut().types_created_since_snapshot( - &snapshot.type_snapshot); - let region_vars = - self.borrow_region_constraints().vars_created_since_snapshot( - &snapshot.region_constraints_snapshot); + let type_variables = self.type_variables.borrow_mut().vars_since_snapshot( + &snapshot.type_snapshot, + ); + let region_vars = self.borrow_region_constraints().vars_since_snapshot( + &snapshot.region_constraints_snapshot, + ); Ok((type_variables, region_vars, value)) } diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 8389f0ab1aa79..fae216c7fe7b7 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -840,7 +840,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } } - pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec { + pub fn vars_since_snapshot(&self, mark: &RegionSnapshot) -> Vec { self.undo_log[mark.length..] .iter() .filter_map(|&elt| match elt { diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 4c76818346b43..ae7ac855228dd 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -292,11 +292,9 @@ impl<'tcx> TypeVariableTable<'tcx> { self.sub_relations.commit(sub_snapshot); } - /// Returns a map `{V1 -> V2}`, where the keys `{V1}` are - /// ty-variables created during the snapshot, and the values - /// `{V2}` are the root variables that they were unified with, - /// along with their origin. - pub fn types_created_since_snapshot(&mut self, s: &Snapshot<'tcx>) -> TypeVariableMap { + /// Returns a map from the type variables created during the + /// snapshot to the origin of the type variable. + pub fn vars_since_snapshot(&mut self, s: &Snapshot<'tcx>) -> TypeVariableMap { let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot); actions_since_snapshot From 2a08860ae6ec94eccbe7b2b73fbe9d0c175196d4 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 20 Mar 2019 01:54:53 +0000 Subject: [PATCH 03/16] Simplify `RegionConstraintCollector::vars_since_snapshot` --- src/librustc/infer/region_constraints/mod.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index fae216c7fe7b7..c0d118eed86ab 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -841,12 +841,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } pub fn vars_since_snapshot(&self, mark: &RegionSnapshot) -> Vec { - self.undo_log[mark.length..] - .iter() - .filter_map(|&elt| match elt { - AddVar(vid) => Some(vid), - _ => None, - }).collect() + self.unification_table.vars_since_snapshot(&mark.region_snapshot).collect() } /// See [`RegionInference::region_constraints_added_in_snapshot`]. From a5c653be6389c5d62368ed07c60f064b6f1c037e Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 20 Mar 2019 10:07:30 +0000 Subject: [PATCH 04/16] Simplify `TypeVariableTable::vars_since_snapshot` --- src/librustc/infer/type_variable.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index ae7ac855228dd..422dd24eb0b45 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -295,19 +295,10 @@ impl<'tcx> TypeVariableTable<'tcx> { /// Returns a map from the type variables created during the /// snapshot to the origin of the type variable. pub fn vars_since_snapshot(&mut self, s: &Snapshot<'tcx>) -> TypeVariableMap { - let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot); - - actions_since_snapshot - .iter() - .filter_map(|action| match action { - &sv::UndoLog::NewElem(index) => Some(ty::TyVid { index: index as u32 }), - _ => None, - }) - .map(|vid| { - let origin = self.values.get(vid.index as usize).origin.clone(); - (vid, origin) - }) - .collect() + self.values.values_since_snapshot(&s.snapshot).map(|idx| { + let origin = self.values.get(idx).origin.clone(); + (ty::TyVid { index: idx as u32 }, origin) + }).collect() } /// Finds the set of type variables that existed *before* `s` From abf5e816636428454262b907d64e6d8cb45dc387 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 21 Mar 2019 12:37:31 +0000 Subject: [PATCH 05/16] Use Ranges for vars_since_snapshot --- src/librustc/infer/fudge.rs | 59 ++++++++++---------- src/librustc/infer/region_constraints/mod.rs | 5 +- src/librustc/infer/type_variable.rs | 12 ++-- src/librustc/lib.rs | 1 + 4 files changed, 38 insertions(+), 39 deletions(-) diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index 4dc4341d4c88c..d8107e64d28b0 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -1,10 +1,11 @@ -use crate::infer::type_variable::TypeVariableMap; -use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::{self, Ty, TyCtxt, TyVid, RegionVid}; use crate::ty::fold::{TypeFoldable, TypeFolder}; use super::InferCtxt; use super::RegionVariableOrigin; +use std::ops::Range; + impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// This rather funky routine is used while processing expected /// types. What happens here is that we want to propagate a @@ -42,12 +43,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// regions in question are not particularly important. We will /// use the expected types to guide coercions, but we will still /// type-check the resulting types from those coercions against - /// the actual types (`?T`, `Option`) -- and remember that /// after the snapshot is popped, the variable `?T` is no longer /// unified. - pub fn fudge_regions_if_ok(&self, - origin: &RegionVariableOrigin, - f: F) -> Result where + pub fn fudge_regions_if_ok( + &self, + origin: &RegionVariableOrigin, + f: F, + ) -> Result where F: FnOnce() -> Result, T: TypeFoldable<'tcx>, { @@ -101,8 +104,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub struct RegionFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - type_variables: &'a TypeVariableMap, - region_vars: &'a Vec, + type_variables: &'a Range, + region_vars: &'a Range, origin: &'a RegionVariableOrigin, } @@ -114,25 +117,21 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { match ty.sty { ty::Infer(ty::InferTy::TyVar(vid)) => { - match self.type_variables.get(&vid) { - None => { - // This variable was created before the - // "fudging". Since we refresh all type - // variables to their binding anyhow, we know - // that it is unbound, so we can just return - // it. - debug_assert!(self.infcx.type_variables.borrow_mut() - .probe(vid) - .is_unknown()); - ty - } - - Some(&origin) => { - // This variable was created during the - // fudging. Recreate it with a fresh variable - // here. - self.infcx.next_ty_var(origin) - } + if self.type_variables.contains(&vid) { + // This variable was created during the fudging. + // Recreate it with a fresh variable here. + let origin = self.infcx.type_variables.borrow().var_origin(vid).clone(); + self.infcx.next_ty_var(origin) + } else { + // This variable was created before the + // "fudging". Since we refresh all type + // variables to their binding anyhow, we know + // that it is unbound, so we can just return + // it. + debug_assert!(self.infcx.type_variables.borrow_mut() + .probe(vid) + .is_unknown()); + ty } } _ => ty.super_fold_with(self), @@ -141,12 +140,10 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match *r { - ty::ReVar(v) if self.region_vars.contains(&v) => { + ty::ReVar(vid) if self.region_vars.contains(&vid) => { self.infcx.next_region_var(self.origin.clone()) } - _ => { - r - } + _ => r, } } } diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index c0d118eed86ab..51d8a0edc81d3 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -16,6 +16,7 @@ use crate::ty::{Region, RegionVid}; use std::collections::BTreeMap; use std::{cmp, fmt, mem, u32}; +use std::ops::Range; mod leak_check; @@ -840,8 +841,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } } - pub fn vars_since_snapshot(&self, mark: &RegionSnapshot) -> Vec { - self.unification_table.vars_since_snapshot(&mark.region_snapshot).collect() + pub fn vars_since_snapshot(&self, mark: &RegionSnapshot) -> Range { + self.unification_table.vars_since_snapshot(&mark.region_snapshot) } /// See [`RegionInference::region_constraints_added_in_snapshot`]. diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 422dd24eb0b45..a5b2e591f91bb 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -1,13 +1,15 @@ use syntax::symbol::InternedString; use syntax_pos::Span; -use crate::ty::{self, Ty}; +use crate::ty::{self, Ty, TyVid}; use std::cmp; use std::marker::PhantomData; +use std::ops::Range; use std::u32; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::unify as ut; +use ut::UnifyKey; pub struct TypeVariableTable<'tcx> { values: sv::SnapshotVec, @@ -294,11 +296,9 @@ impl<'tcx> TypeVariableTable<'tcx> { /// Returns a map from the type variables created during the /// snapshot to the origin of the type variable. - pub fn vars_since_snapshot(&mut self, s: &Snapshot<'tcx>) -> TypeVariableMap { - self.values.values_since_snapshot(&s.snapshot).map(|idx| { - let origin = self.values.get(idx).origin.clone(); - (ty::TyVid { index: idx as u32 }, origin) - }).collect() + pub fn vars_since_snapshot(&mut self, s: &Snapshot<'tcx>) -> Range { + let range = self.values.values_since_snapshot(&s.snapshot); + TyVid::from_index(range.start as u32)..TyVid::from_index(range.end as u32) } /// Finds the set of type variables that existed *before* `s` diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 4b2fda3b02f9d..e905c3688518b 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -44,6 +44,7 @@ #![feature(non_exhaustive)] #![feature(proc_macro_internals)] #![feature(optin_builtin_traits)] +#![feature(range_is_empty)] #![feature(refcell_replace_swap)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_attrs)] From 6cc09fc8b2b678ea605254ea9a0fd58da3e4d44b Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 21 Mar 2019 12:38:05 +0000 Subject: [PATCH 06/16] Remove `TypeVariableMap` --- src/librustc/infer/type_variable.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index a5b2e591f91bb..96a9f9520b406 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -60,8 +60,6 @@ pub enum TypeVariableOrigin { Generalized(ty::TyVid), } -pub type TypeVariableMap = FxHashMap; - struct TypeVariableData { origin: TypeVariableOrigin, diverging: bool, From 1f9a2326b58b1de43cb3d1bfae1e1403f5d059ef Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 21 Mar 2019 12:39:05 +0000 Subject: [PATCH 07/16] Rename `RegionFudger` to `InferenceFudger` --- src/librustc/infer/fudge.rs | 14 +++++++------- src/librustc_typeck/check/mod.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index d8107e64d28b0..a335a21359bce 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -18,7 +18,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// from `&[u32; 3]` to `&[u32]` and make the users life more /// pleasant. /// - /// The way we do this is using `fudge_regions_if_ok`. What the + /// The way we do this is using `fudge_inference_if_ok`. What the /// routine actually does is to start a snapshot and execute the /// closure `f`. In our example above, what this closure will do /// is to unify the expectation (`Option<&[u32]>`) with the actual @@ -27,7 +27,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// with `&?a [u32]`, where `?a` is a fresh lifetime variable. The /// input type (`?T`) is then returned by `f()`. /// - /// At this point, `fudge_regions_if_ok` will normalize all type + /// At this point, `fudge_inference_if_ok` will normalize all type /// variables, converting `?T` to `&?a [u32]` and end the /// snapshot. The problem is that we can't just return this type /// out, because it references the region variable `?a`, and that @@ -46,7 +46,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// the actual types (`?T`, `Option`) -- and remember that /// after the snapshot is popped, the variable `?T` is no longer /// unified. - pub fn fudge_regions_if_ok( + pub fn fudge_inference_if_ok( &self, origin: &RegionVariableOrigin, f: F, @@ -54,7 +54,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { F: FnOnce() -> Result, T: TypeFoldable<'tcx>, { - debug!("fudge_regions_if_ok(origin={:?})", origin); + debug!("fudge_inference_if_ok(origin={:?})", origin); let (type_variables, region_vars, value) = self.probe(|snapshot| { match f() { @@ -91,7 +91,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return Ok(value); } - let mut fudger = RegionFudger { + let mut fudger = InferenceFudger { infcx: self, type_variables: &type_variables, region_vars: ®ion_vars, @@ -102,14 +102,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } -pub struct RegionFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +pub struct InferenceFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, type_variables: &'a Range, region_vars: &'a Range, origin: &'a RegionVariableOrigin, } -impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> { +impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b11bd9c2408bf..c0a869d99b9de 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3231,7 +3231,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(ret) => ret, None => return Vec::new() }; - let expect_args = self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || { + let expect_args = self.fudge_inference_if_ok(&RegionVariableOrigin::Coercion(call_span), || { // Attempt to apply a subtyping relationship between the formal // return type (likely containing type variables if the function // is polymorphic) and the expected return type. From ac94858e32bdf7a8d00126e8d901dfd44e2df508 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 21 Mar 2019 13:39:57 +0000 Subject: [PATCH 08/16] Add int variables and float variables to `InferenceFudger` --- src/librustc/infer/fudge.rs | 43 +++++++++++++++++++++++------ src/librustc/infer/type_variable.rs | 1 - 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index a335a21359bce..198e0ce738191 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -1,4 +1,4 @@ -use crate::ty::{self, Ty, TyCtxt, TyVid, RegionVid}; +use crate::ty::{self, Ty, TyCtxt, TyVid, IntVid, FloatVid, RegionVid}; use crate::ty::fold::{TypeFoldable, TypeFolder}; use super::InferCtxt; @@ -56,7 +56,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { debug!("fudge_inference_if_ok(origin={:?})", origin); - let (type_variables, region_vars, value) = self.probe(|snapshot| { + let (type_vars, int_vars, float_vars, region_vars, value) = self.probe(|snapshot| { match f() { Ok(value) => { let value = self.resolve_type_vars_if_possible(&value); @@ -67,14 +67,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // going to be popped, so we will have to // eliminate any references to them. - let type_variables = self.type_variables.borrow_mut().vars_since_snapshot( + let type_vars = self.type_variables.borrow_mut().vars_since_snapshot( &snapshot.type_snapshot, ); + let int_vars = self.int_unification_table.borrow_mut().vars_since_snapshot( + &snapshot.int_snapshot, + ); + let float_vars = self.float_unification_table.borrow_mut().vars_since_snapshot( + &snapshot.float_snapshot, + ); let region_vars = self.borrow_region_constraints().vars_since_snapshot( &snapshot.region_constraints_snapshot, ); - Ok((type_variables, region_vars, value)) + Ok((type_vars, int_vars, float_vars, region_vars, value)) } Err(e) => Err(e), } @@ -87,13 +93,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Micro-optimization: if no variables have been created, then // `value` can't refer to any of them. =) So we can just return it. - if type_variables.is_empty() && region_vars.is_empty() { + if type_vars.is_empty() && + int_vars.is_empty() && + float_vars.is_empty() && + region_vars.is_empty() { return Ok(value); } let mut fudger = InferenceFudger { infcx: self, - type_variables: &type_variables, + type_vars: &type_vars, + int_vars: &int_vars, + float_vars: &float_vars, region_vars: ®ion_vars, origin, }; @@ -104,7 +115,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub struct InferenceFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - type_variables: &'a Range, + type_vars: &'a Range, + int_vars: &'a Range, + float_vars: &'a Range, region_vars: &'a Range, origin: &'a RegionVariableOrigin, } @@ -117,7 +130,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { match ty.sty { ty::Infer(ty::InferTy::TyVar(vid)) => { - if self.type_variables.contains(&vid) { + if self.type_vars.contains(&vid) { // This variable was created during the fudging. // Recreate it with a fresh variable here. let origin = self.infcx.type_variables.borrow().var_origin(vid).clone(); @@ -134,6 +147,20 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> ty } } + ty::Infer(ty::InferTy::IntVar(vid)) => { + if self.int_vars.contains(&vid) { + self.infcx.tcx.mk_int_var(self.infcx.next_int_var_id()) + } else { + ty + } + } + ty::Infer(ty::InferTy::FloatVar(vid)) => { + if self.float_vars.contains(&vid) { + self.infcx.tcx.mk_float_var(self.infcx.next_float_var_id()) + } else { + ty + } + } _ => ty.super_fold_with(self), } } diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 96a9f9520b406..a09c03c34cafa 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -6,7 +6,6 @@ use std::cmp; use std::marker::PhantomData; use std::ops::Range; use std::u32; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::unify as ut; use ut::UnifyKey; From f9d8bb8e2cb9a8ce7f8663c0a114cbc1a81209d4 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 21 Mar 2019 13:43:37 +0000 Subject: [PATCH 09/16] Simplify `fudge_inference_if_ok` --- src/librustc/infer/fudge.rs | 38 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index 198e0ce738191..f21fb603cb599 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -56,7 +56,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { debug!("fudge_inference_if_ok(origin={:?})", origin); - let (type_vars, int_vars, float_vars, region_vars, value) = self.probe(|snapshot| { + let (mut fudger, value) = self.probe(|snapshot| { match f() { Ok(value) => { let value = self.resolve_type_vars_if_possible(&value); @@ -80,7 +80,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { &snapshot.region_constraints_snapshot, ); - Ok((type_vars, int_vars, float_vars, region_vars, value)) + let fudger = InferenceFudger { + infcx: self, + type_vars, + int_vars, + float_vars, + region_vars, + origin, + }; + + Ok((fudger, value)) } Err(e) => Err(e), } @@ -93,32 +102,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Micro-optimization: if no variables have been created, then // `value` can't refer to any of them. =) So we can just return it. - if type_vars.is_empty() && - int_vars.is_empty() && - float_vars.is_empty() && - region_vars.is_empty() { + if fudger.type_vars.is_empty() && + fudger.int_vars.is_empty() && + fudger.float_vars.is_empty() && + fudger.region_vars.is_empty() { return Ok(value); } - let mut fudger = InferenceFudger { - infcx: self, - type_vars: &type_vars, - int_vars: &int_vars, - float_vars: &float_vars, - region_vars: ®ion_vars, - origin, - }; - Ok(value.fold_with(&mut fudger)) } } pub struct InferenceFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - type_vars: &'a Range, - int_vars: &'a Range, - float_vars: &'a Range, - region_vars: &'a Range, + type_vars: Range, + int_vars: Range, + float_vars: Range, + region_vars: Range, origin: &'a RegionVariableOrigin, } From fa18c129c3cbb1ef9f731da126a3b2fdcfbd03a6 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 21 Mar 2019 13:47:57 +0000 Subject: [PATCH 10/16] Add `next_int_var` and `next_float_var` --- src/librustc/infer/canonical/mod.rs | 4 ++-- src/librustc/infer/fudge.rs | 4 ++-- src/librustc/infer/mod.rs | 12 ++++++++++-- src/librustc_typeck/check/mod.rs | 6 ++---- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index 95fdd6f01e2a8..39b84fabff6fb 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -360,9 +360,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { ) } - CanonicalTyVarKind::Int => self.tcx.mk_int_var(self.next_int_var_id()), + CanonicalTyVarKind::Int => self.next_int_var(), - CanonicalTyVarKind::Float => self.tcx.mk_float_var(self.next_float_var_id()), + CanonicalTyVarKind::Float => self.next_float_var(), }; ty.into() } diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index f21fb603cb599..ba9100bc4f7a7 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -149,14 +149,14 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> } ty::Infer(ty::InferTy::IntVar(vid)) => { if self.int_vars.contains(&vid) { - self.infcx.tcx.mk_int_var(self.infcx.next_int_var_id()) + self.infcx.next_int_var() } else { ty } } ty::Infer(ty::InferTy::FloatVar(vid)) => { if self.float_vars.contains(&vid) { - self.infcx.tcx.mk_float_var(self.infcx.next_float_var_id()) + self.infcx.next_float_var() } else { ty } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index cc1c439f3bd94..16140d006bf09 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -999,14 +999,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.tcx.mk_ty_var(self.next_ty_var_id(true, origin)) } - pub fn next_int_var_id(&self) -> IntVid { + fn next_int_var_id(&self) -> IntVid { self.int_unification_table.borrow_mut().new_key(None) } - pub fn next_float_var_id(&self) -> FloatVid { + pub fn next_int_var(&self) -> Ty<'tcx> { + self.tcx.mk_int_var(self.next_int_var_id()) + } + + fn next_float_var_id(&self) -> FloatVid { self.float_unification_table.borrow_mut().new_key(None) } + pub fn next_float_var(&self) -> Ty<'tcx> { + self.tcx.mk_float_var(self.next_float_var_id()) + } + /// Creates a fresh region variable with the next available index. /// The variable will be created in the maximum universe created /// thus far, allowing it to name any region created thus far. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c0a869d99b9de..7a554605232ce 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3097,8 +3097,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => None } }); - opt_ty.unwrap_or_else( - || tcx.mk_int_var(self.next_int_var_id())) + opt_ty.unwrap_or_else(|| self.next_int_var()) } ast::LitKind::Float(_, t) => tcx.mk_mach_float(t), ast::LitKind::FloatUnsuffixed(_) => { @@ -3108,8 +3107,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => None } }); - opt_ty.unwrap_or_else( - || tcx.mk_float_var(self.next_float_var_id())) + opt_ty.unwrap_or_else(|| self.next_float_var()) } ast::LitKind::Bool(_) => tcx.types.bool, ast::LitKind::Err(_) => tcx.types.err, From 267370ed585a722a551e3b493e4a32dc6ebe80ce Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 21 Mar 2019 17:11:42 +0000 Subject: [PATCH 11/16] Use `eq_relations` --- src/librustc/infer/fudge.rs | 10 +++++----- src/librustc/infer/type_variable.rs | 8 +++----- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index ba9100bc4f7a7..18573b9ce176f 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -62,7 +62,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let value = self.resolve_type_vars_if_possible(&value); // At this point, `value` could in principle refer - // to types/regions that have been created during + // to inference variables that have been created during // the snapshot. Once we exit `probe()`, those are // going to be popped, so we will have to // eliminate any references to them. @@ -106,10 +106,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fudger.int_vars.is_empty() && fudger.float_vars.is_empty() && fudger.region_vars.is_empty() { - return Ok(value); + Ok(value) + } else { + Ok(value.fold_with(&mut fudger)) } - - Ok(value.fold_with(&mut fudger)) } } @@ -137,7 +137,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> self.infcx.next_ty_var(origin) } else { // This variable was created before the - // "fudging". Since we refresh all type + // "fudging". Since we refresh all type // variables to their binding anyhow, we know // that it is unbound, so we can just return // it. diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index a09c03c34cafa..5b9c3f25b20fd 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -8,7 +8,6 @@ use std::ops::Range; use std::u32; use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::unify as ut; -use ut::UnifyKey; pub struct TypeVariableTable<'tcx> { values: sv::SnapshotVec, @@ -291,11 +290,10 @@ impl<'tcx> TypeVariableTable<'tcx> { self.sub_relations.commit(sub_snapshot); } - /// Returns a map from the type variables created during the - /// snapshot to the origin of the type variable. + /// Returns a range of the type variables created during the snapshot. pub fn vars_since_snapshot(&mut self, s: &Snapshot<'tcx>) -> Range { - let range = self.values.values_since_snapshot(&s.snapshot); - TyVid::from_index(range.start as u32)..TyVid::from_index(range.end as u32) + let range = self.eq_relations.vars_since_snapshot(&s.eq_snapshot); + range.start.vid..range.end.vid } /// Finds the set of type variables that existed *before* `s` From 3683f51352311dc5adb3788239bdb498f002f850 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Mar 2019 15:45:44 +0000 Subject: [PATCH 12/16] Update ena to version 0.13.0 --- Cargo.lock | 6 +++--- src/librustc_data_structures/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0443ea30be9ae..73adb762e485b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "ena" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2670,7 +2670,7 @@ name = "rustc_data_structures" version = "0.0.0" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "ena 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "graphviz 0.0.0", "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4051,7 +4051,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0" "checksum elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455" "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00" -"checksum ena 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1bc0780a33d340b98e80725a927ff9c3fe30eac92b414725968faeb49458df17" +"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index e0306ff273191..63e44d82a28c3 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -10,7 +10,7 @@ path = "lib.rs" crate-type = ["dylib"] [dependencies] -ena = "0.12" +ena = "0.13" log = "0.4" jobserver_crate = { version = "0.1", package = "jobserver" } lazy_static = "1" From 58a04f06cb6522040af4d9352c3a25dd66547acc Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Mar 2019 16:48:57 +0000 Subject: [PATCH 13/16] Propitiate tidy --- src/librustc_typeck/check/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7a554605232ce..433f6685d1ff1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3229,7 +3229,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(ret) => ret, None => return Vec::new() }; - let expect_args = self.fudge_inference_if_ok(&RegionVariableOrigin::Coercion(call_span), || { + let origin = RegionVariableOrigin::Coercion(call_span); + let expect_args = self.fudge_inference_if_ok(&origin, || { // Attempt to apply a subtyping relationship between the formal // return type (likely containing type variables if the function // is polymorphic) and the expected return type. From 2d48ffa9c63255eafa25639142f3b5601d42ae05 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Mar 2019 21:28:15 +0000 Subject: [PATCH 14/16] Store type variable origins in InferenceFudger --- src/librustc/infer/fudge.rs | 7 ++++--- src/librustc/infer/type_variable.rs | 12 +++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index 18573b9ce176f..4c603cb54559d 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -3,8 +3,10 @@ use crate::ty::fold::{TypeFoldable, TypeFolder}; use super::InferCtxt; use super::RegionVariableOrigin; +use super::type_variable::TypeVariableOrigin; use std::ops::Range; +use rustc_data_structures::fx::FxHashMap; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// This rather funky routine is used while processing expected @@ -115,7 +117,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub struct InferenceFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - type_vars: Range, + type_vars: FxHashMap, int_vars: Range, float_vars: Range, region_vars: Range, @@ -130,10 +132,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { match ty.sty { ty::Infer(ty::InferTy::TyVar(vid)) => { - if self.type_vars.contains(&vid) { + if let Some(&origin) = self.type_vars.get(&vid) { // This variable was created during the fudging. // Recreate it with a fresh variable here. - let origin = self.infcx.type_variables.borrow().var_origin(vid).clone(); self.infcx.next_ty_var(origin) } else { // This variable was created before the diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 5b9c3f25b20fd..cde695aefc10a 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -4,8 +4,8 @@ use crate::ty::{self, Ty, TyVid}; use std::cmp; use std::marker::PhantomData; -use std::ops::Range; use std::u32; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::unify as ut; @@ -291,9 +291,15 @@ impl<'tcx> TypeVariableTable<'tcx> { } /// Returns a range of the type variables created during the snapshot. - pub fn vars_since_snapshot(&mut self, s: &Snapshot<'tcx>) -> Range { + pub fn vars_since_snapshot( + &mut self, + s: &Snapshot<'tcx>, + ) -> FxHashMap { let range = self.eq_relations.vars_since_snapshot(&s.eq_snapshot); - range.start.vid..range.end.vid + (range.start.vid.index..range.end.vid.index).map(|index| { + let origin = self.values.get(index as usize).origin.clone(); + (TyVid { index }, origin) + }).collect() } /// Finds the set of type variables that existed *before* `s` From 688cbad9b89fb79d651f62480bb65fdb5d2c6e02 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Mar 2019 21:28:39 +0000 Subject: [PATCH 15/16] Lookup region variable origin instead of choosing one --- src/librustc/infer/fudge.rs | 15 ++++++--------- src/librustc/infer/region_constraints/mod.rs | 13 ++++++++++--- src/librustc_typeck/check/mod.rs | 5 ++--- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index 4c603cb54559d..c19507c2f3c3e 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -50,13 +50,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// unified. pub fn fudge_inference_if_ok( &self, - origin: &RegionVariableOrigin, f: F, ) -> Result where F: FnOnce() -> Result, T: TypeFoldable<'tcx>, { - debug!("fudge_inference_if_ok(origin={:?})", origin); + debug!("fudge_inference_if_ok()"); let (mut fudger, value) = self.probe(|snapshot| { match f() { @@ -88,7 +87,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { int_vars, float_vars, region_vars, - origin, }; Ok((fudger, value)) @@ -120,8 +118,7 @@ pub struct InferenceFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { type_vars: FxHashMap, int_vars: Range, float_vars: Range, - region_vars: Range, - origin: &'a RegionVariableOrigin, + region_vars: FxHashMap, } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> { @@ -167,11 +164,11 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - match *r { - ty::ReVar(vid) if self.region_vars.contains(&vid) => { - self.infcx.next_region_var(self.origin.clone()) + if let ty::ReVar(vid) = r { + if let Some(&origin) = self.region_vars.get(&vid) { + return self.infcx.next_region_var(origin); } - _ => r, } + r } } diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 51d8a0edc81d3..c3c4e724c6956 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -16,7 +16,6 @@ use crate::ty::{Region, RegionVid}; use std::collections::BTreeMap; use std::{cmp, fmt, mem, u32}; -use std::ops::Range; mod leak_check; @@ -841,8 +840,16 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } } - pub fn vars_since_snapshot(&self, mark: &RegionSnapshot) -> Range { - self.unification_table.vars_since_snapshot(&mark.region_snapshot) + pub fn vars_since_snapshot( + &self, + mark: &RegionSnapshot, + ) -> FxHashMap { + let range = self.unification_table.vars_since_snapshot(&mark.region_snapshot); + (range.start.index()..range.end.index()).map(|index| { + let vid = ty::RegionVid::from(index); + let origin = self.var_infos[vid].origin.clone(); + (vid, origin) + }).collect() } /// See [`RegionInference::region_constraints_added_in_snapshot`]. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 433f6685d1ff1..ec4fc2a3bfb88 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -92,7 +92,7 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::ItemLikeVisitor; use crate::middle::lang_items; use crate::namespace::Namespace; -use rustc::infer::{self, InferCtxt, InferOk, InferResult, RegionVariableOrigin}; +use rustc::infer::{self, InferCtxt, InferOk, InferResult}; use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; @@ -3229,8 +3229,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Some(ret) => ret, None => return Vec::new() }; - let origin = RegionVariableOrigin::Coercion(call_span); - let expect_args = self.fudge_inference_if_ok(&origin, || { + let expect_args = self.fudge_inference_if_ok(|| { // Attempt to apply a subtyping relationship between the formal // return type (likely containing type variables if the function // is polymorphic) and the expected return type. From 86d5a69d9d884b3c40be464c7dc32261f35accc5 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 25 Mar 2019 22:26:37 +0000 Subject: [PATCH 16/16] Use Vec instead of FxHashMap --- src/librustc/infer/fudge.rs | 17 ++++++++++------- src/librustc/infer/region_constraints/mod.rs | 11 +++++------ src/librustc/infer/type_variable.rs | 11 +++++------ 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index c19507c2f3c3e..7788ae2b88f21 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -6,7 +6,6 @@ use super::RegionVariableOrigin; use super::type_variable::TypeVariableOrigin; use std::ops::Range; -use rustc_data_structures::fx::FxHashMap; impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// This rather funky routine is used while processing expected @@ -102,10 +101,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Micro-optimization: if no variables have been created, then // `value` can't refer to any of them. =) So we can just return it. - if fudger.type_vars.is_empty() && + if fudger.type_vars.0.is_empty() && fudger.int_vars.is_empty() && fudger.float_vars.is_empty() && - fudger.region_vars.is_empty() { + fudger.region_vars.0.is_empty() { Ok(value) } else { Ok(value.fold_with(&mut fudger)) @@ -115,10 +114,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub struct InferenceFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - type_vars: FxHashMap, + type_vars: (Range, Vec), int_vars: Range, float_vars: Range, - region_vars: FxHashMap, + region_vars: (Range, Vec), } impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> { @@ -129,9 +128,11 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { match ty.sty { ty::Infer(ty::InferTy::TyVar(vid)) => { - if let Some(&origin) = self.type_vars.get(&vid) { + if self.type_vars.0.contains(&vid) { // This variable was created during the fudging. // Recreate it with a fresh variable here. + let idx = (vid.index - self.type_vars.0.start.index) as usize; + let origin = self.type_vars.1[idx]; self.infcx.next_ty_var(origin) } else { // This variable was created before the @@ -165,7 +166,9 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { if let ty::ReVar(vid) = r { - if let Some(&origin) = self.region_vars.get(&vid) { + if self.region_vars.0.contains(&vid) { + let idx = (vid.index() - self.region_vars.0.start.index()) as usize; + let origin = self.region_vars.1[idx]; return self.infcx.next_region_var(origin); } } diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index c3c4e724c6956..6a20d95cc3ad3 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -16,6 +16,7 @@ use crate::ty::{Region, RegionVid}; use std::collections::BTreeMap; use std::{cmp, fmt, mem, u32}; +use std::ops::Range; mod leak_check; @@ -843,13 +844,11 @@ impl<'tcx> RegionConstraintCollector<'tcx> { pub fn vars_since_snapshot( &self, mark: &RegionSnapshot, - ) -> FxHashMap { + ) -> (Range, Vec) { let range = self.unification_table.vars_since_snapshot(&mark.region_snapshot); - (range.start.index()..range.end.index()).map(|index| { - let vid = ty::RegionVid::from(index); - let origin = self.var_infos[vid].origin.clone(); - (vid, origin) - }).collect() + (range.clone(), (range.start.index()..range.end.index()).map(|index| { + self.var_infos[ty::RegionVid::from(index)].origin.clone() + }).collect()) } /// See [`RegionInference::region_constraints_added_in_snapshot`]. diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index cde695aefc10a..8a719ff2bf31c 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -5,7 +5,7 @@ use crate::ty::{self, Ty, TyVid}; use std::cmp; use std::marker::PhantomData; use std::u32; -use rustc_data_structures::fx::FxHashMap; +use std::ops::Range; use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::unify as ut; @@ -294,12 +294,11 @@ impl<'tcx> TypeVariableTable<'tcx> { pub fn vars_since_snapshot( &mut self, s: &Snapshot<'tcx>, - ) -> FxHashMap { + ) -> (Range, Vec) { let range = self.eq_relations.vars_since_snapshot(&s.eq_snapshot); - (range.start.vid.index..range.end.vid.index).map(|index| { - let origin = self.values.get(index as usize).origin.clone(); - (TyVid { index }, origin) - }).collect() + (range.start.vid..range.end.vid, (range.start.vid.index..range.end.vid.index).map(|index| { + self.values.get(index as usize).origin.clone() + }).collect()) } /// Finds the set of type variables that existed *before* `s`