From e502194e7e2605b461c3e24d30fdc5def4e1c166 Mon Sep 17 00:00:00 2001 From: Taylor Cramer Date: Fri, 15 Dec 2017 12:27:20 -0800 Subject: [PATCH] Refactor argument-position impl Trait --- src/librustc/hir/intravisit.rs | 3 - src/librustc/hir/lowering.rs | 83 +++++++++--- src/librustc/hir/mod.rs | 5 +- src/librustc/hir/print.rs | 3 - src/librustc/ich/impls_hir.rs | 1 - src/librustc/middle/resolve_lifetime.rs | 13 -- src/librustc_typeck/astconv.rs | 8 -- src/librustc_typeck/collect.rs | 155 ++++------------------ src/librustdoc/clean/mod.rs | 1 - src/libsyntax/print/pprust.rs | 2 +- src/test/run-pass/impl-trait/lifetimes.rs | 5 +- 11 files changed, 93 insertions(+), 186 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index eacad100f10..3a1b0b8c58e 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -602,9 +602,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_list!(visitor, visit_ty_param_bound, bounds); walk_list!(visitor, visit_lifetime, lifetimes); } - TyImplTraitUniversal(_, ref bounds) => { - walk_list!(visitor, visit_ty_param_bound, bounds); - } TyTypeof(expression) => { visitor.visit_nested_body(expression) } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index b544ea820c0..847cf64ce6a 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -61,6 +61,7 @@ use syntax::attr; use syntax::ast::*; use syntax::errors; use syntax::ext::hygiene::{Mark, SyntaxContext}; +use syntax::print::pprust; use syntax::ptr::P; use syntax::codemap::{self, respan, Spanned, CompilerDesugaringKind}; use syntax::std_inject; @@ -106,6 +107,13 @@ pub struct LoweringContext<'a> { is_in_loop_condition: bool, is_in_trait_impl: bool, + // 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 @@ -197,6 +205,7 @@ pub fn lower_crate(sess: &Session, 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(), @@ -526,20 +535,23 @@ impl<'a> LoweringContext<'a> { // Creates a new hir::LifetimeDef for every new lifetime encountered // while evaluating `f`. Definitions are created with the parent provided. // If no `parent_id` is provided, no definitions will be returned. - fn collect_in_band_lifetime_defs( + fn collect_in_band_defs( &mut self, parent_id: Option, f: F - ) -> (Vec, T) where F: FnOnce(&mut LoweringContext) -> T + ) -> (Vec, Vec, T) where F: FnOnce(&mut LoweringContext) -> T { assert!(!self.is_collecting_in_band_lifetimes); assert!(self.lifetimes_to_define.is_empty()); self.is_collecting_in_band_lifetimes = self.sess.features.borrow().in_band_lifetimes; + assert!(self.in_band_ty_params.is_empty()); + let res = f(self); self.is_collecting_in_band_lifetimes = false; + 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 lifetime_defs = match parent_id { @@ -569,7 +581,7 @@ impl<'a> LoweringContext<'a> { None => Vec::new(), }; - (lifetime_defs, res) + (in_band_ty_params, lifetime_defs, res) } // Evaluates `f` with the lifetimes in `lt_defs` in-scope. @@ -613,11 +625,9 @@ impl<'a> LoweringContext<'a> { res } - // Appends in-band lifetime defs to the existing set of out-of-band lifetime defs. - // Evaluates all within the context of the out-of-band defs. - // If provided, `impl_item_id` is used to find the parent impls of impl items so - // that their generics are not duplicated. - fn add_in_band_lifetime_defs( + // Appends in-band lifetime defs and argument-position `impl Trait` defs + // to the existing set of generics. + fn add_in_band_defs( &mut self, generics: &Generics, parent_id: Option, @@ -625,17 +635,23 @@ impl<'a> LoweringContext<'a> { ) -> (hir::Generics, T) where F: FnOnce(&mut LoweringContext) -> T { - let (in_band_defs, (mut lowered_generics, res)) = + let (in_band_ty_defs, in_band_lifetime_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(&generics.lifetimes, |this| { - this.collect_in_band_lifetime_defs(parent_id, |this| { + this.collect_in_band_defs(parent_id, |this| { (this.lower_generics(generics), f(this)) }) }); + lowered_generics.ty_params = + lowered_generics.ty_params + .iter().cloned() + .chain(in_band_ty_defs.into_iter()) + .collect(); + lowered_generics.lifetimes = lowered_generics.lifetimes .iter().cloned() - .chain(in_band_defs.into_iter()) + .chain(in_band_lifetime_defs.into_iter()) .collect(); (lowered_generics, res) @@ -922,6 +938,7 @@ impl<'a> LoweringContext<'a> { } TyKind::ImplTrait(ref bounds) => { use syntax::feature_gate::{emit_feature_err, GateIssue}; + let span = t.span; match itctx { ImplTraitContext::Existential => { let has_feature = self.sess.features.borrow().conservative_impl_trait; @@ -944,7 +961,7 @@ impl<'a> LoweringContext<'a> { id: self.next_id().node_id, predicates: Vec::new().into(), }, - span: t.span, + span, }, bounds: hir_bounds, }, lifetimes) @@ -956,7 +973,35 @@ impl<'a> LoweringContext<'a> { t.span, GateIssue::Language, "`impl Trait` in argument position is experimental"); } - hir::TyImplTraitUniversal(def_id, self.lower_bounds(bounds, itctx)) + + let def_node_id = self.next_id().node_id; + + // Add a definition for the in-band TyParam + let def_index = self.resolver.definitions().create_def_with_parent( + def_id.index, + def_node_id, + DefPathData::ImplTrait, + DefIndexAddressSpace::High, + Mark::root() + ); + + let hir_bounds = self.lower_bounds(bounds, itctx); + self.in_band_ty_params.push(hir::TyParam { + // Set the name to `impl Bound1 + Bound2` + name: Symbol::intern(&pprust::ty_to_string(t)), + id: def_node_id, + bounds: hir_bounds, + default: None, + span, + pure_wrt_drop: false, + synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), + }); + + hir::TyPath(hir::QPath::Resolved(None, P(hir::Path { + span, + def: Def::TyParam(DefId::local(def_index)), + segments: vec![].into(), + }))) }, ImplTraitContext::Disallowed => { span_err!(self.sess, t.span, E0562, @@ -1829,7 +1874,7 @@ impl<'a> LoweringContext<'a> { this.expr_block(body, ThinVec::new()) }); let (generics, fn_decl) = - this.add_in_band_lifetime_defs(generics, fn_def_id, |this| + this.add_in_band_defs(generics, fn_def_id, |this| this.lower_fn_decl(decl, fn_def_id, true)); hir::ItemFn(fn_decl, @@ -1883,7 +1928,7 @@ impl<'a> LoweringContext<'a> { ref impl_items) => { let def_id = self.resolver.definitions().opt_local_def_id(id); let (generics, (ifce, lowered_ty)) = - self.add_in_band_lifetime_defs(ast_generics, def_id, |this| { + self.add_in_band_defs(ast_generics, def_id, |this| { let ifce = ifce.as_ref().map(|trait_ref| { this.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed) }); @@ -2059,7 +2104,7 @@ impl<'a> LoweringContext<'a> { } TraitItemKind::Method(ref sig, None) => { let names = this.lower_fn_args_to_names(&sig.decl); - this.add_in_band_lifetime_defs(&i.generics, fn_def_id, |this| + this.add_in_band_defs(&i.generics, fn_def_id, |this| hir::TraitItemKind::Method( this.lower_method_sig(sig, fn_def_id, false), hir::TraitMethod::Required(names))) @@ -2070,7 +2115,7 @@ impl<'a> LoweringContext<'a> { this.expr_block(body, ThinVec::new()) }); - this.add_in_band_lifetime_defs(&i.generics, fn_def_id, |this| + this.add_in_band_defs(&i.generics, fn_def_id, |this| hir::TraitItemKind::Method( this.lower_method_sig(sig, fn_def_id, false), hir::TraitMethod::Provided(body_id))) @@ -2147,7 +2192,7 @@ impl<'a> LoweringContext<'a> { }); let impl_trait_return_allow = !this.is_in_trait_impl; - this.add_in_band_lifetime_defs(&i.generics, fn_def_id, |this| + this.add_in_band_defs(&i.generics, fn_def_id, |this| hir::ImplItemKind::Method( this.lower_method_sig(sig, fn_def_id, impl_trait_return_allow), body_id)) @@ -2280,7 +2325,7 @@ impl<'a> LoweringContext<'a> { ForeignItemKind::Fn(ref fdec, ref generics) => { // Disallow impl Trait in foreign items let (generics, (fn_dec, fn_args)) = - this.add_in_band_lifetime_defs( + this.add_in_band_defs( generics, Some(def_id), |this| ( diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index dc44a943e4c..f8da8145b0d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1506,7 +1506,7 @@ pub enum Ty_ { /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. TyTraitObject(HirVec, Lifetime), - /// An exsitentially quantified (there exists a type satisfying) `impl + /// An existentially quantified (there exists a type satisfying) `impl /// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime. /// /// The `ExistTy` structure emulates an @@ -1518,9 +1518,6 @@ pub enum Ty_ { /// because all in-scope type parameters are captured by `impl Trait`, /// so they are resolved directly through the parent `Generics`. TyImplTraitExistential(ExistTy, HirVec), - /// An universally quantified (for all types satisfying) `impl - /// Bound1 + Bound2 + Bound3` type where `Bound` is a trait or a lifetime. - TyImplTraitUniversal(DefId, TyParamBounds), /// Unused for now TyTypeof(BodyId), /// TyInfer means the type should be inferred instead of it having been diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index c7bb121e901..21e2b8233dc 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -424,9 +424,6 @@ impl<'a> State<'a> { hir::TyImplTraitExistential(ref existty, ref _lifetimes) => { self.print_bounds("impl", &existty.bounds[..])?; } - hir::TyImplTraitUniversal(_, ref bounds) => { - self.print_bounds("impl", &bounds[..])?; - } hir::TyArray(ref ty, v) => { self.s.word("[")?; self.print_type(&ty)?; diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index ff5327ced8b..02a394f9634 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -312,7 +312,6 @@ impl_stable_hash_for!(enum hir::Ty_ { TyPath(qpath), TyTraitObject(trait_refs, lifetime), TyImplTraitExistential(existty, lifetimes), - TyImplTraitUniversal(def_id, bounds), TyTypeof(body_id), TyErr, TyInfer diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 188dbe2f1de..93e850267b6 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -2146,19 +2146,6 @@ fn insert_late_bound_lifetimes( visit_where_predicate, &generics.where_clause.predicates ); - // We need to collect argument impl Trait lifetimes as well, - // we do so here. - walk_list!( - &mut appears_in_where_clause, - visit_ty, - decl.inputs - .iter() - .filter(|ty| if let hir::TyImplTraitUniversal(..) = ty.node { - true - } else { - false - }) - ); for lifetime_def in &generics.lifetimes { if !lifetime_def.bounds.is_empty() { // `'a: 'b` means both `'a` and `'b` are referenced diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6b37a30cb82..34c539795a1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -30,7 +30,6 @@ use util::nodemap::FxHashSet; use std::iter; use syntax::{abi, ast}; -use syntax::symbol::Symbol; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax_pos::Span; @@ -1050,13 +1049,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let def_id = tcx.hir.local_def_id(ast_ty.id); self.impl_trait_ty_to_ty(def_id, lifetimes) } - hir::TyImplTraitUniversal(fn_def_id, _) => { - let impl_trait_def_id = tcx.hir.local_def_id(ast_ty.id); - let generics = tcx.generics_of(fn_def_id); - let index = generics.type_param_to_index[&impl_trait_def_id.index]; - tcx.mk_param(index, - Symbol::intern(&tcx.hir.node_to_pretty_string(ast_ty.id))) - } hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => { debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path); let opt_self_ty = maybe_qself.as_ref().map(|qself| { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 3d4d8e65f69..f51bdf050c7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -43,7 +43,6 @@ use rustc_const_math::ConstInt; use std::collections::BTreeMap; use syntax::{abi, ast}; -use syntax::ptr::P; use syntax::codemap::Spanned; use syntax::symbol::{Symbol, keywords}; use syntax_pos::{Span, DUMMY_SP}; @@ -880,32 +879,22 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut allow_defaults = false; let no_generics = hir::Generics::empty(); - let (ast_generics, opt_inputs) = match node { - NodeTraitItem(item) => { - match item.node { - TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)), - _ => (&item.generics, None) - } - } + let ast_generics = match node { + NodeTraitItem(item) => &item.generics, - NodeImplItem(item) => { - match item.node { - ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)), - _ => (&item.generics, None) - } - } + NodeImplItem(item) => &item.generics, NodeItem(item) => { match item.node { - ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)), - ItemImpl(_, _, _, ref generics, ..) => (generics, None), + ItemFn(.., ref generics, _) | + ItemImpl(_, _, _, ref generics, ..) => generics, ItemTy(_, ref generics) | ItemEnum(_, ref generics) | ItemStruct(_, ref generics) | ItemUnion(_, ref generics) => { allow_defaults = true; - (generics, None) + generics } ItemTrait(_, _, ref generics, ..) | ItemTraitAlias(ref generics, ..) => { @@ -926,26 +915,26 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }); allow_defaults = true; - (generics, None) + generics } - _ => (&no_generics, None) + _ => &no_generics, } } NodeForeignItem(item) => { match item.node { - ForeignItemStatic(..) => (&no_generics, None), - ForeignItemFn(ref decl, _, ref generics) => (generics, Some(&decl.inputs)), - ForeignItemType => (&no_generics, None) + ForeignItemStatic(..) => &no_generics, + ForeignItemFn(_, _, ref generics) => generics, + ForeignItemType => &no_generics, } } NodeTy(&hir::Ty { node: hir::TyImplTraitExistential(ref exist_ty, _), .. }) => { - (&exist_ty.generics, None) + &exist_ty.generics } - _ => (&no_generics, None) + _ => &no_generics, }; let has_self = opt_self.is_some(); @@ -1003,23 +992,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }); - let fn_ins = opt_inputs.map(|tys| &tys[..]); - let univ_impl_trait_info = extract_universal_impl_trait_info(tcx, fn_ins); - let other_type_start = type_start + ast_generics.ty_params.len() as u32; - let mut types: Vec<_> = opt_self.into_iter() - .chain(types) - .chain(univ_impl_trait_info.iter().enumerate().map(|(i, info)| { - ty::TypeParameterDef { - index: other_type_start + i as u32, - name: Symbol::intern(&tcx.hir.node_to_pretty_string(info.id)), - def_id: info.def_id, - has_default: false, - object_lifetime_default: rl::Set1::Empty, - pure_wrt_drop: false, - synthetic: Some(SyntheticTyParamKind::ImplTrait), - } - })) - .collect(); + let mut types: Vec<_> = opt_self.into_iter().chain(types).collect(); // provide junk type parameter defs - the only place that // cares about anything but the length is instantiation, @@ -1419,50 +1392,36 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let icx = ItemCtxt::new(tcx, def_id); let no_generics = hir::Generics::empty(); - let (ast_generics, opt_inputs) = match node { - NodeTraitItem(item) => { - match item.node { - TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)), - _ => (&item.generics, None) - } - } - - NodeImplItem(item) => { - match item.node { - ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)), - _ => (&item.generics, None) - } - } + let ast_generics = match node { + NodeTraitItem(item) => &item.generics, + NodeImplItem(item) => &item.generics, NodeItem(item) => { match item.node { - ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)), - + ItemFn(.., ref generics, _) | ItemImpl(_, _, _, ref generics, ..) | ItemTy(_, ref generics) | ItemEnum(_, ref generics) | ItemStruct(_, ref generics) | - ItemUnion(_, ref generics) => { - (generics, None) - } + ItemUnion(_, ref generics) => generics, ItemTrait(_, _, ref generics, .., ref items) => { is_trait = Some((ty::TraitRef { def_id, substs: Substs::identity_for_item(tcx, def_id) }, items)); - (generics, None) + generics } - _ => (&no_generics, None) + _ => &no_generics, } } NodeForeignItem(item) => { match item.node { - ForeignItemStatic(..) => (&no_generics, None), - ForeignItemFn(ref decl, _, ref generics) => (generics, Some(&decl.inputs)), - ForeignItemType => (&no_generics, None), + ForeignItemStatic(..) => &no_generics, + ForeignItemFn(_, _, ref generics) => generics, + ForeignItemType => &no_generics, } } @@ -1491,7 +1450,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; } - _ => (&no_generics, None) + _ => &no_generics, }; let generics = tcx.generics_of(def_id); @@ -1622,19 +1581,6 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, })) } - // Add predicates from impl Trait arguments - let fn_ins = opt_inputs.map(|tys| &tys[..]); - let univ_impl_trait_info = extract_universal_impl_trait_info(tcx, fn_ins); - for info in univ_impl_trait_info.iter() { - let name = keywords::Invalid.name(); - let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); - index += 1; - let bounds = compute_bounds(&icx, param_ty, info.bounds, - SizedByDefault::Yes, - info.span); - predicates.extend(bounds.predicates(tcx, param_ty)); - } - // Subtle: before we store the predicates into the tcx, we // sort them so that predicates like `T: Foo` come // before uses of `U`. This avoids false ambiguity errors @@ -1795,54 +1741,3 @@ fn is_auto_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => bug!("is_auto_impl applied to non-local def-id {:?}", def_id) } } - -struct ImplTraitUniversalInfo<'hir> { - id: ast::NodeId, - def_id: DefId, - span: Span, - bounds: &'hir [hir::TyParamBound], -} - -/// Take some possible list of arguments and return the DefIds of the ImplTraitUniversal -/// arguments -fn extract_universal_impl_trait_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - opt_inputs: Option<&'tcx [P]>) - -> Vec> -{ - // A visitor for simply collecting Universally quantified impl Trait arguments - struct ImplTraitUniversalVisitor<'tcx> { - items: Vec<&'tcx hir::Ty> - } - - impl<'tcx> Visitor<'tcx> for ImplTraitUniversalVisitor<'tcx> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyImplTraitUniversal(..) = ty.node { - self.items.push(ty); - } - intravisit::walk_ty(self, ty); - } - } - - let mut visitor = ImplTraitUniversalVisitor { items: Vec::new() }; - - if let Some(inputs) = opt_inputs { - for t in inputs.iter() { - visitor.visit_ty(t); - } - } - - visitor.items.into_iter().map(|ty| if let hir::TyImplTraitUniversal(_, ref bounds) = ty.node { - ImplTraitUniversalInfo { - id: ty.id, - def_id: tcx.hir.local_def_id(ty.id), - span: ty.span, - bounds: bounds - } - } else { - span_bug!(ty.span, "this type should be a universally quantified impl trait. this is a bug") - }).collect() -} diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 91908de98a6..5f5ad952cf0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2133,7 +2133,6 @@ impl Clean for hir::Ty { } TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)), TyImplTraitExistential(ref exist_ty, ref _lts) => ImplTrait(exist_ty.bounds.clean(cx)), - TyImplTraitUniversal(_, ref bounds) => ImplTrait(bounds.clean(cx)), TyInfer | TyErr => Infer, TyTypeof(..) => panic!("Unimplemented type {:?}", self.node), } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e9386e5187f..2b8bd58c51a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1070,7 +1070,7 @@ impl<'a> State<'a> { self.print_bounds(prefix, &bounds[..])?; } ast::TyKind::ImplTrait(ref bounds) => { - self.print_bounds("impl ", &bounds[..])?; + self.print_bounds("impl", &bounds[..])?; } ast::TyKind::Array(ref ty, ref v) => { self.s.word("[")?; diff --git a/src/test/run-pass/impl-trait/lifetimes.rs b/src/test/run-pass/impl-trait/lifetimes.rs index 0f2f67fd89a..a56f083e08f 100644 --- a/src/test/run-pass/impl-trait/lifetimes.rs +++ b/src/test/run-pass/impl-trait/lifetimes.rs @@ -57,9 +57,8 @@ fn pass_through_elision_with_fn_path &u32>( x: &T ) -> impl Into<&impl Fn(&u32) -> &u32> { x } -// FIXME(cramertj) Currently ICEing, part of issue #46685: -// fn foo(x: &impl Debug) -> impl Into<&impl Debug> { x } -// Works: +fn foo(x: &impl Debug) -> impl Into<&impl Debug> { x } +fn foo_explicit_lifetime<'a>(x: &'a impl Debug) -> impl Into<&'a impl Debug> { x } fn foo_no_outer_impl(x: &impl Debug) -> &impl Debug { x } fn foo_explicit_arg(x: &T) -> impl Into<&impl Debug> { x }