about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-03-01 21:08:26 +0100
committerCamille GILLOT <gillot.camille@gmail.com>2022-03-12 14:18:56 +0100
commitd3b7ea6c9eae104995da1e2a29d662320d30b9f1 (patch)
tree20675ed5b06943e0749df7ee277ee0773aa6a8d0 /compiler
parent012720ffb075a087b781325d17d1822a340a2f2a (diff)
downloadrust-d3b7ea6c9eae104995da1e2a29d662320d30b9f1.tar.gz
rust-d3b7ea6c9eae104995da1e2a29d662320d30b9f1.zip
Identify anonymous lifetimes by their DefId in HIR.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs24
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs145
-rw-r--r--compiler/rustc_hir/src/hir.rs4
3 files changed, 104 insertions, 69 deletions
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index b452290dff4..73fdc74b6f0 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -95,6 +95,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
     }
 
     fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
+        debug!(in_scope_lifetimes = ?self.lctx.in_scope_lifetimes);
         self.lctx.with_hir_id_owner(item.id, |lctx| match ctxt {
             AssocCtxt::Trait => hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)),
             AssocCtxt::Impl => hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)),
@@ -118,35 +119,42 @@ impl<'hir> LoweringContext<'_, 'hir> {
     // This should only be used with generics that have already had their
     // in-band lifetimes added. In practice, this means that this function is
     // only used when lowering a child item of a trait or impl.
+    #[tracing::instrument(level = "debug", skip(self, f))]
     fn with_parent_item_lifetime_defs<T>(
         &mut self,
         parent_hir_id: LocalDefId,
         f: impl FnOnce(&mut Self) -> T,
     ) -> T {
-        let old_len = self.in_scope_lifetimes.len();
-
         let parent_generics = match self.owners[parent_hir_id].unwrap().node().expect_item().kind {
             hir::ItemKind::Impl(hir::Impl { ref generics, .. })
             | hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params,
             _ => &[],
         };
-        let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind {
-            hir::GenericParamKind::Lifetime { .. } => Some(param.name.normalize_to_macros_2_0()),
-            _ => None,
-        });
-        self.in_scope_lifetimes.extend(lt_def_names);
+        let lt_def_names = parent_generics
+            .iter()
+            .filter_map(|param| match param.kind {
+                hir::GenericParamKind::Lifetime { .. } => {
+                    Some(param.name.normalize_to_macros_2_0())
+                }
+                _ => None,
+            })
+            .collect();
+        let old_in_scope_lifetimes = mem::replace(&mut self.in_scope_lifetimes, lt_def_names);
+        debug!(in_scope_lifetimes = ?self.in_scope_lifetimes);
 
         let res = f(self);
 
-        self.in_scope_lifetimes.truncate(old_len);
+        self.in_scope_lifetimes = old_in_scope_lifetimes;
         res
     }
 
     // Clears (and restores) the `in_scope_lifetimes` field. Used when
     // visiting nested items, which never inherit in-scope lifetimes
     // from their surrounding environment.
+    #[tracing::instrument(level = "debug", skip(self, f))]
     fn without_in_scope_lifetime_defs<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
         let old_in_scope_lifetimes = mem::replace(&mut self.in_scope_lifetimes, vec![]);
+        debug!(?old_in_scope_lifetimes);
 
         // this vector is only used when walking over impl headers,
         // input types, and the like, and should not be non-empty in
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 7a272308fb0..8799e6ff897 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -136,13 +136,13 @@ struct LoweringContext<'a, 'hir: 'a> {
     /// (i.e., it doesn't appear in the in_scope_lifetimes list), it is added
     /// to this list. The results of this list are then added to the list of
     /// lifetime definitions in the corresponding impl or function generics.
-    lifetimes_to_define: Vec<(Span, ParamName)>,
+    lifetimes_to_define: Vec<(Span, NodeId)>,
 
     /// `true` if in-band lifetimes are being collected. This is used to
     /// indicate whether or not we're in a place where new lifetimes will result
     /// in in-band lifetime definitions, such a function or an impl header,
     /// including implicit lifetimes from `impl_header_lifetime_elision`.
-    is_collecting_anonymous_lifetimes: bool,
+    is_collecting_anonymous_lifetimes: Option<LocalDefId>,
 
     /// Currently in-scope lifetimes defined in impl headers, fn headers, or HRTB.
     /// We always store a `normalize_to_macros_2_0()` version of the param-name in this
@@ -375,7 +375,7 @@ pub fn lower_crate<'a, 'hir>(
         task_context: None,
         current_item: None,
         lifetimes_to_define: Vec::new(),
-        is_collecting_anonymous_lifetimes: false,
+        is_collecting_anonymous_lifetimes: None,
         in_scope_lifetimes: Vec::new(),
         allow_try_trait: Some([sym::try_trait_v2][..].into()),
         allow_gen_future: Some([sym::gen_future][..].into()),
@@ -720,9 +720,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     /// parameter while `f` is running (and restored afterwards).
     fn collect_in_band_defs<T>(
         &mut self,
+        parent_def_id: LocalDefId,
         f: impl FnOnce(&mut Self) -> T,
-    ) -> (Vec<(Span, ParamName)>, T) {
-        let was_collecting = std::mem::replace(&mut self.is_collecting_anonymous_lifetimes, true);
+    ) -> (Vec<(Span, NodeId)>, T) {
+        let was_collecting =
+            std::mem::replace(&mut self.is_collecting_anonymous_lifetimes, Some(parent_def_id));
         let len = self.lifetimes_to_define.len();
 
         let res = f(self);
@@ -733,49 +735,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     }
 
     /// Converts a lifetime into a new generic parameter.
-    fn lifetime_to_generic_param(
+    fn fresh_lifetime_to_generic_param(
         &mut self,
         span: Span,
-        hir_name: ParamName,
-        parent_def_id: LocalDefId,
+        node_id: NodeId,
     ) -> hir::GenericParam<'hir> {
-        let node_id = self.resolver.next_node_id();
-
-        // Get the name we'll use to make the def-path. Note
-        // that collisions are ok here and this shouldn't
-        // really show up for end-user.
-        let (str_name, kind) = match hir_name {
-            ParamName::Plain(ident) => (ident.name, hir::LifetimeParamKind::Explicit),
-            ParamName::Fresh(_) => (kw::UnderscoreLifetime, hir::LifetimeParamKind::Elided),
-            ParamName::Error => (kw::UnderscoreLifetime, hir::LifetimeParamKind::Error),
-        };
-
-        // Add a definition for the in-band lifetime def.
-        self.resolver.create_def(
-            parent_def_id,
-            node_id,
-            DefPathData::LifetimeNs(str_name),
-            ExpnId::root(),
-            span.with_parent(None),
-        );
-
+        let hir_id = self.lower_node_id(node_id);
+        let def_id = self.resolver.local_def_id(node_id);
         hir::GenericParam {
-            hir_id: self.lower_node_id(node_id),
-            name: hir_name,
+            hir_id,
+            name: hir::ParamName::Fresh(def_id),
             bounds: &[],
             span: self.lower_span(span),
             pure_wrt_drop: false,
-            kind: hir::GenericParamKind::Lifetime { kind },
+            kind: hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided },
         }
     }
 
     /// When we have either an elided or `'_` lifetime in an impl
     /// header, we convert it to an in-band lifetime.
     fn collect_fresh_anonymous_lifetime(&mut self, span: Span) -> ParamName {
-        assert!(self.is_collecting_anonymous_lifetimes);
-        let index = self.lifetimes_to_define.len() + self.in_scope_lifetimes.len();
-        let hir_name = ParamName::Fresh(index);
-        self.lifetimes_to_define.push((span, hir_name));
+        let Some(parent_def_id) = self.is_collecting_anonymous_lifetimes else { panic!() };
+
+        let node_id = self.resolver.next_node_id();
+
+        // Add a definition for the in-band lifetime def.
+        let param_def_id = self.resolver.create_def(
+            parent_def_id,
+            node_id,
+            DefPathData::LifetimeNs(kw::UnderscoreLifetime),
+            ExpnId::root(),
+            span.with_parent(None),
+        );
+
+        let hir_name = ParamName::Fresh(param_def_id);
+        self.lifetimes_to_define.push((span, node_id));
         hir_name
     }
 
@@ -817,7 +811,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         f: impl FnOnce(&mut Self, &mut Vec<hir::GenericParam<'hir>>) -> T,
     ) -> (hir::Generics<'hir>, T) {
         let (lifetimes_to_define, (mut lowered_generics, impl_trait_defs, res)) = self
-            .collect_in_band_defs(|this| {
+            .collect_in_band_defs(parent_def_id, |this| {
                 this.with_anonymous_lifetime_mode(anonymous_lifetime_mode, |this| {
                     this.with_in_scope_lifetime_defs(&generics.params, |this| {
                         let mut impl_trait_defs = Vec::new();
@@ -844,9 +838,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         lowered_generics.params.extend(
             lifetimes_to_define
                 .into_iter()
-                .map(|(span, hir_name)| {
-                    self.lifetime_to_generic_param(span, hir_name, parent_def_id)
-                })
+                .map(|(span, node_id)| self.fresh_lifetime_to_generic_param(span, node_id))
                 .chain(impl_trait_defs),
         );
 
@@ -1763,15 +1755,53 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             .in_scope_lifetimes
             .iter()
             .cloned()
-            .map(|name| (name.ident().span, name, hir::LifetimeName::Param(name)))
-            .chain(
-                self.lifetimes_to_define
-                    .iter()
-                    .map(|&(span, name)| (span, name, hir::LifetimeName::Param(name))),
-            )
+            .map(|name| (name.ident().span, hir::LifetimeName::Param(name)))
+            .chain(self.lifetimes_to_define.iter().map(|&(span, node_id)| {
+                let def_id = self.resolver.local_def_id(node_id);
+                let name = hir::ParamName::Fresh(def_id);
+                (span, hir::LifetimeName::Param(name))
+            }))
             .collect();
 
         self.with_hir_id_owner(opaque_ty_node_id, |this| {
+            let mut generic_params: Vec<_> = lifetime_params
+                .iter()
+                .map(|&(span, name)| {
+                    // We can only get lifetime names from the outside.
+                    let hir::LifetimeName::Param(hir_name) = name else { panic!() };
+
+                    let node_id = this.resolver.next_node_id();
+
+                    // Add a definition for the in-band lifetime def.
+                    let def_id = this.resolver.create_def(
+                        opaque_ty_def_id,
+                        node_id,
+                        DefPathData::LifetimeNs(hir_name.ident().name),
+                        ExpnId::root(),
+                        span.with_parent(None),
+                    );
+
+                    let (kind, name) = match hir_name {
+                        ParamName::Plain(ident) => {
+                            (hir::LifetimeParamKind::Explicit, hir::ParamName::Plain(ident))
+                        }
+                        ParamName::Fresh(_) => {
+                            (hir::LifetimeParamKind::Elided, hir::ParamName::Fresh(def_id))
+                        }
+                        ParamName::Error => (hir::LifetimeParamKind::Error, hir::ParamName::Error),
+                    };
+
+                    hir::GenericParam {
+                        hir_id: this.lower_node_id(node_id),
+                        name,
+                        bounds: &[],
+                        span: this.lower_span(span),
+                        pure_wrt_drop: false,
+                        kind: hir::GenericParamKind::Lifetime { kind },
+                    }
+                })
+                .collect();
+
             // We have to be careful to get elision right here. The
             // idea is that we create a lifetime parameter for each
             // lifetime in the return type.  So, given a return type
@@ -1782,25 +1812,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // hence the elision takes place at the fn site.
             let (lifetimes_to_define, future_bound) =
                 this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::CreateParameter, |this| {
-                    this.collect_in_band_defs(|this| {
+                    this.collect_in_band_defs(opaque_ty_def_id, |this| {
                         this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span)
                     })
                 });
             debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound);
             debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", lifetimes_to_define);
 
-            lifetime_params.extend(
-                // Output lifetime like `'_`:
-                lifetimes_to_define
-                    .into_iter()
-                    .map(|(span, name)| (span, name, hir::LifetimeName::Implicit(false))),
-            );
+            // Output lifetime like `'_`:
+            for (span, node_id) in lifetimes_to_define {
+                let param = this.fresh_lifetime_to_generic_param(span, node_id);
+                lifetime_params.push((span, hir::LifetimeName::Implicit(false)));
+                generic_params.push(param);
+            }
+            let generic_params = this.arena.alloc_from_iter(generic_params);
             debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params);
-
-            let generic_params =
-                this.arena.alloc_from_iter(lifetime_params.iter().map(|&(span, hir_name, _)| {
-                    this.lifetime_to_generic_param(span, hir_name, opaque_ty_def_id)
-                }));
+            debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
 
             let opaque_ty_item = hir::OpaqueTy {
                 generics: hir::Generics {
@@ -1833,7 +1860,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         // For the "output" lifetime parameters, we just want to
         // generate `'_`.
         let generic_args =
-            self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, _, name)| {
+            self.arena.alloc_from_iter(lifetime_params.into_iter().map(|(span, name)| {
                 GenericArg::Lifetime(hir::Lifetime {
                     hir_id: self.next_id(),
                     span: self.lower_span(span),
@@ -1969,7 +1996,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let (name, kind) = match param.kind {
             GenericParamKind::Lifetime => {
                 let was_collecting_in_band = self.is_collecting_anonymous_lifetimes;
-                self.is_collecting_anonymous_lifetimes = false;
+                self.is_collecting_anonymous_lifetimes = None;
 
                 let lt = self
                     .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index c3795e48d76..64ce196e440 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -59,7 +59,7 @@ pub enum ParamName {
     ///
     /// where `'f` is something like `Fresh(0)`. The indices are
     /// unique per impl, but not necessarily continuous.
-    Fresh(usize),
+    Fresh(LocalDefId),
 
     /// Indicates an illegal name was given and an error has been
     /// reported (so we should squelch other derived errors). Occurs
@@ -3303,7 +3303,7 @@ mod size_asserts {
     rustc_data_structures::static_assert_size!(super::Expr<'static>, 56);
     rustc_data_structures::static_assert_size!(super::Pat<'static>, 88);
     rustc_data_structures::static_assert_size!(super::QPath<'static>, 24);
-    rustc_data_structures::static_assert_size!(super::Ty<'static>, 80);
+    rustc_data_structures::static_assert_size!(super::Ty<'static>, 72);
 
     rustc_data_structures::static_assert_size!(super::Item<'static>, 184);
     rustc_data_structures::static_assert_size!(super::TraitItem<'static>, 128);