2021-02-13 20:41:02 +01:00
|
|
|
use std::mem;
|
2024-07-29 08:13:50 +10:00
|
|
|
|
2023-11-10 10:11:24 +08:00
|
|
|
use rustc_ast::visit::FnKind;
|
2020-04-27 23:26:11 +05:30
|
|
|
use rustc_ast::*;
|
2024-08-24 01:44:52 +00:00
|
|
|
use rustc_ast_pretty::pprust;
|
2019-12-29 17:23:55 +03:00
|
|
|
use rustc_expand::expand::AstFragment;
|
2024-05-07 14:43:23 +02:00
|
|
|
use rustc_hir as hir;
|
2023-11-21 23:40:23 +03:00
|
|
|
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
|
2019-11-03 14:36:59 +02:00
|
|
|
use rustc_hir::def_id::LocalDefId;
|
2021-06-25 20:43:04 +02:00
|
|
|
use rustc_span::hygiene::LocalExpnId;
|
2023-12-03 12:29:59 +03:00
|
|
|
use rustc_span::symbol::{kw, sym, Symbol};
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::Span;
|
2024-05-10 13:46:24 +10:00
|
|
|
use tracing::debug;
|
2016-04-14 12:14:03 +12:00
|
|
|
|
Fix anon const def-creation when macros are involved
Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s,
which don't have associated `DefId`s. To deal with the fact that we don't have
resolution information in `DefCollector`, we decided to implement a process
where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we
would avoid creating a def for it in `DefCollector`. If later, in AST lowering,
we realized it turned out to be a unit struct literal, or we were lowering it
to something that didn't use `hir::ConstArg`, we'd create its def there.
However, let's say we have a macro `m!()` that expands to a reference to a free
constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`),
then in def collection, it appears to be a nontrivial anon const and we create
a def. But the macro expands to something that looks like a trivial const arg,
but is not, so in AST lowering we "fix" the mistake we assumed def collection
made and create a def for it. This causes a duplicate definition ICE.
The ideal long-term fix for this is a bit unclear. One option is to delay def
creation for all expression-like nodes until AST lowering (see #128844 for an
incomplete attempt at this). This would avoid issues like this one that are
caused by hacky workarounds. However, this approach has some downsides as well,
and the best approach is yet to be determined.
In the meantime, this PR fixes the bug by delaying def creation for anon consts
whose bodies are macro invocations until after we expand the macro and know
what is inside it. This is accomplished by adding information to create the
anon const's def to the data in `Resolver.invocation_parents`.
2024-08-15 14:36:10 -07:00
|
|
|
use crate::{ImplTraitContext, InvocationParent, PendingAnonConstInfo, Resolver};
|
2024-07-29 08:13:50 +10:00
|
|
|
|
2022-05-20 19:51:09 -04:00
|
|
|
pub(crate) fn collect_definitions(
|
2022-12-08 12:59:02 +00:00
|
|
|
resolver: &mut Resolver<'_, '_>,
|
2019-11-23 18:19:57 +03:00
|
|
|
fragment: &AstFragment,
|
2021-06-25 20:43:04 +02:00
|
|
|
expansion: LocalExpnId,
|
2019-11-23 18:19:57 +03:00
|
|
|
) {
|
Fix anon const def-creation when macros are involved
Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s,
which don't have associated `DefId`s. To deal with the fact that we don't have
resolution information in `DefCollector`, we decided to implement a process
where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we
would avoid creating a def for it in `DefCollector`. If later, in AST lowering,
we realized it turned out to be a unit struct literal, or we were lowering it
to something that didn't use `hir::ConstArg`, we'd create its def there.
However, let's say we have a macro `m!()` that expands to a reference to a free
constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`),
then in def collection, it appears to be a nontrivial anon const and we create
a def. But the macro expands to something that looks like a trivial const arg,
but is not, so in AST lowering we "fix" the mistake we assumed def collection
made and create a def for it. This causes a duplicate definition ICE.
The ideal long-term fix for this is a bit unclear. One option is to delay def
creation for all expression-like nodes until AST lowering (see #128844 for an
incomplete attempt at this). This would avoid issues like this one that are
caused by hacky workarounds. However, this approach has some downsides as well,
and the best approach is yet to be determined.
In the meantime, this PR fixes the bug by delaying def creation for anon consts
whose bodies are macro invocations until after we expand the macro and know
what is inside it. This is accomplished by adding information to create the
anon const's def to the data in `Resolver.invocation_parents`.
2024-08-15 14:36:10 -07:00
|
|
|
let InvocationParent { parent_def, pending_anon_const_info, impl_trait_context, in_attr } =
|
|
|
|
resolver.invocation_parents[&expansion];
|
|
|
|
let mut visitor = DefCollector {
|
|
|
|
resolver,
|
|
|
|
parent_def,
|
|
|
|
pending_anon_const_info,
|
|
|
|
expansion,
|
|
|
|
impl_trait_context,
|
|
|
|
in_attr,
|
|
|
|
};
|
2024-06-26 13:00:51 +03:00
|
|
|
fragment.visit_with(&mut visitor);
|
2019-11-23 18:19:57 +03:00
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Creates `DefId`s for nodes in the AST.
|
2024-09-10 16:19:40 +10:00
|
|
|
struct DefCollector<'a, 'ra, 'tcx> {
|
|
|
|
resolver: &'a mut Resolver<'ra, 'tcx>,
|
2019-11-03 14:36:59 +02:00
|
|
|
parent_def: LocalDefId,
|
Fix anon const def-creation when macros are involved
Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s,
which don't have associated `DefId`s. To deal with the fact that we don't have
resolution information in `DefCollector`, we decided to implement a process
where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we
would avoid creating a def for it in `DefCollector`. If later, in AST lowering,
we realized it turned out to be a unit struct literal, or we were lowering it
to something that didn't use `hir::ConstArg`, we'd create its def there.
However, let's say we have a macro `m!()` that expands to a reference to a free
constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`),
then in def collection, it appears to be a nontrivial anon const and we create
a def. But the macro expands to something that looks like a trivial const arg,
but is not, so in AST lowering we "fix" the mistake we assumed def collection
made and create a def for it. This causes a duplicate definition ICE.
The ideal long-term fix for this is a bit unclear. One option is to delay def
creation for all expression-like nodes until AST lowering (see #128844 for an
incomplete attempt at this). This would avoid issues like this one that are
caused by hacky workarounds. However, this approach has some downsides as well,
and the best approach is yet to be determined.
In the meantime, this PR fixes the bug by delaying def creation for anon consts
whose bodies are macro invocations until after we expand the macro and know
what is inside it. This is accomplished by adding information to create the
anon const's def to the data in `Resolver.invocation_parents`.
2024-08-15 14:36:10 -07:00
|
|
|
/// If we have an anon const that consists of a macro invocation, e.g. `Foo<{ m!() }>`,
|
|
|
|
/// we need to wait until we know what the macro expands to before we create the def for
|
|
|
|
/// the anon const. That's because we lower some anon consts into `hir::ConstArgKind::Path`,
|
|
|
|
/// which don't have defs.
|
|
|
|
///
|
|
|
|
/// See `Self::visit_anon_const()`.
|
|
|
|
pending_anon_const_info: Option<PendingAnonConstInfo>,
|
2021-02-13 20:41:02 +01:00
|
|
|
impl_trait_context: ImplTraitContext,
|
2024-06-26 13:00:51 +03:00
|
|
|
in_attr: bool,
|
2021-06-25 20:43:04 +02:00
|
|
|
expansion: LocalExpnId,
|
2016-04-14 12:14:03 +12:00
|
|
|
}
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
|
2023-11-21 23:40:23 +03:00
|
|
|
fn create_def(
|
|
|
|
&mut self,
|
|
|
|
node_id: NodeId,
|
2023-12-03 12:29:59 +03:00
|
|
|
name: Symbol,
|
2023-11-21 23:40:23 +03:00
|
|
|
def_kind: DefKind,
|
|
|
|
span: Span,
|
|
|
|
) -> LocalDefId {
|
2019-07-02 23:42:00 +03:00
|
|
|
let parent_def = self.parent_def;
|
2023-12-03 12:29:59 +03:00
|
|
|
debug!(
|
|
|
|
"create_def(node_id={:?}, def_kind={:?}, parent_def={:?})",
|
|
|
|
node_id, def_kind, parent_def
|
|
|
|
);
|
2024-02-14 14:49:16 +00:00
|
|
|
self.resolver
|
|
|
|
.create_def(
|
|
|
|
parent_def,
|
|
|
|
node_id,
|
|
|
|
name,
|
|
|
|
def_kind,
|
|
|
|
self.expansion.to_expn_id(),
|
|
|
|
span.with_parent(None),
|
|
|
|
)
|
|
|
|
.def_id()
|
2016-04-14 12:14:03 +12:00
|
|
|
}
|
|
|
|
|
2019-11-03 14:36:59 +02:00
|
|
|
fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: LocalDefId, f: F) {
|
2024-06-26 13:00:51 +03:00
|
|
|
let orig_parent_def = mem::replace(&mut self.parent_def, parent_def);
|
2016-04-14 17:24:30 +12:00
|
|
|
f(self);
|
2019-07-02 23:42:00 +03:00
|
|
|
self.parent_def = orig_parent_def;
|
2016-04-14 17:24:30 +12:00
|
|
|
}
|
2016-05-02 23:11:19 +03:00
|
|
|
|
2021-02-13 20:41:02 +01:00
|
|
|
fn with_impl_trait<F: FnOnce(&mut Self)>(
|
|
|
|
&mut self,
|
|
|
|
impl_trait_context: ImplTraitContext,
|
|
|
|
f: F,
|
|
|
|
) {
|
2024-06-26 13:00:51 +03:00
|
|
|
let orig_itc = mem::replace(&mut self.impl_trait_context, impl_trait_context);
|
2021-02-13 20:41:02 +01:00
|
|
|
f(self);
|
|
|
|
self.impl_trait_context = orig_itc;
|
|
|
|
}
|
|
|
|
|
2021-03-16 00:36:07 +03:00
|
|
|
fn collect_field(&mut self, field: &'a FieldDef, index: Option<usize>) {
|
2019-11-23 14:16:38 +03:00
|
|
|
let index = |this: &Self| {
|
|
|
|
index.unwrap_or_else(|| {
|
|
|
|
let node_id = NodeId::placeholder_from_expn_id(this.expansion);
|
2020-06-20 19:59:29 +01:00
|
|
|
this.resolver.placeholder_field_indices[&node_id]
|
2019-11-23 14:16:38 +03:00
|
|
|
})
|
|
|
|
};
|
|
|
|
|
2019-09-14 17:36:27 +03:00
|
|
|
if field.is_placeholder {
|
2020-06-20 19:59:29 +01:00
|
|
|
let old_index = self.resolver.placeholder_field_indices.insert(field.id, index(self));
|
|
|
|
assert!(old_index.is_none(), "placeholder field index is reset for a node ID");
|
2019-09-14 17:36:27 +03:00
|
|
|
self.visit_macro_invoc(field.id);
|
|
|
|
} else {
|
2019-11-23 14:16:38 +03:00
|
|
|
let name = field.ident.map_or_else(|| sym::integer(index(self)), |ident| ident.name);
|
2023-12-03 12:29:59 +03:00
|
|
|
let def = self.create_def(field.id, name, DefKind::Field, field.span);
|
2021-03-16 00:36:07 +03:00
|
|
|
self.with_parent(def, |this| visit::walk_field_def(this, field));
|
2024-01-06 18:22:37 +08:00
|
|
|
self.visit_anon_adt(&field.ty);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_anon_adt(&mut self, ty: &'a Ty) {
|
|
|
|
let def_kind = match &ty.kind {
|
|
|
|
TyKind::AnonStruct(..) => DefKind::Struct,
|
|
|
|
TyKind::AnonUnion(..) => DefKind::Union,
|
|
|
|
_ => return,
|
|
|
|
};
|
|
|
|
match &ty.kind {
|
|
|
|
TyKind::AnonStruct(node_id, _) | TyKind::AnonUnion(node_id, _) => {
|
|
|
|
let def_id = self.create_def(*node_id, kw::Empty, def_kind, ty.span);
|
|
|
|
self.with_parent(def_id, |this| visit::walk_ty(this, ty));
|
|
|
|
}
|
|
|
|
_ => {}
|
2019-09-14 17:36:27 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-10 01:41:47 +03:00
|
|
|
fn visit_macro_invoc(&mut self, id: NodeId) {
|
2021-02-13 20:41:02 +01:00
|
|
|
let id = id.placeholder_to_expn_id();
|
Fix anon const def-creation when macros are involved
Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s,
which don't have associated `DefId`s. To deal with the fact that we don't have
resolution information in `DefCollector`, we decided to implement a process
where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we
would avoid creating a def for it in `DefCollector`. If later, in AST lowering,
we realized it turned out to be a unit struct literal, or we were lowering it
to something that didn't use `hir::ConstArg`, we'd create its def there.
However, let's say we have a macro `m!()` that expands to a reference to a free
constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`),
then in def collection, it appears to be a nontrivial anon const and we create
a def. But the macro expands to something that looks like a trivial const arg,
but is not, so in AST lowering we "fix" the mistake we assumed def collection
made and create a def for it. This causes a duplicate definition ICE.
The ideal long-term fix for this is a bit unclear. One option is to delay def
creation for all expression-like nodes until AST lowering (see #128844 for an
incomplete attempt at this). This would avoid issues like this one that are
caused by hacky workarounds. However, this approach has some downsides as well,
and the best approach is yet to be determined.
In the meantime, this PR fixes the bug by delaying def creation for anon consts
whose bodies are macro invocations until after we expand the macro and know
what is inside it. This is accomplished by adding information to create the
anon const's def to the data in `Resolver.invocation_parents`.
2024-08-15 14:36:10 -07:00
|
|
|
let pending_anon_const_info = self.pending_anon_const_info.take();
|
|
|
|
let old_parent = self.resolver.invocation_parents.insert(
|
|
|
|
id,
|
|
|
|
InvocationParent {
|
|
|
|
parent_def: self.parent_def,
|
|
|
|
pending_anon_const_info,
|
|
|
|
impl_trait_context: self.impl_trait_context,
|
|
|
|
in_attr: self.in_attr,
|
|
|
|
},
|
|
|
|
);
|
2020-06-20 19:59:29 +01:00
|
|
|
assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
|
2016-09-14 09:55:20 +00:00
|
|
|
}
|
2016-04-14 12:14:03 +12:00
|
|
|
}
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_item(&mut self, i: &'a Item) {
|
2016-04-14 12:14:03 +12:00
|
|
|
// Pick the def data. This need not be unique, but the more
|
2018-05-22 14:31:56 +02:00
|
|
|
// information we encapsulate into, the better
|
2023-11-21 23:40:23 +03:00
|
|
|
let mut opt_macro_data = None;
|
2023-12-03 12:29:59 +03:00
|
|
|
let def_kind = match &i.kind {
|
|
|
|
ItemKind::Impl(i) => DefKind::Impl { of_trait: i.of_trait.is_some() },
|
|
|
|
ItemKind::ForeignMod(..) => DefKind::ForeignMod,
|
|
|
|
ItemKind::Mod(..) => DefKind::Mod,
|
|
|
|
ItemKind::Trait(..) => DefKind::Trait,
|
|
|
|
ItemKind::TraitAlias(..) => DefKind::TraitAlias,
|
|
|
|
ItemKind::Enum(..) => DefKind::Enum,
|
|
|
|
ItemKind::Struct(..) => DefKind::Struct,
|
|
|
|
ItemKind::Union(..) => DefKind::Union,
|
|
|
|
ItemKind::ExternCrate(..) => DefKind::ExternCrate,
|
|
|
|
ItemKind::TyAlias(..) => DefKind::TyAlias,
|
2024-05-07 14:43:23 +02:00
|
|
|
ItemKind::Static(s) => DefKind::Static {
|
|
|
|
safety: hir::Safety::Safe,
|
|
|
|
mutability: s.mutability,
|
|
|
|
nested: false,
|
|
|
|
},
|
2023-12-03 12:29:59 +03:00
|
|
|
ItemKind::Const(..) => DefKind::Const,
|
2023-11-26 15:57:31 +03:00
|
|
|
ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn,
|
2023-11-21 23:40:23 +03:00
|
|
|
ItemKind::MacroDef(..) => {
|
|
|
|
let macro_data = self.resolver.compile_macro(i, self.resolver.tcx.sess.edition());
|
|
|
|
let macro_kind = macro_data.ext.macro_kind();
|
|
|
|
opt_macro_data = Some(macro_data);
|
2023-12-03 12:29:59 +03:00
|
|
|
DefKind::Macro(macro_kind)
|
2018-06-06 15:50:59 -07:00
|
|
|
}
|
2023-12-03 12:29:59 +03:00
|
|
|
ItemKind::GlobalAsm(..) => DefKind::GlobalAsm,
|
2024-04-24 19:56:56 +03:00
|
|
|
ItemKind::Use(..) => return visit::walk_item(self, i),
|
2024-03-15 14:21:03 +03:00
|
|
|
ItemKind::MacCall(..) | ItemKind::DelegationMac(..) => {
|
|
|
|
return self.visit_macro_invoc(i.id);
|
|
|
|
}
|
2016-04-14 12:14:03 +12:00
|
|
|
};
|
2023-12-03 12:29:59 +03:00
|
|
|
let def_id = self.create_def(i.id, i.ident.name, def_kind, i.span);
|
2016-04-14 12:14:03 +12:00
|
|
|
|
2023-11-21 23:40:23 +03:00
|
|
|
if let Some(macro_data) = opt_macro_data {
|
2023-11-24 23:39:42 +03:00
|
|
|
self.resolver.macro_map.insert(def_id.to_def_id(), macro_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
self.with_parent(def_id, |this| {
|
2021-02-13 20:41:02 +01:00
|
|
|
this.with_impl_trait(ImplTraitContext::Existential, |this| {
|
|
|
|
match i.kind {
|
|
|
|
ItemKind::Struct(ref struct_def, _) | ItemKind::Union(ref struct_def, _) => {
|
|
|
|
// If this is a unit or tuple-like struct, register the constructor.
|
2023-11-21 23:40:23 +03:00
|
|
|
if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(struct_def) {
|
|
|
|
this.create_def(
|
|
|
|
ctor_node_id,
|
2023-12-03 12:29:59 +03:00
|
|
|
kw::Empty,
|
2023-11-21 23:40:23 +03:00
|
|
|
DefKind::Ctor(CtorOf::Struct, ctor_kind),
|
|
|
|
i.span,
|
|
|
|
);
|
2021-02-13 20:41:02 +01:00
|
|
|
}
|
2016-04-14 17:24:30 +12:00
|
|
|
}
|
2021-02-13 20:41:02 +01:00
|
|
|
_ => {}
|
2016-04-14 12:14:03 +12:00
|
|
|
}
|
2021-02-13 20:41:02 +01:00
|
|
|
visit::walk_item(this, i);
|
|
|
|
})
|
2016-04-14 17:24:30 +12:00
|
|
|
});
|
2016-04-14 12:14:03 +12:00
|
|
|
}
|
|
|
|
|
2020-03-14 22:22:29 +03:00
|
|
|
fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
|
2024-08-24 01:44:52 +00:00
|
|
|
match fn_kind {
|
|
|
|
FnKind::Fn(_ctxt, _ident, FnSig { header, decl, span: _ }, _vis, generics, body)
|
|
|
|
if let Some(coroutine_kind) = header.coroutine_kind =>
|
|
|
|
{
|
|
|
|
self.visit_fn_header(header);
|
|
|
|
self.visit_generics(generics);
|
|
|
|
|
|
|
|
// For async functions, we need to create their inner defs inside of a
|
|
|
|
// closure to match their desugared representation. Besides that,
|
|
|
|
// we must mirror everything that `visit::walk_fn` below does.
|
|
|
|
let FnDecl { inputs, output } = &**decl;
|
|
|
|
for param in inputs {
|
|
|
|
self.visit_param(param);
|
|
|
|
}
|
|
|
|
|
|
|
|
let (return_id, return_span) = coroutine_kind.return_id();
|
|
|
|
let return_def =
|
|
|
|
self.create_def(return_id, kw::Empty, DefKind::OpaqueTy, return_span);
|
|
|
|
self.with_parent(return_def, |this| this.visit_fn_ret_ty(output));
|
|
|
|
|
|
|
|
// If this async fn has no body (i.e. it's an async fn signature in a trait)
|
|
|
|
// then the closure_def will never be used, and we should avoid generating a
|
|
|
|
// def-id for it.
|
|
|
|
if let Some(body) = body {
|
|
|
|
let closure_def = self.create_def(
|
|
|
|
coroutine_kind.closure_id(),
|
|
|
|
kw::Empty,
|
|
|
|
DefKind::Closure,
|
|
|
|
span,
|
|
|
|
);
|
|
|
|
self.with_parent(closure_def, |this| this.visit_block(body));
|
2022-09-24 18:53:53 +00:00
|
|
|
}
|
2020-03-14 22:22:29 +03:00
|
|
|
}
|
2024-08-24 01:44:52 +00:00
|
|
|
FnKind::Closure(binder, Some(coroutine_kind), decl, body) => {
|
|
|
|
self.visit_closure_binder(binder);
|
|
|
|
visit::walk_fn_decl(self, decl);
|
2020-03-14 22:22:29 +03:00
|
|
|
|
2024-08-24 01:44:52 +00:00
|
|
|
// Async closures desugar to closures inside of closures, so
|
|
|
|
// we must create two defs.
|
|
|
|
let coroutine_def =
|
|
|
|
self.create_def(coroutine_kind.closure_id(), kw::Empty, DefKind::Closure, span);
|
2024-09-01 11:16:50 -04:00
|
|
|
self.with_parent(coroutine_def, |this| this.visit_expr(body));
|
2024-08-24 01:44:52 +00:00
|
|
|
}
|
|
|
|
_ => visit::walk_fn(self, fn_kind),
|
|
|
|
}
|
2020-03-14 22:22:29 +03:00
|
|
|
}
|
|
|
|
|
2017-09-26 23:04:00 +02:00
|
|
|
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) {
|
2023-12-03 12:29:59 +03:00
|
|
|
self.create_def(id, kw::Empty, DefKind::Use, use_tree.span);
|
2017-09-26 23:04:00 +02:00
|
|
|
visit::walk_use_tree(self, use_tree, id);
|
|
|
|
}
|
|
|
|
|
2023-11-28 15:43:07 +03:00
|
|
|
fn visit_foreign_item(&mut self, fi: &'a ForeignItem) {
|
2023-12-03 12:29:59 +03:00
|
|
|
let def_kind = match fi.kind {
|
2024-06-20 19:50:57 -04:00
|
|
|
ForeignItemKind::Static(box StaticItem { ty: _, mutability, expr: _, safety }) => {
|
2024-05-07 14:43:23 +02:00
|
|
|
let safety = match safety {
|
|
|
|
ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe,
|
|
|
|
ast::Safety::Safe(_) => hir::Safety::Safe,
|
|
|
|
};
|
|
|
|
|
|
|
|
DefKind::Static { safety, mutability, nested: false }
|
|
|
|
}
|
2023-12-03 12:29:59 +03:00
|
|
|
ForeignItemKind::Fn(_) => DefKind::Fn,
|
|
|
|
ForeignItemKind::TyAlias(_) => DefKind::ForeignTy,
|
2023-11-28 15:43:07 +03:00
|
|
|
ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id),
|
2023-11-21 23:40:23 +03:00
|
|
|
};
|
2018-03-10 18:16:26 -08:00
|
|
|
|
2023-12-03 12:29:59 +03:00
|
|
|
let def = self.create_def(fi.id, fi.ident.name, def_kind, fi.span);
|
2016-04-14 12:14:03 +12:00
|
|
|
|
2024-04-24 20:31:51 +03:00
|
|
|
self.with_parent(def, |this| visit::walk_item(this, fi));
|
2016-04-14 12:14:03 +12:00
|
|
|
}
|
|
|
|
|
2019-08-24 13:54:40 -03:00
|
|
|
fn visit_variant(&mut self, v: &'a Variant) {
|
2019-09-09 09:26:25 -03:00
|
|
|
if v.is_placeholder {
|
|
|
|
return self.visit_macro_invoc(v.id);
|
|
|
|
}
|
2023-12-03 12:29:59 +03:00
|
|
|
let def = self.create_def(v.id, v.ident.name, DefKind::Variant, v.span);
|
2019-03-21 23:38:50 +01:00
|
|
|
self.with_parent(def, |this| {
|
2023-11-21 23:40:23 +03:00
|
|
|
if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&v.data) {
|
|
|
|
this.create_def(
|
|
|
|
ctor_node_id,
|
2023-12-03 12:29:59 +03:00
|
|
|
kw::Empty,
|
2023-11-21 23:40:23 +03:00
|
|
|
DefKind::Ctor(CtorOf::Variant, ctor_kind),
|
|
|
|
v.span,
|
|
|
|
);
|
2019-03-21 23:38:50 +01:00
|
|
|
}
|
2019-08-24 13:54:40 -03:00
|
|
|
visit::walk_variant(this, v)
|
2019-03-21 23:38:50 +01:00
|
|
|
});
|
2018-05-17 21:28:50 +03:00
|
|
|
}
|
|
|
|
|
2019-08-24 13:54:40 -03:00
|
|
|
fn visit_variant_data(&mut self, data: &'a VariantData) {
|
2019-09-14 13:56:44 +03:00
|
|
|
// The assumption here is that non-`cfg` macro expansion cannot change field indices.
|
|
|
|
// It currently holds because only inert attributes are accepted on fields,
|
|
|
|
// and every such attribute expands into a single field after it's resolved.
|
2018-05-17 21:28:50 +03:00
|
|
|
for (index, field) in data.fields().iter().enumerate() {
|
2019-09-14 17:36:27 +03:00
|
|
|
self.collect_field(field, Some(index));
|
2018-05-17 21:28:50 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-27 20:07:09 +01:00
|
|
|
fn visit_generic_param(&mut self, param: &'a GenericParam) {
|
2019-09-09 09:26:25 -03:00
|
|
|
if param.is_placeholder {
|
|
|
|
self.visit_macro_invoc(param.id);
|
|
|
|
return;
|
|
|
|
}
|
2023-12-03 12:29:59 +03:00
|
|
|
let def_kind = match param.kind {
|
|
|
|
GenericParamKind::Lifetime { .. } => DefKind::LifetimeParam,
|
|
|
|
GenericParamKind::Type { .. } => DefKind::TyParam,
|
|
|
|
GenericParamKind::Const { .. } => DefKind::ConstParam,
|
2018-05-26 19:16:21 +01:00
|
|
|
};
|
2023-12-03 12:29:59 +03:00
|
|
|
self.create_def(param.id, param.ident.name, def_kind, param.ident.span);
|
2016-04-14 12:14:03 +12:00
|
|
|
|
2021-02-13 20:41:02 +01:00
|
|
|
// impl-Trait can happen inside generic parameters, like
|
|
|
|
// ```
|
|
|
|
// fn foo<U: Iterator<Item = impl Clone>>() {}
|
|
|
|
// ```
|
|
|
|
//
|
|
|
|
// In that case, the impl-trait is lowered as an additional generic parameter.
|
2023-11-25 15:45:44 -05:00
|
|
|
self.with_impl_trait(ImplTraitContext::Universal, |this| {
|
2021-02-13 20:41:02 +01:00
|
|
|
visit::walk_generic_param(this, param)
|
|
|
|
});
|
2016-04-14 12:14:03 +12:00
|
|
|
}
|
|
|
|
|
2020-01-30 00:18:54 +01:00
|
|
|
fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) {
|
2023-12-03 12:29:59 +03:00
|
|
|
let def_kind = match &i.kind {
|
2023-11-26 15:57:31 +03:00
|
|
|
AssocItemKind::Fn(..) | AssocItemKind::Delegation(..) => DefKind::AssocFn,
|
2023-12-03 12:29:59 +03:00
|
|
|
AssocItemKind::Const(..) => DefKind::AssocConst,
|
|
|
|
AssocItemKind::Type(..) => DefKind::AssocTy,
|
2024-03-15 14:21:03 +03:00
|
|
|
AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
|
|
|
|
return self.visit_macro_invoc(i.id);
|
|
|
|
}
|
2016-04-14 12:14:03 +12:00
|
|
|
};
|
|
|
|
|
2023-12-03 12:29:59 +03:00
|
|
|
let def = self.create_def(i.id, i.ident.name, def_kind, i.span);
|
2020-01-30 00:18:54 +01:00
|
|
|
self.with_parent(def, |this| visit::walk_assoc_item(this, i, ctxt));
|
2016-04-14 12:14:03 +12:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_pat(&mut self, pat: &'a Pat) {
|
2019-09-26 16:18:31 +01:00
|
|
|
match pat.kind {
|
2020-03-20 15:03:11 +01:00
|
|
|
PatKind::MacCall(..) => self.visit_macro_invoc(pat.id),
|
2017-04-29 14:39:47 +03:00
|
|
|
_ => visit::walk_pat(self, pat),
|
2016-04-14 12:14:03 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-17 21:28:50 +03:00
|
|
|
fn visit_anon_const(&mut self, constant: &'a AnonConst) {
|
2024-09-08 01:49:25 -04:00
|
|
|
// HACK(min_generic_const_args): don't create defs for anon consts if we think they will
|
|
|
|
// later be turned into ConstArgKind::Path's. because this is before resolve is done, we
|
|
|
|
// may accidentally identify a construction of a unit struct as a param and not create a
|
|
|
|
// def. we'll then create a def later in ast lowering in this case. the parent of nested
|
|
|
|
// items will be messed up, but that's ok because there can't be any if we're just looking
|
|
|
|
// for bare idents.
|
|
|
|
|
|
|
|
if matches!(constant.value.maybe_unwrap_block().kind, ExprKind::MacCall(..)) {
|
|
|
|
// See self.pending_anon_const_info for explanation
|
|
|
|
self.pending_anon_const_info =
|
|
|
|
Some(PendingAnonConstInfo { id: constant.id, span: constant.value.span });
|
|
|
|
return visit::walk_anon_const(self, constant);
|
|
|
|
} else if constant.value.is_potential_trivial_const_arg() {
|
|
|
|
return visit::walk_anon_const(self, constant);
|
2024-07-16 19:07:36 -07:00
|
|
|
}
|
Fix anon const def-creation when macros are involved
Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s,
which don't have associated `DefId`s. To deal with the fact that we don't have
resolution information in `DefCollector`, we decided to implement a process
where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we
would avoid creating a def for it in `DefCollector`. If later, in AST lowering,
we realized it turned out to be a unit struct literal, or we were lowering it
to something that didn't use `hir::ConstArg`, we'd create its def there.
However, let's say we have a macro `m!()` that expands to a reference to a free
constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`),
then in def collection, it appears to be a nontrivial anon const and we create
a def. But the macro expands to something that looks like a trivial const arg,
but is not, so in AST lowering we "fix" the mistake we assumed def collection
made and create a def for it. This causes a duplicate definition ICE.
The ideal long-term fix for this is a bit unclear. One option is to delay def
creation for all expression-like nodes until AST lowering (see #128844 for an
incomplete attempt at this). This would avoid issues like this one that are
caused by hacky workarounds. However, this approach has some downsides as well,
and the best approach is yet to be determined.
In the meantime, this PR fixes the bug by delaying def creation for anon consts
whose bodies are macro invocations until after we expand the macro and know
what is inside it. This is accomplished by adding information to create the
anon const's def to the data in `Resolver.invocation_parents`.
2024-08-15 14:36:10 -07:00
|
|
|
|
|
|
|
let def = self.create_def(constant.id, kw::Empty, DefKind::AnonConst, constant.value.span);
|
|
|
|
self.with_parent(def, |this| visit::walk_anon_const(this, constant));
|
2018-05-17 21:28:50 +03:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_expr(&mut self, expr: &'a Expr) {
|
Fix anon const def-creation when macros are involved
Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s,
which don't have associated `DefId`s. To deal with the fact that we don't have
resolution information in `DefCollector`, we decided to implement a process
where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we
would avoid creating a def for it in `DefCollector`. If later, in AST lowering,
we realized it turned out to be a unit struct literal, or we were lowering it
to something that didn't use `hir::ConstArg`, we'd create its def there.
However, let's say we have a macro `m!()` that expands to a reference to a free
constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`),
then in def collection, it appears to be a nontrivial anon const and we create
a def. But the macro expands to something that looks like a trivial const arg,
but is not, so in AST lowering we "fix" the mistake we assumed def collection
made and create a def for it. This causes a duplicate definition ICE.
The ideal long-term fix for this is a bit unclear. One option is to delay def
creation for all expression-like nodes until AST lowering (see #128844 for an
incomplete attempt at this). This would avoid issues like this one that are
caused by hacky workarounds. However, this approach has some downsides as well,
and the best approach is yet to be determined.
In the meantime, this PR fixes the bug by delaying def creation for anon consts
whose bodies are macro invocations until after we expand the macro and know
what is inside it. This is accomplished by adding information to create the
anon const's def to the data in `Resolver.invocation_parents`.
2024-08-15 14:36:10 -07:00
|
|
|
if matches!(expr.kind, ExprKind::MacCall(..)) {
|
|
|
|
return self.visit_macro_invoc(expr.id);
|
|
|
|
}
|
|
|
|
|
|
|
|
let grandparent_def = if let Some(pending_anon) = self.pending_anon_const_info.take() {
|
|
|
|
// See self.pending_anon_const_info for explanation
|
|
|
|
if !expr.is_potential_trivial_const_arg() {
|
|
|
|
self.create_def(pending_anon.id, kw::Empty, DefKind::AnonConst, pending_anon.span)
|
|
|
|
} else {
|
|
|
|
self.parent_def
|
2024-06-03 09:11:58 +00:00
|
|
|
}
|
Fix anon const def-creation when macros are involved
Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s,
which don't have associated `DefId`s. To deal with the fact that we don't have
resolution information in `DefCollector`, we decided to implement a process
where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we
would avoid creating a def for it in `DefCollector`. If later, in AST lowering,
we realized it turned out to be a unit struct literal, or we were lowering it
to something that didn't use `hir::ConstArg`, we'd create its def there.
However, let's say we have a macro `m!()` that expands to a reference to a free
constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`),
then in def collection, it appears to be a nontrivial anon const and we create
a def. But the macro expands to something that looks like a trivial const arg,
but is not, so in AST lowering we "fix" the mistake we assumed def collection
made and create a def for it. This causes a duplicate definition ICE.
The ideal long-term fix for this is a bit unclear. One option is to delay def
creation for all expression-like nodes until AST lowering (see #128844 for an
incomplete attempt at this). This would avoid issues like this one that are
caused by hacky workarounds. However, this approach has some downsides as well,
and the best approach is yet to be determined.
In the meantime, this PR fixes the bug by delaying def creation for anon consts
whose bodies are macro invocations until after we expand the macro and know
what is inside it. This is accomplished by adding information to create the
anon const's def to the data in `Resolver.invocation_parents`.
2024-08-15 14:36:10 -07:00
|
|
|
} else {
|
|
|
|
self.parent_def
|
2018-06-06 15:50:59 -07:00
|
|
|
};
|
2016-04-14 12:14:03 +12:00
|
|
|
|
Fix anon const def-creation when macros are involved
Ever since #125915, some `ast::AnonConst`s turn into `hir::ConstArgKind::Path`s,
which don't have associated `DefId`s. To deal with the fact that we don't have
resolution information in `DefCollector`, we decided to implement a process
where if the anon const *appeared* to be trivial (i.e., `N` or `{ N }`), we
would avoid creating a def for it in `DefCollector`. If later, in AST lowering,
we realized it turned out to be a unit struct literal, or we were lowering it
to something that didn't use `hir::ConstArg`, we'd create its def there.
However, let's say we have a macro `m!()` that expands to a reference to a free
constant `FOO`. If we use `m!()` in the body of an anon const (e.g., `Foo<{ m!() }>`),
then in def collection, it appears to be a nontrivial anon const and we create
a def. But the macro expands to something that looks like a trivial const arg,
but is not, so in AST lowering we "fix" the mistake we assumed def collection
made and create a def for it. This causes a duplicate definition ICE.
The ideal long-term fix for this is a bit unclear. One option is to delay def
creation for all expression-like nodes until AST lowering (see #128844 for an
incomplete attempt at this). This would avoid issues like this one that are
caused by hacky workarounds. However, this approach has some downsides as well,
and the best approach is yet to be determined.
In the meantime, this PR fixes the bug by delaying def creation for anon consts
whose bodies are macro invocations until after we expand the macro and know
what is inside it. This is accomplished by adding information to create the
anon const's def to the data in `Resolver.invocation_parents`.
2024-08-15 14:36:10 -07:00
|
|
|
self.with_parent(grandparent_def, |this| {
|
|
|
|
let parent_def = match expr.kind {
|
|
|
|
ExprKind::Closure(..) | ExprKind::Gen(..) => {
|
|
|
|
this.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
|
|
|
|
}
|
|
|
|
ExprKind::ConstBlock(ref constant) => {
|
|
|
|
for attr in &expr.attrs {
|
|
|
|
visit::walk_attribute(this, attr);
|
|
|
|
}
|
|
|
|
let def = this.create_def(
|
|
|
|
constant.id,
|
|
|
|
kw::Empty,
|
|
|
|
DefKind::InlineConst,
|
|
|
|
constant.value.span,
|
|
|
|
);
|
|
|
|
this.with_parent(def, |this| visit::walk_anon_const(this, constant));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_ => this.parent_def,
|
|
|
|
};
|
|
|
|
|
|
|
|
this.with_parent(parent_def, |this| visit::walk_expr(this, expr))
|
|
|
|
})
|
2016-04-14 12:14:03 +12:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_ty(&mut self, ty: &'a Ty) {
|
2024-01-04 21:45:06 +08:00
|
|
|
match &ty.kind {
|
2020-10-04 22:48:57 +02:00
|
|
|
TyKind::MacCall(..) => self.visit_macro_invoc(ty.id),
|
2024-01-06 18:22:37 +08:00
|
|
|
// Anonymous structs or unions are visited later after defined.
|
|
|
|
TyKind::AnonStruct(..) | TyKind::AnonUnion(..) => {}
|
2024-08-24 01:44:52 +00:00
|
|
|
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', " "));
|
|
|
|
let kind = match self.impl_trait_context {
|
|
|
|
ImplTraitContext::Universal => DefKind::TyParam,
|
|
|
|
ImplTraitContext::Existential => DefKind::OpaqueTy,
|
|
|
|
};
|
|
|
|
let id = self.create_def(*id, name, kind, ty.span);
|
|
|
|
match self.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`.
|
|
|
|
ImplTraitContext::Universal => visit::walk_ty(self, ty),
|
|
|
|
ImplTraitContext::Existential => {
|
|
|
|
self.with_parent(id, |this| visit::walk_ty(this, ty))
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2020-10-04 22:48:57 +02:00
|
|
|
_ => visit::walk_ty(self, ty),
|
2016-07-22 18:56:22 +03:00
|
|
|
}
|
2016-05-02 23:11:19 +03:00
|
|
|
}
|
|
|
|
|
2016-12-06 11:26:52 +01:00
|
|
|
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
2019-09-26 17:34:50 +01:00
|
|
|
match stmt.kind {
|
2020-02-29 19:32:20 +03:00
|
|
|
StmtKind::MacCall(..) => self.visit_macro_invoc(stmt.id),
|
2016-09-14 09:55:20 +00:00
|
|
|
_ => visit::walk_stmt(self, stmt),
|
|
|
|
}
|
|
|
|
}
|
2017-10-23 17:22:28 +09:00
|
|
|
|
2019-09-09 09:26:25 -03:00
|
|
|
fn visit_arm(&mut self, arm: &'a Arm) {
|
|
|
|
if arm.is_placeholder { self.visit_macro_invoc(arm.id) } else { visit::walk_arm(self, arm) }
|
|
|
|
}
|
|
|
|
|
2021-03-16 00:36:07 +03:00
|
|
|
fn visit_expr_field(&mut self, f: &'a ExprField) {
|
|
|
|
if f.is_placeholder {
|
|
|
|
self.visit_macro_invoc(f.id)
|
|
|
|
} else {
|
|
|
|
visit::walk_expr_field(self, f)
|
|
|
|
}
|
2019-09-09 09:26:25 -03:00
|
|
|
}
|
|
|
|
|
2021-03-16 00:36:07 +03:00
|
|
|
fn visit_pat_field(&mut self, fp: &'a PatField) {
|
2019-09-09 09:26:25 -03:00
|
|
|
if fp.is_placeholder {
|
|
|
|
self.visit_macro_invoc(fp.id)
|
|
|
|
} else {
|
2021-03-16 00:36:07 +03:00
|
|
|
visit::walk_pat_field(self, fp)
|
2019-09-09 09:26:25 -03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn visit_param(&mut self, p: &'a Param) {
|
2021-02-13 20:41:02 +01:00
|
|
|
if p.is_placeholder {
|
|
|
|
self.visit_macro_invoc(p.id)
|
|
|
|
} else {
|
2023-11-25 15:45:44 -05:00
|
|
|
self.with_impl_trait(ImplTraitContext::Universal, |this| visit::walk_param(this, p))
|
2021-02-13 20:41:02 +01:00
|
|
|
}
|
2019-09-09 09:26:25 -03:00
|
|
|
}
|
|
|
|
|
2019-09-14 13:56:44 +03:00
|
|
|
// This method is called only when we are visiting an individual field
|
|
|
|
// after expanding an attribute on it.
|
2021-03-16 00:36:07 +03:00
|
|
|
fn visit_field_def(&mut self, field: &'a FieldDef) {
|
2019-09-14 17:36:27 +03:00
|
|
|
self.collect_field(field, None);
|
2019-09-09 09:26:25 -03:00
|
|
|
}
|
2021-10-17 19:32:34 +03:00
|
|
|
|
|
|
|
fn visit_crate(&mut self, krate: &'a Crate) {
|
2022-01-05 16:09:55 +08:00
|
|
|
if krate.is_placeholder {
|
|
|
|
self.visit_macro_invoc(krate.id)
|
2021-10-17 19:32:34 +03:00
|
|
|
} else {
|
|
|
|
visit::walk_crate(self, krate)
|
|
|
|
}
|
|
|
|
}
|
2024-06-26 13:00:51 +03:00
|
|
|
|
|
|
|
fn visit_attribute(&mut self, attr: &'a Attribute) -> Self::Result {
|
|
|
|
let orig_in_attr = mem::replace(&mut self.in_attr, true);
|
|
|
|
visit::walk_attribute(self, attr);
|
|
|
|
self.in_attr = orig_in_attr;
|
|
|
|
}
|
2018-09-06 22:18:39 +01:00
|
|
|
}
|