diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index edcfcffaa03a4..8239fd7d13c11 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -100,6 +100,10 @@ impl Lifetime { pub fn is_elided(&self) -> bool { self.name == keywords::Invalid.name() } + + pub fn is_static(&self) -> bool { + self.name == keywords::StaticLifetime.name() + } } /// A lifetime definition, eg `'a: 'b+'c+'d` diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 37749816eb153..5094e28475b26 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -29,7 +29,7 @@ use syntax::ast; use syntax::attr; use syntax::ptr::P; use syntax::symbol::keywords; -use syntax_pos::Span; +use syntax_pos::{mk_sp, Span}; use errors::DiagnosticBuilder; use util::nodemap::{NodeMap, NodeSet, FxHashSet, FxHashMap, DefIdMap}; use rustc_back::slice; @@ -434,7 +434,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.resolve_elided_lifetimes(slice::ref_slice(lifetime_ref)); return; } - if lifetime_ref.name == keywords::StaticLifetime.name() { + if lifetime_ref.is_static() { self.insert_lifetime(lifetime_ref, Region::Static); return; } @@ -1434,7 +1434,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let lifetime_i = &lifetimes[i]; for lifetime in lifetimes { - if lifetime.lifetime.name == keywords::StaticLifetime.name() { + if lifetime.lifetime.is_static() { let lifetime = lifetime.lifetime; let mut err = struct_span_err!(self.sess, lifetime.span, E0262, "invalid lifetime parameter name: `{}`", lifetime.name); @@ -1464,7 +1464,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime); for bound in &lifetime_i.bounds { - self.resolve_lifetime_ref(bound); + if !bound.is_static() { + self.resolve_lifetime_ref(bound); + } else { + self.insert_lifetime(bound, Region::Static); + let full_span = mk_sp(lifetime_i.lifetime.span.lo, bound.span.hi); + self.sess.struct_span_warn(full_span, + &format!("unnecessary lifetime parameter `{}`", lifetime_i.lifetime.name)) + .help(&format!("you can use the `'static` lifetime directly, in place \ + of `{}`", lifetime_i.lifetime.name)) + .emit(); + } } } } diff --git a/src/test/compile-fail/static-lifetime-bound.rs b/src/test/compile-fail/static-lifetime-bound.rs new file mode 100644 index 0000000000000..38534ab0a3687 --- /dev/null +++ b/src/test/compile-fail/static-lifetime-bound.rs @@ -0,0 +1,16 @@ +// Copyright 2017 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. + +fn f<'a: 'static>(_: &'a i32) {} //~WARN unnecessary lifetime parameter `'a` + +fn main() { + let x = 0; + f(&x); //~ERROR does not live long enough +}