Skip to content

Commit bf2f1af

Browse files
Don't give APITs names with macro expansion placeholder fragments in it
1 parent 95cd989 commit bf2f1af

File tree

9 files changed

+78
-19
lines changed

9 files changed

+78
-19
lines changed

compiler/rustc_expand/src/base.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,10 @@ pub trait ResolverExpand {
11181118
trait_def_id: DefId,
11191119
impl_def_id: LocalDefId,
11201120
) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>;
1121+
1122+
/// Record the name of an opaque `Ty::ImplTrait` pre-expansion so that it can be used
1123+
/// to generate an item name later that does not reference placeholder macros.
1124+
fn insert_impl_trait_name(&mut self, id: NodeId, name: Symbol);
11211125
}
11221126

11231127
pub trait LintStoreExpand {

compiler/rustc_expand/src/expand.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
2626
use rustc_session::parse::feature_err;
2727
use rustc_session::{Limit, Session};
2828
use rustc_span::hygiene::SyntaxContext;
29-
use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, sym};
29+
use rustc_span::{ErrorGuaranteed, FileName, Ident, LocalExpnId, Span, Symbol, sym};
3030
use smallvec::SmallVec;
3131

3232
use crate::base::*;
@@ -1778,6 +1778,16 @@ impl InvocationCollectorNode for ast::Ty {
17781778
fragment.make_ty()
17791779
}
17801780
fn walk(&mut self, collector: &mut InvocationCollector<'_, '_>) {
1781+
// Save the pre-expanded name of this `ImplTrait`, so that later when defining
1782+
// an APIT we use a name that doesn't have any placeholder fragments in it.
1783+
if let ast::TyKind::ImplTrait(..) = self.kind {
1784+
// HACK: pprust breaks strings with newlines when the type
1785+
// gets too long. We don't want these to show up in compiler
1786+
// output or built artifacts, so replace them here...
1787+
// Perhaps we should instead format APITs more robustly.
1788+
let name = Symbol::intern(&pprust::ty_to_string(self).replace('\n', " "));
1789+
collector.cx.resolver.insert_impl_trait_name(self.id, name);
1790+
}
17811791
walk_ty(collector, self)
17821792
}
17831793
fn is_mac_call(&self) -> bool {

compiler/rustc_resolve/src/def_collector.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ use std::mem;
22

33
use rustc_ast::visit::FnKind;
44
use rustc_ast::*;
5-
use rustc_ast_pretty::pprust;
65
use rustc_attr_parsing::{AttributeParser, OmitDoc};
76
use rustc_expand::expand::AstFragment;
87
use rustc_hir as hir;
98
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
109
use rustc_hir::def_id::LocalDefId;
10+
use rustc_middle::span_bug;
1111
use rustc_span::hygiene::LocalExpnId;
1212
use rustc_span::{Span, Symbol, sym};
1313
use tracing::debug;
@@ -380,20 +380,20 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
380380
}
381381

382382
fn visit_ty(&mut self, ty: &'a Ty) {
383-
match &ty.kind {
383+
match ty.kind {
384384
TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
385-
TyKind::ImplTrait(id, _) => {
386-
// HACK: pprust breaks strings with newlines when the type
387-
// gets too long. We don't want these to show up in compiler
388-
// output or built artifacts, so replace them here...
389-
// Perhaps we should instead format APITs more robustly.
390-
let name = Symbol::intern(&pprust::ty_to_string(ty).replace('\n', " "));
385+
TyKind::ImplTrait(opaque_id, _) => {
386+
let name = *self
387+
.resolver
388+
.impl_trait_names
389+
.get(&ty.id)
390+
.unwrap_or_else(|| span_bug!(ty.span, "expected this opaque to be named"));
391391
let kind = match self.invocation_parent.impl_trait_context {
392392
ImplTraitContext::Universal => DefKind::TyParam,
393393
ImplTraitContext::Existential => DefKind::OpaqueTy,
394394
ImplTraitContext::InBinding => return visit::walk_ty(self, ty),
395395
};
396-
let id = self.create_def(*id, Some(name), kind, ty.span);
396+
let id = self.create_def(opaque_id, Some(name), kind, ty.span);
397397
match self.invocation_parent.impl_trait_context {
398398
// Do not nest APIT, as we desugar them as `impl_trait: bounds`,
399399
// so the `impl_trait` node is not a parent to `bounds`.

compiler/rustc_resolve/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,11 @@ pub struct Resolver<'ra, 'tcx> {
12241224
current_crate_outer_attr_insert_span: Span,
12251225

12261226
mods_with_parse_errors: FxHashSet<DefId>,
1227+
1228+
// Stores pre-expansion and pre-placeholder-fragment-insertion names for `impl Trait` types
1229+
// that were encountered during resolution. These names are used to generate item names
1230+
// for APITs, so we don't want to leak details of resolution into these names.
1231+
impl_trait_names: FxHashMap<NodeId, Symbol>,
12271232
}
12281233

12291234
/// This provides memory for the rest of the crate. The `'ra` lifetime that is
@@ -1579,6 +1584,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
15791584
impl_binding_keys: Default::default(),
15801585
current_crate_outer_attr_insert_span,
15811586
mods_with_parse_errors: Default::default(),
1587+
impl_trait_names: Default::default(),
15821588
};
15831589

15841590
let root_parent_scope = ParentScope::module(graph_root, &resolver);

compiler/rustc_resolve/src/macros.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,10 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
522522
});
523523
Ok(idents)
524524
}
525+
526+
fn insert_impl_trait_name(&mut self, id: NodeId, name: Symbol) {
527+
self.impl_trait_names.insert(id, name);
528+
}
525529
}
526530

527531
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {

tests/crashes/140333.rs

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
trait Foo<T> {}
2+
3+
macro_rules! bar {
4+
() => { () }
5+
}
6+
7+
fn foo(x: impl Foo<bar!()>) {
8+
let () = x;
9+
//~^ ERROR mismatched types
10+
}
11+
12+
fn main() {}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/name-mentioning-macro.rs:8:9
3+
|
4+
LL | fn foo(x: impl Foo<bar!()>) {
5+
| ---------------- expected this type parameter
6+
LL | let () = x;
7+
| ^^ - this expression has type `impl Foo<bar!()>`
8+
| |
9+
| expected type parameter `impl Foo<bar!()>`, found `()`
10+
|
11+
= note: expected type parameter `impl Foo<bar!()>`
12+
found unit type `()`
13+
14+
error: aborting due to 1 previous error
15+
16+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ check-pass
2+
3+
trait Trait<T> {}
4+
5+
fn a(_: impl Trait<
6+
[(); {
7+
struct D {
8+
#[rustfmt::skip]
9+
bar: (),
10+
}
11+
0
12+
}],
13+
>) {
14+
}
15+
16+
fn main() {}

0 commit comments

Comments
 (0)