diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f24a803bac317..6dd339ccdcc6b 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -594,6 +594,18 @@ impl<'a> LoweringContext<'a> { span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } + fn with_anonymous_lifetime_mode( + &mut self, + anonymous_lifetime_mode: AnonymousLifetimeMode, + op: impl FnOnce(&mut Self) -> R, + ) -> R { + let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode; + self.anonymous_lifetime_mode = anonymous_lifetime_mode; + let result = op(self); + self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; + result + } + /// Creates a new hir::GenericParam for every new lifetime and /// type parameter encountered while evaluating `f`. Definitions /// are created with the parent provided. If no `parent_id` is @@ -1021,17 +1033,22 @@ impl<'a> LoweringContext<'a> { _ => None, }), |this| { - hir::TyBareFn(P(hir::BareFnTy { - generic_params: this.lower_generic_params( - &f.generic_params, - &NodeMap(), - ImplTraitContext::Disallowed, - ), - unsafety: this.lower_unsafety(f.unsafety), - abi: f.abi, - decl: this.lower_fn_decl(&f.decl, None, false), - arg_names: this.lower_fn_args_to_names(&f.decl), - })) + this.with_anonymous_lifetime_mode( + AnonymousLifetimeMode::PassThrough, + |this| { + hir::TyBareFn(P(hir::BareFnTy { + generic_params: this.lower_generic_params( + &f.generic_params, + &NodeMap(), + ImplTraitContext::Disallowed, + ), + unsafety: this.lower_unsafety(f.unsafety), + abi: f.abi, + decl: this.lower_fn_decl(&f.decl, None, false), + arg_names: this.lower_fn_args_to_names(&f.decl), + })) + }, + ) }, ), TyKind::Never => hir::TyNever, @@ -1620,44 +1637,54 @@ impl<'a> LoweringContext<'a> { &mut self, data: &ParenthesizedParameterData, ) -> (hir::PathParameters, bool) { - const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed; - let &ParenthesizedParameterData { - ref inputs, - ref output, - span, - } = data; - let inputs = inputs - .iter() - .map(|ty| self.lower_ty(ty, DISALLOWED)) - .collect(); - let mk_tup = |this: &mut Self, tys, span| { - let LoweredNodeId { node_id, hir_id } = this.next_id(); - P(hir::Ty { - node: hir::TyTup(tys), - id: node_id, - hir_id, - span, - }) - }; + // Switch to `PassThrough` mode for anonymous lifetimes: this + // means that we permit things like `&Ref`, where `Ref` has + // a hidden lifetime parameter. This is needed for backwards + // compatibility, even in contexts like an impl header where + // we generally don't permit such things (see #51008). + self.with_anonymous_lifetime_mode( + AnonymousLifetimeMode::PassThrough, + |this| { + const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed; + let &ParenthesizedParameterData { + ref inputs, + ref output, + span, + } = data; + let inputs = inputs + .iter() + .map(|ty| this.lower_ty(ty, DISALLOWED)) + .collect(); + let mk_tup = |this: &mut Self, tys, span| { + let LoweredNodeId { node_id, hir_id } = this.next_id(); + P(hir::Ty { + node: hir::TyTup(tys), + id: node_id, + hir_id, + span, + }) + }; - ( - hir::PathParameters { - lifetimes: hir::HirVec::new(), - types: hir_vec![mk_tup(self, inputs, span)], - bindings: hir_vec![ - hir::TypeBinding { - id: self.next_id().node_id, - name: Symbol::intern(FN_OUTPUT_NAME), - ty: output - .as_ref() - .map(|ty| self.lower_ty(&ty, DISALLOWED)) - .unwrap_or_else(|| mk_tup(self, hir::HirVec::new(), span)), - span: output.as_ref().map_or(span, |ty| ty.span), - } - ], - parenthesized: true, - }, - false, + ( + hir::PathParameters { + lifetimes: hir::HirVec::new(), + types: hir_vec![mk_tup(this, inputs, span)], + bindings: hir_vec![ + hir::TypeBinding { + id: this.next_id().node_id, + name: Symbol::intern(FN_OUTPUT_NAME), + ty: output + .as_ref() + .map(|ty| this.lower_ty(&ty, DISALLOWED)) + .unwrap_or_else(|| mk_tup(this, hir::HirVec::new(), span)), + span: output.as_ref().map_or(span, |ty| ty.span), + } + ], + parenthesized: true, + }, + false, + ) + } ) } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 53d51d9429fb5..2da99b35929a1 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -101,6 +101,13 @@ impl Region { let depth = ty::DebruijnIndex::INNERMOST; let def_id = hir_map.local_def_id(def.lifetime.id); let origin = LifetimeDefOrigin::from_is_in_band(def.in_band); + debug!( + "Region::late: def={:?} depth={:?} def_id={:?} origin={:?}", + def, + depth, + def_id, + origin, + ); (def.lifetime.name, Region::LateBound(depth, def_id, origin)) } diff --git a/src/test/ui/rust-2018/issue-51008-1.rs b/src/test/ui/rust-2018/issue-51008-1.rs new file mode 100644 index 0000000000000..4a76d683d6e50 --- /dev/null +++ b/src/test/ui/rust-2018/issue-51008-1.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #51008 -- the anonymous lifetime in `&i32` was +// being incorrectly considered part of the "elided lifetimes" from +// the impl. +// +// run-pass + +#![feature(rust_2018_preview)] + +trait A { + +} + +impl A for F where F: PartialEq { } + +fn main() {} diff --git a/src/test/ui/rust-2018/issue-51008.rs b/src/test/ui/rust-2018/issue-51008.rs new file mode 100644 index 0000000000000..eb2673857e2f4 --- /dev/null +++ b/src/test/ui/rust-2018/issue-51008.rs @@ -0,0 +1,25 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #51008 -- the anonymous lifetime in `&i32` was +// being incorrectly considered part of the "elided lifetimes" from +// the impl. +// +// run-pass + +#![feature(rust_2018_preview)] + +trait A { + +} + +impl A for F where F: FnOnce(&i32) {} + +fn main() {}