Skip to content

Commit

Permalink
Auto merge of #44691 - cramertj:underscore-lifetimes, r=nikomatsakis
Browse files Browse the repository at this point in the history
Implement underscore lifetimes

Part of #44524
  • Loading branch information
bors committed Sep 22, 2017
2 parents ee409a4 + f5505d1 commit 3eb19bf
Show file tree
Hide file tree
Showing 21 changed files with 259 additions and 62 deletions.
1 change: 1 addition & 0 deletions src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
7 changes: 6 additions & 1 deletion src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,12 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {

pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
visitor.visit_id(lifetime.id);
visitor.visit_name(lifetime.span, lifetime.name);
match lifetime.name {
LifetimeName::Name(name) => {
visitor.visit_name(lifetime.span, name);
}
LifetimeName::Static | LifetimeName::Implicit | LifetimeName::Underscore => {}
}
}

pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) {
Expand Down
8 changes: 6 additions & 2 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,11 @@ impl<'a> LoweringContext<'a> {
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
hir::Lifetime {
id: self.lower_node_id(l.id).node_id,
name: self.lower_ident(l.ident),
name: match self.lower_ident(l.ident) {
x if x == "'_" => hir::LifetimeName::Underscore,
x if x == "'static" => hir::LifetimeName::Static,
name => hir::LifetimeName::Name(name),
},
span: l.span,
}
}
Expand Down Expand Up @@ -3005,7 +3009,7 @@ impl<'a> LoweringContext<'a> {
hir::Lifetime {
id: self.next_id().node_id,
span,
name: keywords::Invalid.name()
name: hir::LifetimeName::Implicit,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ impl<'hir> Map<'hir> {
NodeTraitItem(ti) => ti.name,
NodeVariant(v) => v.node.name,
NodeField(f) => f.name,
NodeLifetime(lt) => lt.name,
NodeLifetime(lt) => lt.name.name(),
NodeTyParam(tp) => tp.name,
NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node,
NodeStructCtor(_) => self.name(self.get_parent(id)),
Expand Down
30 changes: 27 additions & 3 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,27 @@ pub struct Lifetime {
/// HIR lowering inserts these placeholders in type paths that
/// refer to type definitions needing lifetime parameters,
/// `&T` and `&mut T`, and trait objects without `... + 'a`.
pub name: Name,
pub name: LifetimeName,
}

#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
pub enum LifetimeName {
Implicit,
Underscore,
Static,
Name(Name),
}

impl LifetimeName {
pub fn name(&self) -> Name {
use self::LifetimeName::*;
match *self {
Implicit => keywords::Invalid.name(),
Underscore => Symbol::intern("'_"),
Static => keywords::StaticLifetime.name(),
Name(name) => name,
}
}
}

impl fmt::Debug for Lifetime {
Expand All @@ -159,11 +179,15 @@ impl fmt::Debug for Lifetime {

impl Lifetime {
pub fn is_elided(&self) -> bool {
self.name == keywords::Invalid.name()
use self::LifetimeName::*;
match self.name {
Implicit | Underscore => true,
Static | Name(_) => false,
}
}

pub fn is_static(&self) -> bool {
self.name == "'static"
self.name == LifetimeName::Static
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1975,7 +1975,7 @@ impl<'a> State<'a> {
}

pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
self.print_name(lifetime.name)
self.print_name(lifetime.name.name())
}

pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> {
Expand Down
7 changes: 7 additions & 0 deletions src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItemId {
}
}

impl_stable_hash_for!(enum hir::LifetimeName {
Implicit,
Underscore,
Static,
Name(name)
});

impl_stable_hash_for!(struct hir::Lifetime {
id,
span,
Expand Down
78 changes: 48 additions & 30 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,16 @@ pub enum Region {
}

impl Region {
fn early(hir_map: &Map, index: &mut u32, def: &hir::LifetimeDef) -> (ast::Name, Region) {
fn early(hir_map: &Map, index: &mut u32, def: &hir::LifetimeDef)
-> (hir::LifetimeName, Region)
{
let i = *index;
*index += 1;
let def_id = hir_map.local_def_id(def.lifetime.id);
(def.lifetime.name, Region::EarlyBound(i, def_id))
}

fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (ast::Name, Region) {
fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (hir::LifetimeName, Region) {
let depth = ty::DebruijnIndex::new(1);
let def_id = hir_map.local_def_id(def.lifetime.id);
(def.lifetime.name, Region::LateBound(depth, def_id))
Expand Down Expand Up @@ -198,7 +200,7 @@ enum Scope<'a> {
/// it should be shifted by the number of `Binder`s in between the
/// declaration `Binder` and the location it's referenced from.
Binder {
lifetimes: FxHashMap<ast::Name, Region>,
lifetimes: FxHashMap<hir::LifetimeName, Region>,
s: ScopeRef<'a>
},

Expand Down Expand Up @@ -654,7 +656,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, body: &hir::Body) {

Scope::Binder { ref lifetimes, s } => {
// FIXME (#24278): non-hygienic comparison
if let Some(def) = lifetimes.get(&label) {
if let Some(def) = lifetimes.get(&hir::LifetimeName::Name(label)) {
let node_id = hir_map.as_local_node_id(def.id().unwrap())
.unwrap();

Expand Down Expand Up @@ -692,7 +694,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map)
Set1::Empty => "BaseDefault".to_string(),
Set1::One(Region::Static) => "'static".to_string(),
Set1::One(Region::EarlyBound(i, _)) => {
generics.lifetimes[i as usize].lifetime.name.to_string()
generics.lifetimes[i as usize].lifetime.name.name().to_string()
}
Set1::One(_) => bug!(),
Set1::Many => "Ambiguous".to_string(),
Expand All @@ -714,7 +716,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map)
/// for each type parameter.
fn object_lifetime_defaults_for_item(hir_map: &Map, generics: &hir::Generics)
-> Vec<ObjectLifetimeDefault> {
fn add_bounds(set: &mut Set1<ast::Name>, bounds: &[hir::TyParamBound]) {
fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::TyParamBound]) {
for bound in bounds {
if let hir::RegionTyParamBound(ref lifetime) = *bound {
set.insert(lifetime.name);
Expand Down Expand Up @@ -754,7 +756,7 @@ fn object_lifetime_defaults_for_item(hir_map: &Map, generics: &hir::Generics)
match set {
Set1::Empty => Set1::Empty,
Set1::One(name) => {
if name == "'static" {
if name == hir::LifetimeName::Static {
Set1::One(Region::Static)
} else {
generics.lifetimes.iter().enumerate().find(|&(_, def)| {
Expand Down Expand Up @@ -922,7 +924,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
self.insert_lifetime(lifetime_ref, def);
} else {
struct_span_err!(self.sess, lifetime_ref.span, E0261,
"use of undeclared lifetime name `{}`", lifetime_ref.name)
"use of undeclared lifetime name `{}`", lifetime_ref.name.name())
.span_label(lifetime_ref.span, "undeclared lifetime")
.emit();
}
Expand Down Expand Up @@ -1422,13 +1424,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
let lifetime_i = &lifetimes[i];

for lifetime in lifetimes {
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);
err.span_label(lifetime.span,
format!("{} is a reserved lifetime name", lifetime.name));
err.emit();
match lifetime.lifetime.name {
hir::LifetimeName::Static | hir::LifetimeName::Underscore => {
let lifetime = lifetime.lifetime;
let name = lifetime.name.name();
let mut err = struct_span_err!(self.sess, lifetime.span, E0262,
"invalid lifetime parameter name: `{}`", name);
err.span_label(lifetime.span,
format!("{} is a reserved lifetime name", name));
err.emit();
}
hir::LifetimeName::Implicit | hir::LifetimeName::Name(_) => {}
}
}

Expand All @@ -1439,7 +1445,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
struct_span_err!(self.sess, lifetime_j.lifetime.span, E0263,
"lifetime name `{}` declared twice in the same scope",
lifetime_j.lifetime.name)
lifetime_j.lifetime.name.name())
.span_label(lifetime_j.lifetime.span,
"declared twice")
.span_label(lifetime_i.lifetime.span,
Expand All @@ -1452,15 +1458,27 @@ 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() {
self.resolve_lifetime_ref(bound);
} else {
self.insert_lifetime(bound, Region::Static);
self.sess.struct_span_warn(lifetime_i.lifetime.span.to(bound.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();
match bound.name {
hir::LifetimeName::Underscore => {
let mut err = struct_span_err!(self.sess, bound.span, E0637,
"invalid lifetime bound name: `'_`");
err.span_label(bound.span, "`'_` is a reserved lifetime name");
err.emit();
}
hir::LifetimeName::Static => {
self.insert_lifetime(bound, Region::Static);
self.sess.struct_span_warn(lifetime_i.lifetime.span.to(bound.span),
&format!("unnecessary lifetime parameter `{}`",
lifetime_i.lifetime.name.name()))
.help(&format!(
"you can use the `'static` lifetime directly, in place \
of `{}`", lifetime_i.lifetime.name.name()))
.emit();
}
hir::LifetimeName::Implicit |
hir::LifetimeName::Name(_) => {
self.resolve_lifetime_ref(bound);
}
}
}
}
Expand All @@ -1472,9 +1490,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
{
for &(label, label_span) in &self.labels_in_fn {
// FIXME (#24278): non-hygienic comparison
if lifetime.name == label {
if lifetime.name.name() == label {
signal_shadowing_problem(self.sess,
lifetime.name,
label,
original_label(label_span),
shadower_lifetime(&lifetime));
return;
Expand All @@ -1501,7 +1519,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {

signal_shadowing_problem(
self.sess,
lifetime.name,
lifetime.name.name(),
original_lifetime(self.hir_map.span(node_id)),
shadower_lifetime(&lifetime));
return;
Expand Down Expand Up @@ -1617,7 +1635,7 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
return;

struct ConstrainedCollector {
regions: FxHashSet<ast::Name>,
regions: FxHashSet<hir::LifetimeName>,
}

impl<'v> Visitor<'v> for ConstrainedCollector {
Expand Down Expand Up @@ -1657,7 +1675,7 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
}

struct AllCollector {
regions: FxHashSet<ast::Name>,
regions: FxHashSet<hir::LifetimeName>,
impl_trait: bool
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_lint/bad_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
self.check_snake_case(cx,
"lifetime",
&t.lifetime.name.as_str(),
&t.lifetime.name.name().as_str(),
Some(t.lifetime.span));
}

Expand Down
8 changes: 0 additions & 8 deletions src/librustc_passes/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)) |
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {

let (span, name) = if index < ast_generics.lifetimes.len() {
(ast_generics.lifetimes[index].lifetime.span,
ast_generics.lifetimes[index].lifetime.name)
ast_generics.lifetimes[index].lifetime.name.name())
} else {
let index = index - ast_generics.lifetimes.len();
(ast_generics.ty_params[index].span,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -953,7 +953,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
let regions = early_lifetimes.enumerate().map(|(i, l)| {
ty::RegionParameterDef {
name: l.lifetime.name,
name: l.lifetime.name.name(),
index: own_start + i as u32,
def_id: tcx.hir.local_def_id(l.lifetime.id),
pure_wrt_drop: l.pure_wrt_drop,
Expand Down Expand Up @@ -1423,7 +1423,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
def_id: tcx.hir.local_def_id(param.lifetime.id),
index,
name: param.lifetime.name
name: param.lifetime.name.name(),
}));
index += 1;

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/impl_wf_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
!input_parameters.contains(&param)
{
report_unused_parameter(tcx, lifetime.lifetime.span,
"lifetime", &lifetime.lifetime.name.to_string());
"lifetime", &lifetime.lifetime.name.name().to_string());
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,22 +876,22 @@ impl Clean<Lifetime> for hir::Lifetime {
}
_ => {}
}
Lifetime(self.name.to_string())
Lifetime(self.name.name().to_string())
}
}

impl Clean<Lifetime> for hir::LifetimeDef {
fn clean(&self, _: &DocContext) -> Lifetime {
if self.bounds.len() > 0 {
let mut s = format!("{}: {}",
self.lifetime.name.to_string(),
self.bounds[0].name.to_string());
self.lifetime.name.name(),
self.bounds[0].name.name());
for bound in self.bounds.iter().skip(1) {
s.push_str(&format!(" + {}", bound.name.to_string()));
s.push_str(&format!(" + {}", bound.name.name()));
}
Lifetime(s)
} else {
Lifetime(self.lifetime.name.to_string())
Lifetime(self.lifetime.name.name().to_string())
}
}
}
Expand Down
Loading

0 comments on commit 3eb19bf

Please sign in to comment.