diff options
| author | Oliver Schneider <github35764891676564198441@oli-obk.de> | 2018-06-19 13:47:53 +0200 |
|---|---|---|
| committer | Oliver Schneider <github35764891676564198441@oli-obk.de> | 2018-06-30 11:45:11 +0200 |
| commit | 7879369fa684cde8721e2fd966e7c87a46940b96 (patch) | |
| tree | 66ca517f1cd48946283861d87541f85dd7ca06b6 | |
| parent | 87005c0fd99e273d325f3b2cd2852271c974812b (diff) | |
| download | rust-7879369fa684cde8721e2fd966e7c87a46940b96.tar.gz rust-7879369fa684cde8721e2fd966e7c87a46940b96.zip | |
Remove some global state from the lowering pass
| -rw-r--r-- | src/librustc/hir/lowering.rs | 127 |
1 files changed, 76 insertions, 51 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 530733d5f83..8f2ce9a18ee 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -110,13 +110,6 @@ pub struct LoweringContext<'a> { /// written at all (e.g., `&T` or `std::cell::Ref<T>`). anonymous_lifetime_mode: AnonymousLifetimeMode, - // This is a list of in-band type definitions being generated by - // Argument-position `impl Trait`. - // When traversing a signature such as `fn foo(x: impl Trait)`, - // we record `impl Trait` as a new type parameter, then later - // add it on to `foo`s generics. - in_band_ty_params: Vec<hir::GenericParam>, - // Used to create lifetime definitions from in-band lifetime usages. // e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8` // When a named lifetime is encountered in a function or impl header and @@ -172,12 +165,14 @@ pub trait Resolver { ) -> hir::Path; } -#[derive(Clone, Copy, Debug)] -enum ImplTraitContext { +#[derive(Debug)] +enum ImplTraitContext<'a> { /// Treat `impl Trait` as shorthand for a new universal generic parameter. /// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually /// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`. - Universal, + /// + /// Newly generated parameters should be inserted into the given `Vec` + Universal(&'a mut Vec<hir::GenericParam>), /// Treat `impl Trait` as shorthand for a new universal existential parameter. /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually @@ -190,6 +185,17 @@ enum ImplTraitContext { Disallowed, } +impl<'a> ImplTraitContext<'a> { + fn reborrow(&'b mut self) -> ImplTraitContext<'b> { + use self::ImplTraitContext::*; + match self { + Universal(params) => Universal(params), + Existential(did) => Existential(*did), + Disallowed => Disallowed, + } + } +} + pub fn lower_crate( sess: &Session, cstore: &CrateStore, @@ -224,7 +230,6 @@ pub fn lower_crate( node_id_to_hir_id: IndexVec::new(), is_generator: false, is_in_trait_impl: false, - in_band_ty_params: Vec::new(), lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, in_scope_lifetimes: Vec::new(), @@ -645,7 +650,7 @@ impl<'a> LoweringContext<'a> { f: F, ) -> (Vec<hir::GenericParam>, T) where - F: FnOnce(&mut LoweringContext) -> T, + F: FnOnce(&mut LoweringContext) -> (Vec<hir::GenericParam>, T), { assert!(!self.is_collecting_in_band_lifetimes); assert!(self.lifetimes_to_define.is_empty()); @@ -656,13 +661,11 @@ impl<'a> LoweringContext<'a> { self.anonymous_lifetime_mode = anonymous_lifetime_mode; } - assert!(self.in_band_ty_params.is_empty()); - let res = f(self); + let (in_band_ty_params, res) = f(self); self.is_collecting_in_band_lifetimes = false; self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; - let in_band_ty_params = self.in_band_ty_params.split_off(0); let lifetimes_to_define = self.lifetimes_to_define.split_off(0); let params = lifetimes_to_define @@ -796,14 +799,19 @@ impl<'a> LoweringContext<'a> { f: F, ) -> (hir::Generics, T) where - F: FnOnce(&mut LoweringContext) -> T, + F: FnOnce(&mut LoweringContext, &mut Vec<hir::GenericParam>) -> T, { let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs( &generics.params, |this| { - let itctx = ImplTraitContext::Universal; this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| { - (this.lower_generics(generics, itctx), f(this)) + let mut params = Vec::new(); + let generics = this.lower_generics( + generics, + ImplTraitContext::Universal(&mut params), + ); + let res = f(this, &mut params); + (params, (generics, res)) }) }, ); @@ -1069,7 +1077,7 @@ impl<'a> LoweringContext<'a> { P(self.lower_ty_direct(t, itctx)) } - fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty { + fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext) -> hir::Ty { let kind = match t.node { TyKind::Infer => hir::TyInfer, TyKind::Err => hir::TyErr, @@ -1106,7 +1114,9 @@ impl<'a> LoweringContext<'a> { ), TyKind::Never => hir::TyNever, TyKind::Tup(ref tys) => { - hir::TyTup(tys.iter().map(|ty| self.lower_ty_direct(ty, itctx)).collect()) + hir::TyTup(tys.iter().map(|ty| { + self.lower_ty_direct(ty, itctx.reborrow()) + }).collect()) } TyKind::Paren(ref ty) => { return self.lower_ty_direct(ty, itctx); @@ -1140,7 +1150,7 @@ impl<'a> LoweringContext<'a> { .iter() .filter_map(|bound| match *bound { GenericBound::Trait(ref ty, TraitBoundModifier::None) => { - Some(self.lower_poly_trait_ref(ty, itctx)) + Some(self.lower_poly_trait_ref(ty, itctx.reborrow())) } GenericBound::Trait(_, TraitBoundModifier::Maybe) => None, GenericBound::Outlives(ref lifetime) => { @@ -1167,7 +1177,7 @@ impl<'a> LoweringContext<'a> { |this| this.lower_param_bounds(bounds, itctx), ) } - ImplTraitContext::Universal => { + ImplTraitContext::Universal(in_band_ty_params) => { self.lower_node_id(def_node_id); // Add a definition for the in-band TyParam let def_index = self @@ -1176,10 +1186,13 @@ impl<'a> LoweringContext<'a> { .opt_def_index(def_node_id) .unwrap(); - let hir_bounds = self.lower_param_bounds(bounds, itctx); + let hir_bounds = self.lower_param_bounds( + bounds, + ImplTraitContext::Universal(in_band_ty_params), + ); // Set the name to `impl Bound1 + Bound2` let ident = Ident::from_str(&pprust::ty_to_string(t)).with_span_pos(span); - self.in_band_ty_params.push(hir::GenericParam { + in_band_ty_params.push(hir::GenericParam { id: def_node_id, name: ParamName::Plain(ident), pure_wrt_drop: false, @@ -1502,10 +1515,10 @@ impl<'a> LoweringContext<'a> { qself: &Option<QSelf>, p: &Path, param_mode: ParamMode, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext, ) -> hir::QPath { let qself_position = qself.as_ref().map(|q| q.position); - let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); + let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow())); let resolution = self.resolver .get_resolution(id) @@ -1592,7 +1605,7 @@ impl<'a> LoweringContext<'a> { param_mode, num_lifetimes, parenthesized_generic_args, - itctx, + itctx.reborrow(), ) }) .collect(), @@ -1635,7 +1648,7 @@ impl<'a> LoweringContext<'a> { param_mode, 0, ParenthesizedGenericArgs::Warn, - itctx, + itctx.reborrow(), )); let qpath = hir::QPath::TypeRelative(ty, segment); @@ -1752,7 +1765,7 @@ impl<'a> LoweringContext<'a> { &mut self, data: &AngleBracketedArgs, param_mode: ParamMode, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext, ) -> (hir::GenericArgs, bool) { let &AngleBracketedArgs { ref args, ref bindings, .. } = data; let has_types = args.iter().any(|arg| match arg { @@ -1760,8 +1773,8 @@ impl<'a> LoweringContext<'a> { _ => false, }); (hir::GenericArgs { - args: args.iter().map(|a| self.lower_generic_arg(a, itctx)).collect(), - bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx)).collect(), + args: args.iter().map(|a| self.lower_generic_arg(a, itctx.reborrow())).collect(), + bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx.reborrow())).collect(), parenthesized: false, }, !has_types && param_mode == ParamMode::Optional) @@ -1866,15 +1879,15 @@ impl<'a> LoweringContext<'a> { fn lower_fn_decl( &mut self, decl: &FnDecl, - fn_def_id: Option<DefId>, + mut in_band_ty_params: Option<(DefId, &mut Vec<hir::GenericParam>)>, impl_trait_return_allow: bool, make_ret_async: Option<NodeId>, ) -> P<hir::FnDecl> { let inputs = decl.inputs .iter() .map(|arg| { - if fn_def_id.is_some() { - self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal) + if let Some((_, ref mut ibty)) = in_band_ty_params { + self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(ibty)) } else { self.lower_ty_direct(&arg.ty, ImplTraitContext::Disallowed) } @@ -1883,11 +1896,15 @@ impl<'a> LoweringContext<'a> { let output = if let Some(ret_id) = make_ret_async { self.lower_async_fn_ret_ty( - &inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"), ret_id) + &inputs, + &decl.output, + in_band_ty_params.expect("make_ret_async but no fn_def_id").0, + ret_id, + ) } else { match decl.output { - FunctionRetTy::Ty(ref ty) => match fn_def_id { - Some(def_id) if impl_trait_return_allow => { + FunctionRetTy::Ty(ref ty) => match in_band_ty_params { + Some((def_id, _)) if impl_trait_return_allow => { hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(def_id))) } _ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)), @@ -2191,17 +2208,19 @@ impl<'a> LoweringContext<'a> { &mut self, params: &Vec<GenericParam>, add_bounds: &NodeMap<Vec<GenericBound>>, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext, ) -> hir::HirVec<hir::GenericParam> { - params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect() + params.iter().map(|param| { + self.lower_generic_param(param, add_bounds, itctx.reborrow()) + }).collect() } fn lower_generic_param(&mut self, param: &GenericParam, add_bounds: &NodeMap<Vec<GenericBound>>, - itctx: ImplTraitContext) + mut itctx: ImplTraitContext) -> hir::GenericParam { - let mut bounds = self.lower_param_bounds(¶m.bounds, itctx); + let mut bounds = self.lower_param_bounds(¶m.bounds, itctx.reborrow()); match param.kind { GenericParamKind::Lifetime => { let was_collecting_in_band = self.is_collecting_in_band_lifetimes; @@ -2238,8 +2257,9 @@ impl<'a> LoweringContext<'a> { let add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x); if !add_bounds.is_empty() { + let params = self.lower_param_bounds(add_bounds, itctx.reborrow()).into_iter(); bounds = bounds.into_iter() - .chain(self.lower_param_bounds(add_bounds, itctx).into_iter()) + .chain(params) .collect(); } @@ -2434,10 +2454,10 @@ impl<'a> LoweringContext<'a> { fn lower_poly_trait_ref( &mut self, p: &PolyTraitRef, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext, ) -> hir::PolyTraitRef { let bound_generic_params = - self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx); + self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx.reborrow()); let trait_ref = self.with_parent_impl_lifetime_defs( &bound_generic_params, |this| this.lower_trait_ref(&p.trait_ref, itctx), @@ -2482,9 +2502,9 @@ impl<'a> LoweringContext<'a> { } } - fn lower_param_bounds(&mut self, bounds: &[GenericBound], itctx: ImplTraitContext) + fn lower_param_bounds(&mut self, bounds: &[GenericBound], mut itctx: ImplTraitContext) -> hir::GenericBounds { - bounds.iter().map(|bound| self.lower_param_bound(bound, itctx)).collect() + bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect() } fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> { @@ -2585,8 +2605,8 @@ impl<'a> LoweringContext<'a> { generics, fn_def_id, AnonymousLifetimeMode::PassThrough, - |this| this.lower_fn_decl( - decl, Some(fn_def_id), true, header.asyncness.opt_return_id()) + |this, idty| this.lower_fn_decl( + decl, Some((fn_def_id, idty)), true, header.asyncness.opt_return_id()), ); hir::ItemFn( @@ -2656,7 +2676,7 @@ impl<'a> LoweringContext<'a> { ast_generics, def_id, AnonymousLifetimeMode::CreateParameter, - |this| { + |this, _| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed) }); @@ -3191,7 +3211,7 @@ impl<'a> LoweringContext<'a> { generics, def_id, AnonymousLifetimeMode::PassThrough, - |this| { + |this, _| { ( // Disallow impl Trait in foreign items this.lower_fn_decl(fdec, None, false, None), @@ -3226,7 +3246,12 @@ impl<'a> LoweringContext<'a> { generics, fn_def_id, AnonymousLifetimeMode::PassThrough, - |cx| cx.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow, is_async), + |this, idty| this.lower_fn_decl( + &sig.decl, + Some((fn_def_id, idty)), + impl_trait_return_allow, + is_async, + ), ); (generics, hir::MethodSig { header, decl }) } |
