Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement underscore lifetimes #44691

Merged
merged 4 commits into from
Sep 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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