Implement underscore lifetimes

This commit is contained in:
Taylor Cramer 2017-09-18 22:55:21 -07:00
parent e2504cfc76
commit 64314e3ae2
10 changed files with 129 additions and 17 deletions

View File

@ -2086,4 +2086,5 @@ register_diagnostics! {
E0566, // conflicting representation hints
E0623, // lifetime mismatch where both parameters are anonymous regions
E0628, // generators cannot have explicit arguments
E0637, // "'_" is not a valid lifetime bound
}

View File

@ -159,7 +159,8 @@ impl fmt::Debug for Lifetime {
impl Lifetime {
pub fn is_elided(&self) -> bool {
self.name == keywords::Invalid.name()
self.name == keywords::Invalid.name() ||
self.name == "'_"
}
pub fn is_static(&self) -> bool {

View File

@ -1422,7 +1422,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
let lifetime_i = &lifetimes[i];
for lifetime in lifetimes {
if lifetime.lifetime.is_static() {
if lifetime.lifetime.is_static() || lifetime.lifetime.name == "'_" {
let lifetime = lifetime.lifetime;
let mut err = struct_span_err!(self.sess, lifetime.span, E0262,
"invalid lifetime parameter name: `{}`", lifetime.name);
@ -1452,7 +1452,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime);
for bound in &lifetime_i.bounds {
if !bound.is_static() {
if bound.name == "'_" {
let mut err = struct_span_err!(self.sess, bound.span, E0637,
"invalid lifetime bound name: `{}`", bound.name);
err.span_label(bound.span,
format!("{} is a reserved lifetime name", bound.name));
err.emit();
} else if !bound.is_static() {
self.resolve_lifetime_ref(bound);
} else {
self.insert_lifetime(bound, Region::Static);

View File

@ -122,14 +122,6 @@ impl<'a> AstValidator<'a> {
}
impl<'a> Visitor<'a> for AstValidator<'a> {
fn visit_lifetime(&mut self, lt: &'a Lifetime) {
if lt.ident.name == "'_" {
self.err_handler().span_err(lt.span, &format!("invalid lifetime name `{}`", lt.ident));
}
visit::walk_lifetime(self, lt)
}
fn visit_expr(&mut self, expr: &'a Expr) {
match expr.node {
ExprKind::While(.., Some(ident)) |

View File

@ -389,6 +389,9 @@ declare_features! (
// Copy/Clone closures (RFC 2132)
(active, clone_closures, "1.22.0", Some(44490)),
(active, copy_closures, "1.22.0", Some(44490)),
// allow `'_` placeholder lifetimes
(active, underscore_lifetimes, "1.22.0", Some(44524)),
);
declare_features! (
@ -1572,6 +1575,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
visit::walk_lifetime_def(self, lifetime_def)
}
fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) {
if lt.ident.name == "'_" {
gate_feature_post!(&self, underscore_lifetimes, lt.span,
"underscore lifetimes are unstable");
}
visit::walk_lifetime(self, lt)
}
}
pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute]) -> Features {

View File

@ -0,0 +1,20 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(underscore_lifetimes)]
struct Foo<'a: '_>(&'a u8); //~ ERROR invalid lifetime bound name: `'_`
fn foo<'a: '_>(_: &'a u8) {} //~ ERROR invalid lifetime bound name: `'_`
struct Bar<'a>(&'a u8);
impl<'a: '_> Bar<'a> { //~ ERROR invalid lifetime bound name: `'_`
fn bar() {}
}
fn main() {}

View File

@ -0,0 +1,20 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Foo<'a>(&'a u8);
fn foo(x: &u8) -> Foo<'_> { //~ ERROR underscore lifetimes are unstable
Foo(x)
}
fn main() {
let x = 5;
let _ = foo(&x);
}

View File

@ -8,12 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn _f<'_>() //~ ERROR invalid lifetime name `'_`
-> &'_ u8 //~ ERROR invalid lifetime name `'_`
{
panic!();
}
fn main() {
'_: loop { //~ ERROR invalid label name `'_`
break '_ //~ ERROR invalid label name `'_`

View File

@ -0,0 +1,32 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(underscore_lifetimes)]
struct Foo<'a>(&'a u8);
fn foo<'_> //~ ERROR invalid lifetime parameter name: `'_`
(_: Foo<'_>) {}
trait Meh<'a> {}
impl<'a> Meh<'a> for u8 {}
fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
//~^ ERROR missing lifetime specifier
//~^^ ERROR missing lifetime specifier
{
Box::new(5u8)
}
fn main() {
let x = 5;
foo(Foo(&x));
let _ = meh();
}

View File

@ -0,0 +1,35 @@
// 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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(underscore_lifetimes)]
struct Foo<'a>(&'a u8);
fn foo(x: &u8) -> Foo<'_> {
Foo(x)
}
fn foo2(x: &'_ u8) -> Foo<'_> {
Foo(x)
}
fn foo3(x: &'_ u8) -> Foo {
Foo(x)
}
fn foo4(_: Foo<'_>) {}
fn main() {
let x = &5;
let _ = foo(x);
let _ = foo2(x);
let _ = foo3(x);
foo4(Foo(x));
}