about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_expand/src/base.rs4
-rw-r--r--compiler/rustc_expand/src/expand.rs10
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs18
-rw-r--r--compiler/rustc_resolve/src/lib.rs6
-rw-r--r--compiler/rustc_resolve/src/macros.rs4
-rw-r--r--tests/crashes/140333.rs9
-rw-r--r--tests/ui/impl-trait/name-mentioning-macro.rs12
-rw-r--r--tests/ui/impl-trait/name-mentioning-macro.stderr16
-rw-r--r--tests/ui/impl-trait/struct-field-fragment-in-name.rs16
9 files changed, 77 insertions, 18 deletions
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 7a29f8c9fbd..fe76d9e0b64 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1118,6 +1118,10 @@ pub trait ResolverExpand {
         trait_def_id: DefId,
         impl_def_id: LocalDefId,
     ) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>;
+
+    /// Record the name of an opaque `Ty::ImplTrait` pre-expansion so that it can be used
+    /// to generate an item name later that does not reference placeholder macros.
+    fn insert_impl_trait_name(&mut self, id: NodeId, name: Symbol);
 }
 
 pub trait LintStoreExpand {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 0474413e762..2de09aa1a28 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1778,6 +1778,16 @@ impl InvocationCollectorNode for ast::Ty {
         fragment.make_ty()
     }
     fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {
+        // Save the pre-expanded name of this `ImplTrait`, so that later when defining
+        // an APIT we use a name that doesn't have any placeholder fragments in it.
+        if let ast::TyKind::ImplTrait(..) = self.kind {
+            // HACK: pprust breaks strings with newlines when the type
+            // gets too long. We don't want these to show up in compiler
+            // output or built artifacts, so replace them here...
+            // Perhaps we should instead format APITs more robustly.
+            let name = Symbol::intern(&pprust::ty_to_string(self).replace('\n', " "));
+            collector.cx.resolver.insert_impl_trait_name(self.id, name);
+        }
         walk_ty(collector, self)
     }
     fn is_mac_call(&self) -> bool {
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 16852d1661e..1e345b11c14 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -2,12 +2,12 @@ use std::mem;
 
 use rustc_ast::visit::FnKind;
 use rustc_ast::*;
-use rustc_ast_pretty::pprust;
 use rustc_attr_parsing::{AttributeParser, Early, OmitDoc};
 use rustc_expand::expand::AstFragment;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind};
 use rustc_hir::def_id::LocalDefId;
+use rustc_middle::span_bug;
 use rustc_span::hygiene::LocalExpnId;
 use rustc_span::{Span, Symbol, sym};
 use tracing::debug;
@@ -380,20 +380,20 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
     }
 
     fn visit_ty(&mut self, ty: &'a Ty) {
-        match &ty.kind {
+        match ty.kind {
             TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
-            TyKind::ImplTrait(id, _) => {
-                // HACK: pprust breaks strings with newlines when the type
-                // gets too long. We don't want these to show up in compiler
-                // output or built artifacts, so replace them here...
-                // Perhaps we should instead format APITs more robustly.
-                let name = Symbol::intern(&pprust::ty_to_string(ty).replace('\n', " "));
+            TyKind::ImplTrait(opaque_id, _) => {
+                let name = *self
+                    .resolver
+                    .impl_trait_names
+                    .get(&ty.id)
+                    .unwrap_or_else(|| span_bug!(ty.span, "expected this opaque to be named"));
                 let kind = match self.invocation_parent.impl_trait_context {
                     ImplTraitContext::Universal => DefKind::TyParam,
                     ImplTraitContext::Existential => DefKind::OpaqueTy,
                     ImplTraitContext::InBinding => return visit::walk_ty(self, ty),
                 };
-                let id = self.create_def(*id, Some(name), kind, ty.span);
+                let id = self.create_def(opaque_id, Some(name), kind, ty.span);
                 match self.invocation_parent.impl_trait_context {
                     // Do not nest APIT, as we desugar them as `impl_trait: bounds`,
                     // so the `impl_trait` node is not a parent to `bounds`.
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index f0540725416..05bc3611dd8 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1224,6 +1224,11 @@ pub struct Resolver<'ra, 'tcx> {
     current_crate_outer_attr_insert_span: Span,
 
     mods_with_parse_errors: FxHashSet<DefId>,
+
+    // Stores pre-expansion and pre-placeholder-fragment-insertion names for `impl Trait` types
+    // that were encountered during resolution. These names are used to generate item names
+    // for APITs, so we don't want to leak details of resolution into these names.
+    impl_trait_names: FxHashMap<NodeId, Symbol>,
 }
 
 /// This provides memory for the rest of the crate. The `'ra` lifetime that is
@@ -1579,6 +1584,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             impl_binding_keys: Default::default(),
             current_crate_outer_attr_insert_span,
             mods_with_parse_errors: Default::default(),
+            impl_trait_names: Default::default(),
         };
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 1b82e9c9799..3d33a02a9c6 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -522,6 +522,10 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
         });
         Ok(idents)
     }
+
+    fn insert_impl_trait_name(&mut self, id: NodeId, name: Symbol) {
+        self.impl_trait_names.insert(id, name);
+    }
 }
 
 impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
diff --git a/tests/crashes/140333.rs b/tests/crashes/140333.rs
deleted file mode 100644
index cec1100e6ad..00000000000
--- a/tests/crashes/140333.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: #140333
-fn a() -> impl b<
-    [c; {
-        struct d {
-            #[a]
-            bar: e,
-        }
-    }],
->;
diff --git a/tests/ui/impl-trait/name-mentioning-macro.rs b/tests/ui/impl-trait/name-mentioning-macro.rs
new file mode 100644
index 00000000000..8a81911c0bb
--- /dev/null
+++ b/tests/ui/impl-trait/name-mentioning-macro.rs
@@ -0,0 +1,12 @@
+trait Foo<T> {}
+
+macro_rules! bar {
+    () => { () }
+}
+
+fn foo(x: impl Foo<bar!()>) {
+    let () = x;
+    //~^ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/name-mentioning-macro.stderr b/tests/ui/impl-trait/name-mentioning-macro.stderr
new file mode 100644
index 00000000000..adb4c64f812
--- /dev/null
+++ b/tests/ui/impl-trait/name-mentioning-macro.stderr
@@ -0,0 +1,16 @@
+error[E0308]: mismatched types
+  --> $DIR/name-mentioning-macro.rs:8:9
+   |
+LL | fn foo(x: impl Foo<bar!()>) {
+   |           ---------------- expected this type parameter
+LL |     let () = x;
+   |         ^^   - this expression has type `impl Foo<bar!()>`
+   |         |
+   |         expected type parameter `impl Foo<bar!()>`, found `()`
+   |
+   = note: expected type parameter `impl Foo<bar!()>`
+                   found unit type `()`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/struct-field-fragment-in-name.rs b/tests/ui/impl-trait/struct-field-fragment-in-name.rs
new file mode 100644
index 00000000000..b98cd864ccb
--- /dev/null
+++ b/tests/ui/impl-trait/struct-field-fragment-in-name.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+
+trait Trait<T> {}
+
+fn a(_: impl Trait<
+    [(); {
+        struct D {
+            #[rustfmt::skip]
+            bar: (),
+        }
+        0
+    }],
+>) {
+}
+
+fn main() {}