Skip to content

Commit 3eb19bf

Browse files
committed
Auto merge of #44691 - cramertj:underscore-lifetimes, r=nikomatsakis
Implement underscore lifetimes Part of #44524
2 parents ee409a4 + f5505d1 commit 3eb19bf

21 files changed

+259
-62
lines changed

src/librustc/diagnostics.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2086,4 +2086,5 @@ register_diagnostics! {
20862086
E0566, // conflicting representation hints
20872087
E0623, // lifetime mismatch where both parameters are anonymous regions
20882088
E0628, // generators cannot have explicit arguments
2089+
E0637, // "'_" is not a valid lifetime bound
20892090
}

src/librustc/hir/intravisit.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,12 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
422422

423423
pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
424424
visitor.visit_id(lifetime.id);
425-
visitor.visit_name(lifetime.span, lifetime.name);
425+
match lifetime.name {
426+
LifetimeName::Name(name) => {
427+
visitor.visit_name(lifetime.span, name);
428+
}
429+
LifetimeName::Static | LifetimeName::Implicit | LifetimeName::Underscore => {}
430+
}
426431
}
427432

428433
pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) {

src/librustc/hir/lowering.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1121,7 +1121,11 @@ impl<'a> LoweringContext<'a> {
11211121
fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime {
11221122
hir::Lifetime {
11231123
id: self.lower_node_id(l.id).node_id,
1124-
name: self.lower_ident(l.ident),
1124+
name: match self.lower_ident(l.ident) {
1125+
x if x == "'_" => hir::LifetimeName::Underscore,
1126+
x if x == "'static" => hir::LifetimeName::Static,
1127+
name => hir::LifetimeName::Name(name),
1128+
},
11251129
span: l.span,
11261130
}
11271131
}
@@ -3005,7 +3009,7 @@ impl<'a> LoweringContext<'a> {
30053009
hir::Lifetime {
30063010
id: self.next_id().node_id,
30073011
span,
3008-
name: keywords::Invalid.name()
3012+
name: hir::LifetimeName::Implicit,
30093013
}
30103014
}
30113015
}

src/librustc/hir/map/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ impl<'hir> Map<'hir> {
805805
NodeTraitItem(ti) => ti.name,
806806
NodeVariant(v) => v.node.name,
807807
NodeField(f) => f.name,
808-
NodeLifetime(lt) => lt.name,
808+
NodeLifetime(lt) => lt.name.name(),
809809
NodeTyParam(tp) => tp.name,
810810
NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node,
811811
NodeStructCtor(_) => self.name(self.get_parent(id)),

src/librustc/hir/mod.rs

+27-3
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,27 @@ pub struct Lifetime {
145145
/// HIR lowering inserts these placeholders in type paths that
146146
/// refer to type definitions needing lifetime parameters,
147147
/// `&T` and `&mut T`, and trait objects without `... + 'a`.
148-
pub name: Name,
148+
pub name: LifetimeName,
149+
}
150+
151+
#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
152+
pub enum LifetimeName {
153+
Implicit,
154+
Underscore,
155+
Static,
156+
Name(Name),
157+
}
158+
159+
impl LifetimeName {
160+
pub fn name(&self) -> Name {
161+
use self::LifetimeName::*;
162+
match *self {
163+
Implicit => keywords::Invalid.name(),
164+
Underscore => Symbol::intern("'_"),
165+
Static => keywords::StaticLifetime.name(),
166+
Name(name) => name,
167+
}
168+
}
149169
}
150170

151171
impl fmt::Debug for Lifetime {
@@ -159,11 +179,15 @@ impl fmt::Debug for Lifetime {
159179

160180
impl Lifetime {
161181
pub fn is_elided(&self) -> bool {
162-
self.name == keywords::Invalid.name()
182+
use self::LifetimeName::*;
183+
match self.name {
184+
Implicit | Underscore => true,
185+
Static | Name(_) => false,
186+
}
163187
}
164188

165189
pub fn is_static(&self) -> bool {
166-
self.name == "'static"
190+
self.name == LifetimeName::Static
167191
}
168192
}
169193

src/librustc/hir/print.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1975,7 +1975,7 @@ impl<'a> State<'a> {
19751975
}
19761976

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

19811981
pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> {

src/librustc/ich/impls_hir.rs

+7
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for hir::ImplItemId {
123123
}
124124
}
125125

126+
impl_stable_hash_for!(enum hir::LifetimeName {
127+
Implicit,
128+
Underscore,
129+
Static,
130+
Name(name)
131+
});
132+
126133
impl_stable_hash_for!(struct hir::Lifetime {
127134
id,
128135
span,

src/librustc/middle/resolve_lifetime.rs

+48-30
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,16 @@ pub enum Region {
4646
}
4747

4848
impl Region {
49-
fn early(hir_map: &Map, index: &mut u32, def: &hir::LifetimeDef) -> (ast::Name, Region) {
49+
fn early(hir_map: &Map, index: &mut u32, def: &hir::LifetimeDef)
50+
-> (hir::LifetimeName, Region)
51+
{
5052
let i = *index;
5153
*index += 1;
5254
let def_id = hir_map.local_def_id(def.lifetime.id);
5355
(def.lifetime.name, Region::EarlyBound(i, def_id))
5456
}
5557

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

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

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

@@ -692,7 +694,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map)
692694
Set1::Empty => "BaseDefault".to_string(),
693695
Set1::One(Region::Static) => "'static".to_string(),
694696
Set1::One(Region::EarlyBound(i, _)) => {
695-
generics.lifetimes[i as usize].lifetime.name.to_string()
697+
generics.lifetimes[i as usize].lifetime.name.name().to_string()
696698
}
697699
Set1::One(_) => bug!(),
698700
Set1::Many => "Ambiguous".to_string(),
@@ -714,7 +716,7 @@ fn compute_object_lifetime_defaults(sess: &Session, hir_map: &Map)
714716
/// for each type parameter.
715717
fn object_lifetime_defaults_for_item(hir_map: &Map, generics: &hir::Generics)
716718
-> Vec<ObjectLifetimeDefault> {
717-
fn add_bounds(set: &mut Set1<ast::Name>, bounds: &[hir::TyParamBound]) {
719+
fn add_bounds(set: &mut Set1<hir::LifetimeName>, bounds: &[hir::TyParamBound]) {
718720
for bound in bounds {
719721
if let hir::RegionTyParamBound(ref lifetime) = *bound {
720722
set.insert(lifetime.name);
@@ -754,7 +756,7 @@ fn object_lifetime_defaults_for_item(hir_map: &Map, generics: &hir::Generics)
754756
match set {
755757
Set1::Empty => Set1::Empty,
756758
Set1::One(name) => {
757-
if name == "'static" {
759+
if name == hir::LifetimeName::Static {
758760
Set1::One(Region::Static)
759761
} else {
760762
generics.lifetimes.iter().enumerate().find(|&(_, def)| {
@@ -922,7 +924,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
922924
self.insert_lifetime(lifetime_ref, def);
923925
} else {
924926
struct_span_err!(self.sess, lifetime_ref.span, E0261,
925-
"use of undeclared lifetime name `{}`", lifetime_ref.name)
927+
"use of undeclared lifetime name `{}`", lifetime_ref.name.name())
926928
.span_label(lifetime_ref.span, "undeclared lifetime")
927929
.emit();
928930
}
@@ -1422,13 +1424,17 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
14221424
let lifetime_i = &lifetimes[i];
14231425

14241426
for lifetime in lifetimes {
1425-
if lifetime.lifetime.is_static() {
1426-
let lifetime = lifetime.lifetime;
1427-
let mut err = struct_span_err!(self.sess, lifetime.span, E0262,
1428-
"invalid lifetime parameter name: `{}`", lifetime.name);
1429-
err.span_label(lifetime.span,
1430-
format!("{} is a reserved lifetime name", lifetime.name));
1431-
err.emit();
1427+
match lifetime.lifetime.name {
1428+
hir::LifetimeName::Static | hir::LifetimeName::Underscore => {
1429+
let lifetime = lifetime.lifetime;
1430+
let name = lifetime.name.name();
1431+
let mut err = struct_span_err!(self.sess, lifetime.span, E0262,
1432+
"invalid lifetime parameter name: `{}`", name);
1433+
err.span_label(lifetime.span,
1434+
format!("{} is a reserved lifetime name", name));
1435+
err.emit();
1436+
}
1437+
hir::LifetimeName::Implicit | hir::LifetimeName::Name(_) => {}
14321438
}
14331439
}
14341440

@@ -1439,7 +1445,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
14391445
if lifetime_i.lifetime.name == lifetime_j.lifetime.name {
14401446
struct_span_err!(self.sess, lifetime_j.lifetime.span, E0263,
14411447
"lifetime name `{}` declared twice in the same scope",
1442-
lifetime_j.lifetime.name)
1448+
lifetime_j.lifetime.name.name())
14431449
.span_label(lifetime_j.lifetime.span,
14441450
"declared twice")
14451451
.span_label(lifetime_i.lifetime.span,
@@ -1452,15 +1458,27 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
14521458
self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime);
14531459

14541460
for bound in &lifetime_i.bounds {
1455-
if !bound.is_static() {
1456-
self.resolve_lifetime_ref(bound);
1457-
} else {
1458-
self.insert_lifetime(bound, Region::Static);
1459-
self.sess.struct_span_warn(lifetime_i.lifetime.span.to(bound.span),
1460-
&format!("unnecessary lifetime parameter `{}`", lifetime_i.lifetime.name))
1461-
.help(&format!("you can use the `'static` lifetime directly, in place \
1462-
of `{}`", lifetime_i.lifetime.name))
1463-
.emit();
1461+
match bound.name {
1462+
hir::LifetimeName::Underscore => {
1463+
let mut err = struct_span_err!(self.sess, bound.span, E0637,
1464+
"invalid lifetime bound name: `'_`");
1465+
err.span_label(bound.span, "`'_` is a reserved lifetime name");
1466+
err.emit();
1467+
}
1468+
hir::LifetimeName::Static => {
1469+
self.insert_lifetime(bound, Region::Static);
1470+
self.sess.struct_span_warn(lifetime_i.lifetime.span.to(bound.span),
1471+
&format!("unnecessary lifetime parameter `{}`",
1472+
lifetime_i.lifetime.name.name()))
1473+
.help(&format!(
1474+
"you can use the `'static` lifetime directly, in place \
1475+
of `{}`", lifetime_i.lifetime.name.name()))
1476+
.emit();
1477+
}
1478+
hir::LifetimeName::Implicit |
1479+
hir::LifetimeName::Name(_) => {
1480+
self.resolve_lifetime_ref(bound);
1481+
}
14641482
}
14651483
}
14661484
}
@@ -1472,9 +1490,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
14721490
{
14731491
for &(label, label_span) in &self.labels_in_fn {
14741492
// FIXME (#24278): non-hygienic comparison
1475-
if lifetime.name == label {
1493+
if lifetime.name.name() == label {
14761494
signal_shadowing_problem(self.sess,
1477-
lifetime.name,
1495+
label,
14781496
original_label(label_span),
14791497
shadower_lifetime(&lifetime));
14801498
return;
@@ -1501,7 +1519,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
15011519

15021520
signal_shadowing_problem(
15031521
self.sess,
1504-
lifetime.name,
1522+
lifetime.name.name(),
15051523
original_lifetime(self.hir_map.span(node_id)),
15061524
shadower_lifetime(&lifetime));
15071525
return;
@@ -1617,7 +1635,7 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
16171635
return;
16181636

16191637
struct ConstrainedCollector {
1620-
regions: FxHashSet<ast::Name>,
1638+
regions: FxHashSet<hir::LifetimeName>,
16211639
}
16221640

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

16591677
struct AllCollector {
1660-
regions: FxHashSet<ast::Name>,
1678+
regions: FxHashSet<hir::LifetimeName>,
16611679
impl_trait: bool
16621680
}
16631681

src/librustc_lint/bad_style.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
278278
fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
279279
self.check_snake_case(cx,
280280
"lifetime",
281-
&t.lifetime.name.as_str(),
281+
&t.lifetime.name.name().as_str(),
282282
Some(t.lifetime.span));
283283
}
284284

src/librustc_passes/ast_validation.rs

-8
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,6 @@ impl<'a> AstValidator<'a> {
122122
}
123123

124124
impl<'a> Visitor<'a> for AstValidator<'a> {
125-
fn visit_lifetime(&mut self, lt: &'a Lifetime) {
126-
if lt.ident.name == "'_" {
127-
self.err_handler().span_err(lt.span, &format!("invalid lifetime name `{}`", lt.ident));
128-
}
129-
130-
visit::walk_lifetime(self, lt)
131-
}
132-
133125
fn visit_expr(&mut self, expr: &'a Expr) {
134126
match expr.node {
135127
ExprKind::While(.., Some(ident)) |

src/librustc_typeck/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
523523

524524
let (span, name) = if index < ast_generics.lifetimes.len() {
525525
(ast_generics.lifetimes[index].lifetime.span,
526-
ast_generics.lifetimes[index].lifetime.name)
526+
ast_generics.lifetimes[index].lifetime.name.name())
527527
} else {
528528
let index = index - ast_generics.lifetimes.len();
529529
(ast_generics.ty_params[index].span,

src/librustc_typeck/collect.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
953953
let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
954954
let regions = early_lifetimes.enumerate().map(|(i, l)| {
955955
ty::RegionParameterDef {
956-
name: l.lifetime.name,
956+
name: l.lifetime.name.name(),
957957
index: own_start + i as u32,
958958
def_id: tcx.hir.local_def_id(l.lifetime.id),
959959
pure_wrt_drop: l.pure_wrt_drop,
@@ -1423,7 +1423,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
14231423
let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion {
14241424
def_id: tcx.hir.local_def_id(param.lifetime.id),
14251425
index,
1426-
name: param.lifetime.name
1426+
name: param.lifetime.name.name(),
14271427
}));
14281428
index += 1;
14291429

src/librustc_typeck/impl_wf_check.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
132132
!input_parameters.contains(&param)
133133
{
134134
report_unused_parameter(tcx, lifetime.lifetime.span,
135-
"lifetime", &lifetime.lifetime.name.to_string());
135+
"lifetime", &lifetime.lifetime.name.name().to_string());
136136
}
137137
}
138138

src/librustdoc/clean/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -876,22 +876,22 @@ impl Clean<Lifetime> for hir::Lifetime {
876876
}
877877
_ => {}
878878
}
879-
Lifetime(self.name.to_string())
879+
Lifetime(self.name.name().to_string())
880880
}
881881
}
882882

883883
impl Clean<Lifetime> for hir::LifetimeDef {
884884
fn clean(&self, _: &DocContext) -> Lifetime {
885885
if self.bounds.len() > 0 {
886886
let mut s = format!("{}: {}",
887-
self.lifetime.name.to_string(),
888-
self.bounds[0].name.to_string());
887+
self.lifetime.name.name(),
888+
self.bounds[0].name.name());
889889
for bound in self.bounds.iter().skip(1) {
890-
s.push_str(&format!(" + {}", bound.name.to_string()));
890+
s.push_str(&format!(" + {}", bound.name.name()));
891891
}
892892
Lifetime(s)
893893
} else {
894-
Lifetime(self.lifetime.name.to_string())
894+
Lifetime(self.lifetime.name.name().to_string())
895895
}
896896
}
897897
}

0 commit comments

Comments
 (0)