From 82091d421a06db8e37a20bbbfbc017416fea2a0c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 27 Jun 2018 17:32:48 +0200 Subject: [PATCH 1/4] Deduplicate `IsAsync::Async` match --- src/librustc/hir/lowering.rs | 52 +++++++++++++++++------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 0bd5b6b627fe1..c4d8100a1ca8a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2520,6 +2520,28 @@ impl<'a> LoweringContext<'a> { }) } + fn lower_async_body( + &mut self, + decl: &FnDecl, + asyncness: IsAsync, + body: &Block, + ) -> hir::BodyId { + self.lower_body(Some(decl), |this| { + if let IsAsync::Async(async_node_id) = asyncness { + let async_expr = this.make_async_expr( + CaptureBy::Value, async_node_id, None, + |this| { + let body = this.lower_block(body, false); + this.expr_block(body, ThinVec::new()) + }); + this.expr(body.span, async_expr, ThinVec::new()) + } else { + let body = this.lower_block(body, false); + this.expr_block(body, ThinVec::new()) + } + }) + } + fn lower_item_kind( &mut self, id: NodeId, @@ -2559,20 +2581,7 @@ impl<'a> LoweringContext<'a> { // `impl Future` here because lower_body // only cares about the input argument patterns in the function // declaration (decl), not the return types. - let body_id = this.lower_body(Some(decl), |this| { - if let IsAsync::Async { closure_id, .. } = header.asyncness { - let async_expr = this.make_async_expr( - CaptureBy::Value, closure_id, None, - |this| { - let body = this.lower_block(body, false); - this.expr_block(body, ThinVec::new()) - }); - this.expr(body.span, async_expr, ThinVec::new()) - } else { - let body = this.lower_block(body, false); - this.expr_block(body, ThinVec::new()) - } - }); + let body_id = this.lower_async_body(decl, header.asyncness, body); let (generics, fn_decl) = this.add_in_band_defs( generics, @@ -2990,20 +2999,7 @@ impl<'a> LoweringContext<'a> { ) } ImplItemKind::Method(ref sig, ref body) => { - let body_id = self.lower_body(Some(&sig.decl), |this| { - if let IsAsync::Async { closure_id, .. } = sig.header.asyncness { - let async_expr = this.make_async_expr( - CaptureBy::Value, closure_id, None, - |this| { - let body = this.lower_block(body, false); - this.expr_block(body, ThinVec::new()) - }); - this.expr(body.span, async_expr, ThinVec::new()) - } else { - let body = this.lower_block(body, false); - this.expr_block(body, ThinVec::new()) - } - }); + let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness, body); let impl_trait_return_allow = !self.is_in_trait_impl; self.add_in_band_defs( From 6641233b34fd910864131febb22f71777a7add6a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 19 Jun 2018 10:09:00 +0200 Subject: [PATCH 2/4] Reduce repetition around `lower_method_sig` --- src/librustc/hir/lowering.rs | 67 ++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 38 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index c4d8100a1ca8a..30537f41178e7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2905,17 +2905,14 @@ impl<'a> LoweringContext<'a> { ), TraitItemKind::Method(ref sig, None) => { let names = self.lower_fn_args_to_names(&sig.decl); - self.add_in_band_defs( + let (generics, sig) = self.lower_method_sig( &i.generics, + sig, trait_item_def_id, - AnonymousLifetimeMode::PassThrough, - |this| { - hir::TraitItemKind::Method( - this.lower_method_sig(sig, trait_item_def_id, false, None), - hir::TraitMethod::Required(names), - ) - }, - ) + false, + None, + ); + (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } TraitItemKind::Method(ref sig, Some(ref body)) => { let body_id = self.lower_body(Some(&sig.decl), |this| { @@ -2923,17 +2920,15 @@ impl<'a> LoweringContext<'a> { this.expr_block(body, ThinVec::new()) }); - self.add_in_band_defs( + let (generics, sig) = self.lower_method_sig( &i.generics, + sig, trait_item_def_id, - AnonymousLifetimeMode::PassThrough, - |this| { - hir::TraitItemKind::Method( - this.lower_method_sig(sig, trait_item_def_id, false, None), - hir::TraitMethod::Provided(body_id), - ) - }, - ) + false, + None, + ); + + (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id))) } TraitItemKind::Type(ref bounds, ref default) => ( self.lower_generics(&i.generics, ImplTraitContext::Disallowed), @@ -3001,23 +2996,14 @@ impl<'a> LoweringContext<'a> { ImplItemKind::Method(ref sig, ref body) => { let body_id = self.lower_async_body(&sig.decl, sig.header.asyncness, body); let impl_trait_return_allow = !self.is_in_trait_impl; - - self.add_in_band_defs( + let (generics, sig) = self.lower_method_sig( &i.generics, + sig, impl_item_def_id, - AnonymousLifetimeMode::PassThrough, - |this| { - hir::ImplItemKind::Method( - this.lower_method_sig( - sig, - impl_item_def_id, - impl_trait_return_allow, - sig.header.asyncness.opt_return_id(), - ), - body_id, - ) - }, - ) + impl_trait_return_allow, + sig.header.asyncness.opt_return_id(), + ); + (generics, hir::ImplItemKind::Method(sig, body_id)) } ImplItemKind::Type(ref ty) => ( self.lower_generics(&i.generics, ImplTraitContext::Disallowed), @@ -3231,15 +3217,20 @@ impl<'a> LoweringContext<'a> { fn lower_method_sig( &mut self, + generics: &Generics, sig: &MethodSig, fn_def_id: DefId, impl_trait_return_allow: bool, is_async: Option, - ) -> hir::MethodSig { - hir::MethodSig { - header: self.lower_fn_header(sig.header), - decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow, is_async), - } + ) -> (hir::Generics, hir::MethodSig) { + let header = self.lower_fn_header(sig.header); + let (generics, decl) = self.add_in_band_defs( + generics, + fn_def_id, + AnonymousLifetimeMode::PassThrough, + |cx| cx.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow, is_async), + ); + (generics, hir::MethodSig { header, decl }) } fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto { From 87005c0fd99e273d325f3b2cd2852271c974812b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 28 Jun 2018 14:31:46 +0200 Subject: [PATCH 3/4] Remove unused field --- src/librustc/hir/lowering.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 30537f41178e7..530733d5f837e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -177,9 +177,7 @@ enum ImplTraitContext { /// 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(x: T)`. - /// - /// We store a DefId here so we can look up necessary information later - Universal(DefId), + Universal, /// Treat `impl Trait` as shorthand for a new universal existential parameter. /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually @@ -803,7 +801,7 @@ impl<'a> LoweringContext<'a> { let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs( &generics.params, |this| { - let itctx = ImplTraitContext::Universal(parent_id); + let itctx = ImplTraitContext::Universal; this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| { (this.lower_generics(generics, itctx), f(this)) }) @@ -1169,7 +1167,7 @@ impl<'a> LoweringContext<'a> { |this| this.lower_param_bounds(bounds, itctx), ) } - ImplTraitContext::Universal(_def_id) => { + ImplTraitContext::Universal => { self.lower_node_id(def_node_id); // Add a definition for the in-band TyParam let def_index = self @@ -1875,8 +1873,8 @@ impl<'a> LoweringContext<'a> { let inputs = decl.inputs .iter() .map(|arg| { - if let Some(def_id) = fn_def_id { - self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(def_id)) + if fn_def_id.is_some() { + self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal) } else { self.lower_ty_direct(&arg.ty, ImplTraitContext::Disallowed) } @@ -2527,9 +2525,9 @@ impl<'a> LoweringContext<'a> { body: &Block, ) -> hir::BodyId { self.lower_body(Some(decl), |this| { - if let IsAsync::Async(async_node_id) = asyncness { + if let IsAsync::Async { closure_id, .. } = asyncness { let async_expr = this.make_async_expr( - CaptureBy::Value, async_node_id, None, + CaptureBy::Value, closure_id, None, |this| { let body = this.lower_block(body, false); this.expr_block(body, ThinVec::new()) From 7879369fa684cde8721e2fd966e7c87a46940b96 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 19 Jun 2018 13:47:53 +0200 Subject: [PATCH 4/4] Remove some global state from the lowering pass --- src/librustc/hir/lowering.rs | 127 +++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 51 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 530733d5f837e..8f2ce9a18eef4 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`). 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, - // 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(x: T)`. - Universal, + /// + /// Newly generated parameters should be inserted into the given `Vec` + Universal(&'a mut Vec), /// 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, T) where - F: FnOnce(&mut LoweringContext) -> T, + F: FnOnce(&mut LoweringContext) -> (Vec, 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) -> 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, 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, + mut in_band_ty_params: Option<(DefId, &mut Vec)>, impl_trait_return_allow: bool, make_ret_async: Option, ) -> P { 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, add_bounds: &NodeMap>, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext, ) -> hir::HirVec { - 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>, - 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 { @@ -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 }) }