]> git.lizzy.rs Git - rust.git/commitdiff
Refactor lifetime name into an enum
authorTaylor Cramer <cramertj@google.com>
Tue, 19 Sep 2017 23:36:54 +0000 (16:36 -0700)
committerTaylor Cramer <cramertj@google.com>
Thu, 21 Sep 2017 17:19:03 +0000 (10:19 -0700)
13 files changed:
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_hir.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc_lint/bad_style.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/impl_wf_check.rs
src/librustdoc/clean/mod.rs
src/test/run-pass/underscore-lifetimes.rs

index 9d8075de2eb2f985b03c72137519e816e5b7ca82..088fd8d90901c8d2a38876c40d29aef385433209 100644 (file)
@@ -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) {
index c7ea9c47028694d3714398010f054c5527b56d1f..465520ea03434c9af39ae87535cb0d56d6bd2170 100644 (file)
@@ -1121,7 +1121,11 @@ fn lower_ty_params(&mut self, tps: &Vec<TyParam>, add_bounds: &NodeMap<Vec<TyPar
     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,
         }
     }
@@ -3005,7 +3009,7 @@ fn elided_lifetime(&mut self, span: Span) -> hir::Lifetime {
         hir::Lifetime {
             id: self.next_id().node_id,
             span,
-            name: keywords::Invalid.name()
+            name: hir::LifetimeName::Implicit,
         }
     }
 }
index b2d6886e7f22800bcd137c734953c75247be70c3..c0577039f0c35874969fdb0e61c3ae80df83c1da 100644 (file)
@@ -805,7 +805,7 @@ pub fn name(&self, id: NodeId) -> Name {
             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)),
index 3d82481807e022f7721c8565c6633fb5b553fd49..1bef17b28acb572f52b67c0e82c9e1410d9d7ea0 100644 (file)
@@ -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 {
@@ -159,12 +179,15 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 impl Lifetime {
     pub fn is_elided(&self) -> bool {
-        self.name == keywords::Invalid.name() ||
-        self.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
     }
 }
 
index 41a253f7904f72e7b6b5b31e5c4b5780b1a141ed..ad31b2009a01dbefb56ca8757ae81cbba24fef93 100644 (file)
@@ -1975,7 +1975,7 @@ pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io
     }
 
     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<()> {
index 9582b03ce1c8a80b7b373a4d5e429a073f25b532..b3af44c952bdd96788f8fcc8b7ffc8096acd73eb 100644 (file)
@@ -123,6 +123,13 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+impl_stable_hash_for!(enum hir::LifetimeName {
+    Implicit,
+    Underscore,
+    Static,
+    Name(name)
+});
+
 impl_stable_hash_for!(struct hir::Lifetime {
     id,
     span,
index 8b58c75e2418e7fc46d8ede0846a28fb75435bb7..60f03eb5d89ec12bba1e6ddf7906d13a2a39eb68 100644 (file)
@@ -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))
@@ -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>
     },
 
@@ -654,7 +656,7 @@ fn check_if_label_shadows_lifetime<'a>(sess: &'a Session,
 
                 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();
 
@@ -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(),
@@ -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);
@@ -754,7 +756,7 @@ fn add_bounds(set: &mut Set1<ast::Name>, bounds: &[hir::TyParamBound]) {
         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)| {
@@ -922,7 +924,7 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
             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();
         }
@@ -1422,13 +1424,17 @@ fn check_lifetime_defs(&mut self, old_scope: ScopeRef, lifetimes: &[hir::Lifetim
             let lifetime_i = &lifetimes[i];
 
             for lifetime in lifetimes {
-                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);
-                    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(_) => {}
                 }
             }
 
@@ -1439,7 +1445,7 @@ fn check_lifetime_defs(&mut self, old_scope: ScopeRef, lifetimes: &[hir::Lifetim
                 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,
@@ -1452,21 +1458,27 @@ fn check_lifetime_defs(&mut self, old_scope: ScopeRef, lifetimes: &[hir::Lifetim
             self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime);
 
             for bound in &lifetime_i.bounds {
-                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);
-                    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);
+                    }
                 }
             }
         }
@@ -1478,9 +1490,9 @@ fn check_lifetime_def_for_shadowing(&self,
     {
         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;
@@ -1507,7 +1519,7 @@ fn check_lifetime_def_for_shadowing(&self,
 
                         signal_shadowing_problem(
                             self.sess,
-                            lifetime.name,
+                            lifetime.name.name(),
                             original_lifetime(self.hir_map.span(node_id)),
                             shadower_lifetime(&lifetime));
                         return;
@@ -1623,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 {
@@ -1663,7 +1675,7 @@ fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) {
     }
 
     struct AllCollector {
-        regions: FxHashSet<ast::Name>,
+        regions: FxHashSet<hir::LifetimeName>,
         impl_trait: bool
     }
 
index d4b8f0a4924619ebcdb3ce53cf3992f56768f59e..cbc012a65faad04444c139df5e169deab1f4e06d 100644 (file)
@@ -278,7 +278,7 @@ fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
     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));
     }
 
index f17df8b22f3934e0c4943524d1d73148bf083bac..ddbdd204305890f9e3dfffe463aab47d92583577 100644 (file)
@@ -523,7 +523,7 @@ fn check_variances_for_type_defn(&self,
 
             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,
index 79cb9147c185bcc5455223edd0740742df131c21..8d078b922751206a4d6ff997724832c9779b1128 100644 (file)
@@ -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,
@@ -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;
 
index 14e48b9302964904db67f98a144d09ecf701fd60..15708ab766ae82956b38e16ccd41dc80b1983a1c 100644 (file)
@@ -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());
         }
     }
 
index 095eb7797d4578f8d434fa4663a9642a04f7d71d..1e25a57b1d2b1dd5a171f00074a39137ddcaae33 100644 (file)
@@ -876,7 +876,7 @@ fn clean(&self, cx: &DocContext) -> Lifetime {
             }
             _ => {}
         }
-        Lifetime(self.name.to_string())
+        Lifetime(self.name.name().to_string())
     }
 }
 
@@ -884,14 +884,14 @@ 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())
         }
     }
 }
index d3db34a7caa97fa466fc3fe618749e70a236b0d0..ed0369353bcd30785886d22cf852e011be2fbef9 100644 (file)
@@ -26,10 +26,22 @@ fn foo3(x: &'_ u8) -> Foo {
 
 fn foo4(_: Foo<'_>) {}
 
+struct Foo2<'a, 'b> {
+    a: &'a u8,
+    b: &'b u8,
+}
+fn foo5<'b>(foo: Foo2<'_, 'b>) -> &'b u8 {
+    foo.b
+}
+
 fn main() {
     let x = &5;
     let _ = foo(x);
     let _ = foo2(x);
     let _ = foo3(x);
     foo4(Foo(x));
+    let _ = foo5(Foo2 {
+        a: x,
+        b: &6,
+    });
 }