Don't give APITs names with macro expansion placeholder fragments in it
This commit is contained in:
parent
2801f9aaf9
commit
8cd3fa04e2
9 changed files with 77 additions and 18 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
//@ known-bug: #140333
|
||||
fn a() -> impl b<
|
||||
[c; {
|
||||
struct d {
|
||||
#[a]
|
||||
bar: e,
|
||||
}
|
||||
}],
|
||||
>;
|
||||
12
tests/ui/impl-trait/name-mentioning-macro.rs
Normal file
12
tests/ui/impl-trait/name-mentioning-macro.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
trait Foo<T> {}
|
||||
|
||||
macro_rules! bar {
|
||||
() => { () }
|
||||
}
|
||||
|
||||
fn foo(x: impl Foo<bar!()>) {
|
||||
let () = x;
|
||||
//~^ ERROR mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
16
tests/ui/impl-trait/name-mentioning-macro.stderr
Normal file
16
tests/ui/impl-trait/name-mentioning-macro.stderr
Normal file
|
|
@ -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`.
|
||||
16
tests/ui/impl-trait/struct-field-fragment-in-name.rs
Normal file
16
tests/ui/impl-trait/struct-field-fragment-in-name.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//@ check-pass
|
||||
|
||||
trait Trait<T> {}
|
||||
|
||||
fn a(_: impl Trait<
|
||||
[(); {
|
||||
struct D {
|
||||
#[rustfmt::skip]
|
||||
bar: (),
|
||||
}
|
||||
0
|
||||
}],
|
||||
>) {
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue