From d5d5f59e5e0c4c2a2fc1a8e80a2e6557caad6b26 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Mar 2018 07:49:06 -0400 Subject: [PATCH 1/5] do not give ownership of the `InferCtxt` away --- src/librustc/infer/mod.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index fe919775da0b4..1cc5eee07a289 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -430,7 +430,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { } pub fn enter(&'tcx mut self, f: F) -> R - where F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R + where F: for<'b> FnOnce(&InferCtxt<'b, 'gcx, 'tcx>) -> R { let InferCtxtBuilder { global_tcx, @@ -438,7 +438,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { ref fresh_tables, } = *self; let in_progress_tables = fresh_tables.as_ref(); - global_tcx.enter_local(arena, |tcx| f(InferCtxt { + global_tcx.enter_local(arena, |tcx| f(&InferCtxt { tcx, in_progress_tables, projection_cache: RefCell::new(traits::ProjectionCache::new()), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 18de8d1bee74e..a8a5724eb92d8 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -189,7 +189,7 @@ impl<'a, 'tcx> MaybeInProgressTables<'a, 'tcx> { /// `bar()` will each have their own `FnCtxt`, but they will /// share the inherited fields. pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - infcx: InferCtxt<'a, 'gcx, 'tcx>, + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, tables: MaybeInProgressTables<'a, 'tcx>, @@ -620,7 +620,7 @@ impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { - fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self { + fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, def_id: DefId) -> Self { let tcx = infcx.tcx; let item_id = tcx.hir.as_local_node_id(def_id); let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id)); From e5bbb5dce28128ce760e94b8420886c430505845 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sun, 11 Mar 2018 07:50:49 -0400 Subject: [PATCH 2/5] modernize the `enter` signature --- src/librustc/infer/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 1cc5eee07a289..52d868c7dc934 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -429,9 +429,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { self } - pub fn enter(&'tcx mut self, f: F) -> R - where F: for<'b> FnOnce(&InferCtxt<'b, 'gcx, 'tcx>) -> R - { + pub fn enter(&'tcx mut self, f: impl FnOnce(&InferCtxt<'_, 'gcx, 'tcx>) -> R) -> R { let InferCtxtBuilder { global_tcx, ref arena, From f1f209d25285466c56366e855df3dbfd1652a35f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 12 Mar 2018 04:43:19 -0400 Subject: [PATCH 3/5] remove `'tcx` from signature of `InferCtxtBuilder` and friends --- src/librustc/infer/mod.rs | 25 +++++++++++++------------ src/librustc_typeck/check/mod.rs | 15 ++++++++------- src/librustc_typeck/check/wfcheck.rs | 25 +++++++++++++------------ src/librustc_typeck/lib.rs | 2 ++ 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 52d868c7dc934..a7997a291d201 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -404,41 +404,42 @@ impl fmt::Display for FixupError { /// Helper type of a temporary returned by tcx.infer_ctxt(). /// Necessary because we can't write the following bound: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>). -pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { +pub struct InferCtxtBuilder<'a, 'gcx: 'a> { global_tcx: TyCtxt<'a, 'gcx, 'gcx>, arena: DroplessArena, - fresh_tables: Option>>, + fresh_table_owner: Option, } -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> { - pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { +impl<'a, 'gcx> TyCtxt<'a, 'gcx, 'gcx> { + pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx> { InferCtxtBuilder { global_tcx: self, arena: DroplessArena::new(), - fresh_tables: None, - + fresh_table_owner: None, } } } -impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { +impl<'a, 'gcx> InferCtxtBuilder<'a, 'gcx> { /// Used only by `rustc_typeck` during body type-checking/inference, /// will initialize `in_progress_tables` with fresh `TypeckTables`. pub fn with_fresh_in_progress_tables(mut self, table_owner: DefId) -> Self { - self.fresh_tables = Some(RefCell::new(ty::TypeckTables::empty(Some(table_owner)))); + self.fresh_table_owner = Some(table_owner); self } - pub fn enter(&'tcx mut self, f: impl FnOnce(&InferCtxt<'_, 'gcx, 'tcx>) -> R) -> R { + pub fn enter<'tcx, R>(&'tcx mut self, f: impl FnOnce(&InferCtxt<'_, 'gcx, 'tcx>) -> R) -> R { let InferCtxtBuilder { global_tcx, ref arena, - ref fresh_tables, + fresh_table_owner, } = *self; - let in_progress_tables = fresh_tables.as_ref(); + let in_progress_tables = fresh_table_owner.map(|table_owner| { + RefCell::new(ty::TypeckTables::empty(Some(table_owner))) + }); global_tcx.enter_local(arena, |tcx| f(&InferCtxt { tcx, - in_progress_tables, + in_progress_tables: in_progress_tables.as_ref(), projection_cache: RefCell::new(traits::ProjectionCache::new()), type_variables: RefCell::new(type_variable::TypeVariableTable::new()), int_unification_table: RefCell::new(ut::UnificationTable::new()), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a8a5724eb92d8..63ce4142ed677 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -587,14 +587,14 @@ impl<'a, 'gcx, 'tcx> Deref for FnCtxt<'a, 'gcx, 'tcx> { /// Helper type of a temporary returned by Inherited::build(...). /// Necessary because we can't write the following bound: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(Inherited<'b, 'gcx, 'tcx>). -pub struct InheritedBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - infcx: infer::InferCtxtBuilder<'a, 'gcx, 'tcx>, +pub struct InheritedBuilder<'a, 'gcx: 'a> { + infcx: infer::InferCtxtBuilder<'a, 'gcx>, def_id: DefId, } impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { pub fn build(tcx: TyCtxt<'a, 'gcx, 'gcx>, def_id: DefId) - -> InheritedBuilder<'a, 'gcx, 'tcx> { + -> InheritedBuilder<'a, 'gcx> { let hir_id_root = if def_id.is_local() { let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); let hir_id = tcx.hir.definitions().node_to_hir_id(node_id); @@ -610,10 +610,11 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { } } -impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> { - fn enter(&'tcx mut self, f: F) -> R - where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R - { +impl<'a, 'gcx> InheritedBuilder<'a, 'gcx> { + fn enter<'tcx, R>( + &'tcx mut self, + f: impl FnOnce(Inherited<'_, 'gcx, 'tcx>) -> R, + ) -> R { let def_id = self.def_id; self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id))) } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index d10ee358e0728..dd70f1c39372d 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -34,19 +34,22 @@ pub struct CheckTypeWellFormedVisitor<'a, 'tcx:'a> { /// Helper type of a temporary returned by .for_item(...). /// Necessary because we can't write the following bound: /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>). -struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { - inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>, +struct CheckWfFcxBuilder<'a, 'gcx: 'a> { + inherited: super::InheritedBuilder<'a, 'gcx>, code: ObligationCauseCode<'gcx>, id: ast::NodeId, span: Span, - param_env: ty::ParamEnv<'tcx>, + param_env: ty::ParamEnv<'gcx>, } -impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { - fn with_fcx(&'tcx mut self, f: F) where - F: for<'b> FnOnce(&FnCtxt<'b, 'gcx, 'tcx>, - &mut CheckTypeWellFormedVisitor<'b, 'gcx>) -> Vec> - { +impl<'a, 'gcx> CheckWfFcxBuilder<'a, 'gcx> { + fn with_fcx<'tcx>( + &'tcx mut self, + f: impl for<'b> FnOnce( + &FnCtxt<'b, 'gcx, 'tcx>, + &mut CheckTypeWellFormedVisitor<'b, 'gcx>, + ) -> Vec>, + ) { let code = self.code.clone(); let id = self.id; let span = self.span; @@ -203,13 +206,11 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { }) } - fn for_item<'tcx>(&self, item: &hir::Item) - -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { + fn for_item(&self, item: &hir::Item) -> CheckWfFcxBuilder<'a, 'gcx> { self.for_id(item.id, item.span) } - fn for_id<'tcx>(&self, id: ast::NodeId, span: Span) - -> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { + fn for_id(&self, id: ast::NodeId, span: Span) -> CheckWfFcxBuilder<'a, 'gcx> { let def_id = self.tcx.hir.local_def_id(id); CheckWfFcxBuilder { inherited: Inherited::build(self.tcx, def_id), diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 964c0021133aa..342721ff4d973 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -88,6 +88,8 @@ This API is completely unstable and subject to change. #![feature(slice_patterns)] #![feature(i128_type)] #![cfg_attr(stage0, feature(never_type))] +#![feature(underscore_lifetimes)] +#![feature(universal_impl_trait)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; From c85027431903c9d3012349bc8c4c8b3426497891 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 12 Mar 2018 05:07:42 -0400 Subject: [PATCH 4/5] adopt `impl Trait` for `tls::enter` --- src/librustc/ty/context.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index fd3465f59ebf2..0f72452df29c3 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1671,11 +1671,11 @@ pub mod tls { }) } - pub fn enter<'a, 'gcx: 'tcx, 'tcx, F, R>(gcx: &'a GlobalCtxt<'gcx>, - interners: &'a CtxtInterners<'tcx>, - f: F) -> R - where F: FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R - { + pub fn enter<'a, 'gcx: 'tcx, 'tcx, R>( + gcx: &'a GlobalCtxt<'gcx>, + interners: &'a CtxtInterners<'tcx>, + f: impl FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R, + ) -> R { let gcx_ptr = gcx as *const _ as *const ThreadLocalGlobalCtxt; let interners_ptr = interners as *const _ as *const ThreadLocalInterners; TLS_TCX.with(|tls| { From 84252f672303cbc2c5eaf9be2817356e5bfdeb16 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 14 Mar 2018 06:15:49 -0400 Subject: [PATCH 5/5] make Inherited builder give by reference --- src/librustc_typeck/check/mod.rs | 4 ++-- src/librustc_typeck/check/wfcheck.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 63ce4142ed677..5bfa7d0a1643d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -613,10 +613,10 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { impl<'a, 'gcx> InheritedBuilder<'a, 'gcx> { fn enter<'tcx, R>( &'tcx mut self, - f: impl FnOnce(Inherited<'_, 'gcx, 'tcx>) -> R, + f: impl FnOnce(&Inherited<'_, 'gcx, 'tcx>) -> R, ) -> R { let def_id = self.def_id; - self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id))) + self.infcx.enter(|infcx| f(&Inherited::new(infcx, def_id))) } } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index dd70f1c39372d..da82fbdabbc15 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -55,7 +55,7 @@ impl<'a, 'gcx> CheckWfFcxBuilder<'a, 'gcx> { let span = self.span; let param_env = self.param_env; self.inherited.enter(|inh| { - let fcx = FnCtxt::new(&inh, param_env, id); + let fcx = FnCtxt::new(inh, param_env, id); let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor { tcx: fcx.tcx.global_tcx(), code,