diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 143d2c2ea28bb..0577800f3f411 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -246,6 +246,12 @@ declare_lint! { "raw pointer to an inference variable" } +declare_lint! { + pub ELIDED_LIFETIME_IN_PATH, + Allow, + "hidden lifetime parameters are deprecated, try `Foo<'_>`" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -291,7 +297,9 @@ impl LintPass for HardwiredLints { UNUSED_MUT, COERCE_NEVER, SINGLE_USE_LIFETIME, - TYVAR_BEHIND_RAW_POINTER + TYVAR_BEHIND_RAW_POINTER, + ELIDED_LIFETIME_IN_PATH + ) } } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 944d770516375..59460141166b1 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -737,7 +737,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { if lifetime_ref.is_elided() { - self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref)); + self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref), false); return; } if lifetime_ref.is_static() { @@ -1444,7 +1444,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } if params.lifetimes.iter().all(|l| l.is_elided()) { - self.resolve_elided_lifetimes(¶ms.lifetimes); + self.resolve_elided_lifetimes(¶ms.lifetimes, true); } else { for l in ¶ms.lifetimes { self.visit_lifetime(l); @@ -1803,14 +1803,24 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } - fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime]) { + fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime], deprecated: bool) { if lifetime_refs.is_empty() { return; } let span = lifetime_refs[0].span; + let id = lifetime_refs[0].id; let mut late_depth = 0; let mut scope = self.scope; + if deprecated { + self.tcx + .struct_span_lint_node( + lint::builtin::ELIDED_LIFETIME_IN_PATH, + id, + span, + &format!("hidden lifetime parameters are deprecated, try `Foo<'_>`")) + .emit(); + } let error = loop { match *scope { // Do not assign any resolution, it will be inferred. diff --git a/src/test/ui/in-band-lifetimes/ellided-lifetimes.rs b/src/test/ui/in-band-lifetimes/ellided-lifetimes.rs new file mode 100644 index 0000000000000..5151abd68232c --- /dev/null +++ b/src/test/ui/in-band-lifetimes/ellided-lifetimes.rs @@ -0,0 +1,19 @@ +// 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. +#![allow(warnings)] +#![allow(unused_variables, dead_code, unused, bad_style)] +#![deny(elided_lifetime_in_path)] + +struct Foo<'a> { x: &'a u32 } +fn foo(x: &Foo) { + //~^ ERROR: hidden lifetime parameters are deprecated, try `Foo<'_>` +} + +fn main() {} diff --git a/src/test/ui/in-band-lifetimes/ellided-lifetimes.stderr b/src/test/ui/in-band-lifetimes/ellided-lifetimes.stderr new file mode 100644 index 0000000000000..613a7be6ed2c1 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/ellided-lifetimes.stderr @@ -0,0 +1,14 @@ +error: hidden lifetime parameters are deprecated, try `Foo<'_>` + --> $DIR/ellided-lifetimes.rs:15:12 + | +15 | fn foo(x: &Foo) { + | ^^^ + | +note: lint level defined here + --> $DIR/ellided-lifetimes.rs:12:9 + | +12 | #![deny(elided_lifetime_in_path)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error +