Auto merge of #150729 - matthiaskrgr:rollup-an2m4zg, r=matthiaskrgr

Rollup of 4 pull requests

Successful merges:

 - rust-lang/rust#150026 (Fix macro_metavar_expr_concat behavior with nested repetitions)
 - rust-lang/rust#150521 (resolve: Rename "name bindings" to "name declarations")
 - rust-lang/rust#150704 (MGCA: Const constructors support)
 - rust-lang/rust#150728 (Cleanup some ui tests for const-traits)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2026-01-06 19:41:29 +00:00
commit 0aced202c2
42 changed files with 948 additions and 940 deletions

View file

@ -558,25 +558,20 @@ fn metavar_expr_concat<'tx>(
MetaVarExprConcatElem::Ident(elem) => elem.name,
MetaVarExprConcatElem::Literal(elem) => *elem,
MetaVarExprConcatElem::Var(ident) => {
match matched_from_ident(dcx, *ident, tscx.interp)? {
NamedMatch::MatchedSeq(named_matches) => {
let Some((curr_idx, _)) = tscx.repeats.last() else {
return Err(dcx.struct_span_err(dspan.entire(), "invalid syntax"));
};
match &named_matches[*curr_idx] {
// FIXME(c410-f3r) Nested repetitions are unimplemented
MatchedSeq(_) => {
return Err(dcx.struct_span_err(
ident.span,
"nested repetitions with `${concat(...)}` metavariable expressions are not yet supported",
));
}
MatchedSingle(pnr) => extract_symbol_from_pnr(dcx, pnr, ident.span)?,
}
}
NamedMatch::MatchedSingle(pnr) => {
let key = MacroRulesNormalizedIdent::new(*ident);
match lookup_cur_matched(key, tscx.interp, &tscx.repeats) {
Some(NamedMatch::MatchedSingle(pnr)) => {
extract_symbol_from_pnr(dcx, pnr, ident.span)?
}
Some(NamedMatch::MatchedSeq(..)) => {
return Err(dcx.struct_span_err(
ident.span,
"`${concat(...)}` variable is still repeating at this depth",
));
}
None => {
return Err(dcx.create_err(MveUnrecognizedVar { span: ident.span, key }));
}
}
}
};

View file

@ -1415,9 +1415,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let ct = self.check_param_uses_if_mcg(ct, span, false);
Ok(ct)
}
TypeRelativePath::Ctor { ctor_def_id, args } => {
return Ok(ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, ctor_def_id, args)));
}
TypeRelativePath::Ctor { ctor_def_id, args } => match tcx.def_kind(ctor_def_id) {
DefKind::Ctor(_, CtorKind::Fn) => {
Ok(ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, ctor_def_id, args)))
}
DefKind::Ctor(ctor_of, CtorKind::Const) => {
Ok(self.construct_const_ctor_value(ctor_def_id, ctor_of, args))
}
_ => unreachable!(),
},
// FIXME(mgca): implement support for this once ready to support all adt ctor expressions,
// not just const ctors
TypeRelativePath::Variant { .. } => {
@ -1452,7 +1458,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// FIXME(mgca): do we want constructor resolutions to take priority over
// other possible resolutions?
if matches!(mode, LowerTypeRelativePathMode::Const)
&& let Some((CtorKind::Fn, ctor_def_id)) = variant_def.ctor
&& let Some((_, ctor_def_id)) = variant_def.ctor
{
tcx.check_stability(variant_def.def_id, Some(qpath_hir_id), span, None);
let _ = self.prohibit_generic_args(
@ -2597,7 +2603,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
);
self.lower_const_param(def_id, hir_id)
}
Res::Def(DefKind::Const | DefKind::Ctor(_, CtorKind::Const), did) => {
Res::Def(DefKind::Const, did) => {
assert_eq!(opt_self_ty, None);
let [leading_segments @ .., segment] = path.segments else { bug!() };
let _ = self
@ -2605,6 +2611,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let args = self.lower_generic_args_of_path_segment(span, did, segment);
ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args))
}
Res::Def(DefKind::Ctor(ctor_of, CtorKind::Const), did) => {
assert_eq!(opt_self_ty, None);
let [leading_segments @ .., segment] = path.segments else { bug!() };
let _ = self
.prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None);
let parent_did = tcx.parent(did);
let generics_did = match ctor_of {
CtorOf::Variant => tcx.parent(parent_did),
CtorOf::Struct => parent_did,
};
let args = self.lower_generic_args_of_path_segment(span, generics_did, segment);
self.construct_const_ctor_value(did, ctor_of, args)
}
Res::Def(DefKind::Ctor(_, CtorKind::Fn), did) => {
assert_eq!(opt_self_ty, None);
let [leading_segments @ .., segment] = path.segments else { bug!() };
@ -3174,4 +3195,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
Some(r)
}
fn construct_const_ctor_value(
&self,
ctor_def_id: DefId,
ctor_of: CtorOf,
args: GenericArgsRef<'tcx>,
) -> Const<'tcx> {
let tcx = self.tcx();
let parent_did = tcx.parent(ctor_def_id);
let adt_def = tcx.adt_def(match ctor_of {
CtorOf::Variant => tcx.parent(parent_did),
CtorOf::Struct => parent_did,
});
let variant_idx = adt_def.variant_index_with_id(parent_did);
let valtree = if adt_def.is_enum() {
let discr = ty::ValTree::from_scalar_int(tcx, variant_idx.as_u32().into());
ty::ValTree::from_branches(tcx, [ty::Const::new_value(tcx, discr, tcx.types.u32)])
} else {
ty::ValTree::zst(tcx)
};
let adt_ty = Ty::new_adt(tcx, adt_def, args);
ty::Const::new_value(tcx, valtree, adt_ty)
}
}

View file

@ -26,7 +26,7 @@ impl Reexport {
}
}
/// This structure is supposed to keep enough data to re-create `NameBinding`s for other crates
/// This structure is supposed to keep enough data to re-create `Decl`s for other crates
/// during name resolution. Right now the bindings are not recreated entirely precisely so we may
/// need to add more data in the future to correctly support macros 2.0, for example.
/// Module child can be either a proper item or a reexport (including private imports).

View file

@ -33,31 +33,33 @@ use tracing::debug;
use crate::Namespace::{MacroNS, TypeNS, ValueNS};
use crate::def_collector::collect_definitions;
use crate::imports::{ImportData, ImportKind};
use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
use crate::macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef};
use crate::ref_mut::CmCell;
use crate::{
BindingKey, ExternPreludeEntry, Finalize, MacroData, Module, ModuleKind, ModuleOrUniformRoot,
NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult, ResolutionError,
Resolver, Segment, Used, VisResolutionError, errors,
BindingKey, Decl, DeclData, DeclKind, ExternPreludeEntry, Finalize, MacroData, Module,
ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, ResolutionError, Resolver, Segment,
Used, VisResolutionError, errors,
};
type Res = def::Res<NodeId>;
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
/// otherwise, reports an error.
pub(crate) fn define_binding_local(
/// Attempt to put the declaration with the given name and namespace into the module,
/// and report an error in case of a collision.
pub(crate) fn plant_decl_into_local_module(
&mut self,
parent: Module<'ra>,
ident: Ident,
ns: Namespace,
binding: NameBinding<'ra>,
decl: Decl<'ra>,
) {
if let Err(old_binding) = self.try_define_local(parent, ident, ns, binding, false) {
self.report_conflict(parent, ident, ns, old_binding, binding);
if let Err(old_decl) = self.try_plant_decl_into_local_module(parent, ident, ns, decl, false)
{
self.report_conflict(parent, ident, ns, old_decl, decl);
}
}
/// Create a name definitinon from the given components, and put it into the local module.
fn define_local(
&mut self,
parent: Module<'ra>,
@ -68,10 +70,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
span: Span,
expn_id: LocalExpnId,
) {
let binding = self.arenas.new_res_binding(res, vis.to_def_id(), span, expn_id);
self.define_binding_local(parent, ident, ns, binding);
let decl = self.arenas.new_def_decl(res, vis.to_def_id(), span, expn_id);
self.plant_decl_into_local_module(parent, ident, ns, decl);
}
/// Create a name definitinon from the given components, and put it into the extern module.
fn define_extern(
&self,
parent: Module<'ra>,
@ -82,10 +85,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
vis: Visibility<DefId>,
span: Span,
expansion: LocalExpnId,
ambiguity: Option<NameBinding<'ra>>,
ambiguity: Option<Decl<'ra>>,
) {
let binding = self.arenas.alloc_name_binding(NameBindingData {
kind: NameBindingKind::Res(res),
let decl = self.arenas.alloc_decl(DeclData {
kind: DeclKind::Def(res),
ambiguity,
// External ambiguities always report the `AMBIGUOUS_GLOB_IMPORTS` lint at the moment.
warn_ambiguity: true,
@ -101,8 +104,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if self
.resolution_or_default(parent, key)
.borrow_mut_unchecked()
.non_glob_binding
.replace(binding)
.non_glob_decl
.replace(decl)
.is_some()
{
span_bug!(span, "an external binding was already defined");
@ -284,7 +287,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child;
let span = child_span(self, reexport_chain, res);
let res = res.expect_non_local();
self.arenas.new_res_binding(res, vis, span, expansion)
self.arenas.new_def_decl(res, vis, span, expansion)
});
// Record primary definitions.
@ -691,7 +694,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
let kind = ImportKind::Single {
source: source.ident,
target: ident,
bindings: Default::default(),
decls: Default::default(),
type_ns_only,
nested,
id,
@ -977,7 +980,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
let parent_scope = self.parent_scope;
let expansion = parent_scope.expansion;
let (used, module, binding) = if orig_name.is_none() && ident.name == kw::SelfLower {
let (used, module, decl) = if orig_name.is_none() && ident.name == kw::SelfLower {
self.r.dcx().emit_err(errors::ExternCrateSelfRequiresRenaming { span: sp });
return;
} else if orig_name == Some(kw::SelfLower) {
@ -997,10 +1000,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
}
.map(|module| {
let used = self.process_macro_use_imports(item, module);
let binding = self.r.arenas.new_pub_res_binding(module.res().unwrap(), sp, expansion);
(used, Some(ModuleOrUniformRoot::Module(module)), binding)
let decl = self.r.arenas.new_pub_def_decl(module.res().unwrap(), sp, expansion);
(used, Some(ModuleOrUniformRoot::Module(module)), decl)
})
.unwrap_or((true, None, self.r.dummy_binding));
.unwrap_or((true, None, self.r.dummy_decl));
let import = self.r.arenas.alloc_import(ImportData {
kind: ImportKind::ExternCrate { source: orig_name, target: ident, id: item.id },
root_id: item.id,
@ -1019,7 +1022,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
self.r.import_use_map.insert(import, Used::Other);
}
self.r.potentially_unused_imports.push(import);
let imported_binding = self.r.import(binding, import);
let import_decl = self.r.new_import_decl(decl, import);
if ident.name != kw::Underscore && parent == self.r.graph_root {
let norm_ident = Macros20NormalizedIdent::new(ident);
// FIXME: this error is technically unnecessary now when extern prelude is split into
@ -1027,7 +1030,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
if let Some(entry) = self.r.extern_prelude.get(&norm_ident)
&& expansion != LocalExpnId::ROOT
&& orig_name.is_some()
&& entry.item_binding.is_none()
&& entry.item_decl.is_none()
{
self.r.dcx().emit_err(
errors::MacroExpandedExternCrateCannotShadowExternArguments { span: item.span },
@ -1038,21 +1041,21 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
match self.r.extern_prelude.entry(norm_ident) {
Entry::Occupied(mut occupied) => {
let entry = occupied.get_mut();
if entry.item_binding.is_some() {
if entry.item_decl.is_some() {
let msg = format!("extern crate `{ident}` already in extern prelude");
self.r.tcx.dcx().span_delayed_bug(item.span, msg);
} else {
entry.item_binding = Some((imported_binding, orig_name.is_some()));
entry.item_decl = Some((import_decl, orig_name.is_some()));
}
entry
}
Entry::Vacant(vacant) => vacant.insert(ExternPreludeEntry {
item_binding: Some((imported_binding, true)),
flag_binding: None,
item_decl: Some((import_decl, true)),
flag_decl: None,
}),
};
}
self.r.define_binding_local(parent, ident, TypeNS, imported_binding);
self.r.plant_decl_into_local_module(parent, ident, TypeNS, import_decl);
}
/// Constructs the reduced graph for one foreign item.
@ -1089,14 +1092,14 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
}
}
fn add_macro_use_binding(
fn add_macro_use_decl(
&mut self,
name: Symbol,
binding: NameBinding<'ra>,
decl: Decl<'ra>,
span: Span,
allow_shadowing: bool,
) {
if self.r.macro_use_prelude.insert(name, binding).is_some() && !allow_shadowing {
if self.r.macro_use_prelude.insert(name, decl).is_some() && !allow_shadowing {
self.r.dcx().emit_err(errors::MacroUseNameAlreadyInUse { span, name });
}
}
@ -1167,8 +1170,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
}
macro_use_import(this, span, true)
};
let import_binding = this.r.import(binding, import);
this.add_macro_use_binding(ident.name, import_binding, span, allow_shadowing);
let import_decl = this.r.new_import_decl(binding, import);
this.add_macro_use_decl(ident.name, import_decl, span, allow_shadowing);
}
});
} else {
@ -1183,13 +1186,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
if let Ok(binding) = result {
let import = macro_use_import(self, ident.span, false);
self.r.potentially_unused_imports.push(import);
let imported_binding = self.r.import(binding, import);
self.add_macro_use_binding(
ident.name,
imported_binding,
ident.span,
allow_shadowing,
);
let import_decl = self.r.new_import_decl(binding, import);
self.add_macro_use_decl(ident.name, import_decl, ident.span, allow_shadowing);
} else {
self.r.dcx().emit_err(errors::ImportedMacroNotFound { span: ident.span });
}
@ -1300,8 +1298,8 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
} else {
Visibility::Restricted(CRATE_DEF_ID)
};
let binding = self.r.arenas.new_res_binding(res, vis.to_def_id(), span, expansion);
self.r.set_binding_parent_module(binding, parent_scope.module);
let decl = self.r.arenas.new_def_decl(res, vis.to_def_id(), span, expansion);
self.r.set_decl_parent_module(decl, parent_scope.module);
self.r.all_macro_rules.insert(ident.name);
if is_macro_export {
let import = self.r.arenas.alloc_import(ImportData {
@ -1319,17 +1317,17 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
vis_span: item.vis.span,
});
self.r.import_use_map.insert(import, Used::Other);
let import_binding = self.r.import(binding, import);
self.r.define_binding_local(self.r.graph_root, ident, MacroNS, import_binding);
let import_decl = self.r.new_import_decl(decl, import);
self.r.plant_decl_into_local_module(self.r.graph_root, ident, MacroNS, import_decl);
} else {
self.r.check_reserved_macro_name(ident, res);
self.insert_unused_macro(ident, def_id, item.id);
}
self.r.feed_visibility(feed, vis);
let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding(
self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding {
let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Def(
self.r.arenas.alloc_macro_rules_decl(MacroRulesDecl {
parent_macro_rules_scope: parent_scope.macro_rules,
binding,
decl,
ident,
}),
));

View file

@ -36,7 +36,7 @@ use rustc_session::lint::builtin::{
use rustc_span::{DUMMY_SP, Ident, Macros20NormalizedIdent, Span, kw};
use crate::imports::{Import, ImportKind};
use crate::{LexicalScopeBinding, NameBindingKind, Resolver, module_to_string};
use crate::{DeclKind, LateDecl, Resolver, module_to_string};
struct UnusedImport {
use_tree: ast::UseTree,
@ -514,8 +514,8 @@ impl Resolver<'_, '_> {
let mut check_redundant_imports = FxIndexSet::default();
for module in &self.local_modules {
for (_key, resolution) in self.resolutions(*module).borrow().iter() {
if let Some(binding) = resolution.borrow().best_binding()
&& let NameBindingKind::Import { import, .. } = binding.kind
if let Some(decl) = resolution.borrow().best_decl()
&& let DeclKind::Import { import, .. } = decl.kind
&& let ImportKind::Single { id, .. } = import.kind
{
if let Some(unused_import) = unused_imports.get(&import.root_id)
@ -542,8 +542,8 @@ impl Resolver<'_, '_> {
// Deleting both unused imports and unnecessary segments of an item may result
// in the item not being found.
for unn_qua in &self.potentially_unnecessary_qualifications {
if let LexicalScopeBinding::Item(name_binding) = unn_qua.binding
&& let NameBindingKind::Import { import, .. } = name_binding.kind
if let LateDecl::Decl(decl) = unn_qua.decl
&& let DeclKind::Import { import, .. } = decl.kind
&& (is_unused_import(import, &unused_imports)
|| is_redundant_import(import, &redundant_imports))
{

View file

@ -44,11 +44,10 @@ use crate::errors::{
use crate::imports::{Import, ImportKind};
use crate::late::{DiagMetadata, PatternSource, Rib};
use crate::{
AmbiguityError, AmbiguityKind, BindingError, BindingKey, Finalize,
ForwardGenericParamBanReason, HasGenericParams, LexicalScopeBinding, MacroRulesScope, Module,
ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult,
PrivacyError, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,
VisResolutionError, errors as errs, path_names_to_string,
AmbiguityError, AmbiguityKind, BindingError, BindingKey, Decl, DeclKind, Finalize,
ForwardGenericParamBanReason, HasGenericParams, LateDecl, MacroRulesScope, Module, ModuleKind,
ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, ResolutionError, Resolver, Scope,
ScopeSet, Segment, UseError, Used, VisResolutionError, errors as errs, path_names_to_string,
};
type Res = def::Res<ast::NodeId>;
@ -149,8 +148,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if ambiguity_error.warning {
let node_id = match ambiguity_error.b1.0.kind {
NameBindingKind::Import { import, .. } => import.root_id,
NameBindingKind::Res(_) => CRATE_NODE_ID,
DeclKind::Import { import, .. } => import.root_id,
DeclKind::Def(_) => CRATE_NODE_ID,
};
self.lint_buffer.buffer_lint(
AMBIGUOUS_GLOB_IMPORTS,
@ -212,8 +211,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent: Module<'_>,
ident: Ident,
ns: Namespace,
new_binding: NameBinding<'ra>,
old_binding: NameBinding<'ra>,
new_binding: Decl<'ra>,
old_binding: Decl<'ra>,
) {
// Error on the second of two conflicting names
if old_binding.span.lo() > new_binding.span.lo() {
@ -288,8 +287,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
.with_code(code);
// See https://github.com/rust-lang/rust/issues/32354
use NameBindingKind::Import;
let can_suggest = |binding: NameBinding<'_>, import: self::Import<'_>| {
use DeclKind::Import;
let can_suggest = |binding: Decl<'_>, import: self::Import<'_>| {
!binding.span.is_dummy()
&& !matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)
};
@ -473,7 +472,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
&mut self,
finalize: Finalize,
path: &[Segment],
second_binding: Option<NameBinding<'_>>,
second_binding: Option<Decl<'_>>,
) {
let Finalize { node_id, root_span, .. } = finalize;
@ -506,7 +505,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// `ExternCrate` (also used for `crate::...`) then no need to issue a
// warning, this looks all good!
if let Some(binding) = second_binding
&& let NameBindingKind::Import { import, .. } = binding.kind
&& let DeclKind::Import { import, .. } = binding.kind
// Careful: we still want to rewrite paths from renamed extern crates.
&& let ImportKind::ExternCrate { source: None, .. } = import.kind
{
@ -1196,13 +1195,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Never recommend deprecated helper attributes.
}
Scope::MacroRules(macro_rules_scope) => {
if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope.get() {
let res = macro_rules_binding.binding.res();
if let MacroRulesScope::Def(macro_rules_def) = macro_rules_scope.get() {
let res = macro_rules_def.decl.res();
if filter_fn(res) {
suggestions.push(TypoSuggestion::typo_from_ident(
macro_rules_binding.ident,
res,
))
suggestions
.push(TypoSuggestion::typo_from_ident(macro_rules_def.ident, res))
}
}
}
@ -1360,8 +1357,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
// #90113: Do not count an inaccessible reexported item as a candidate.
if let NameBindingKind::Import { binding, .. } = name_binding.kind
&& this.is_accessible_from(binding.vis, parent_scope.module)
if let DeclKind::Import { source_decl, .. } = name_binding.kind
&& this.is_accessible_from(source_decl.vis, parent_scope.module)
&& !this.is_accessible_from(name_binding.vis, parent_scope.module)
{
return;
@ -1469,8 +1466,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let mut path_segments = path_segments.clone();
path_segments.push(ast::PathSegment::from_ident(ident.0));
let alias_import = if let NameBindingKind::Import { import, .. } =
name_binding.kind
let alias_import = if let DeclKind::Import { import, .. } = name_binding.kind
&& let ImportKind::ExternCrate { source: Some(_), .. } = import.kind
&& import.parent_scope.expansion == parent_scope.expansion
{
@ -1583,9 +1579,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|(key, name_resolution)| {
if key.ns == TypeNS
&& key.ident == ident
&& let Some(binding) = name_resolution.borrow().best_binding()
&& let Some(decl) = name_resolution.borrow().best_decl()
{
match binding.res() {
match decl.res() {
// No disambiguation needed if the identically named item we
// found in scope actually refers to the crate in question.
Res::Def(_, def_id) => def_id != crate_def_id,
@ -1754,7 +1750,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
macro_kind.descr_expected(),
),
};
if let crate::NameBindingKind::Import { import, .. } = binding.kind
if let crate::DeclKind::Import { import, .. } = binding.kind
&& !import.span.is_dummy()
{
let note = errors::IdentImporterHereButItIsDesc {
@ -1971,7 +1967,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
true
}
fn binding_description(&self, b: NameBinding<'_>, ident: Ident, scope: Scope<'_>) -> String {
fn decl_description(&self, b: Decl<'_>, ident: Ident, scope: Scope<'_>) -> String {
let res = b.res();
if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
let (built_in, from) = match scope {
@ -2007,7 +2003,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
&& self
.extern_prelude
.get(&Macros20NormalizedIdent::new(ident))
.is_some_and(|entry| entry.item_binding.map(|(b, _)| b) == Some(b1))
.is_some_and(|entry| entry.item_decl.map(|(b, _)| b) == Some(b1))
};
let (b1, b2, scope1, scope2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
// We have to print the span-less alternative first, otherwise formatting looks bad.
@ -2016,8 +2012,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
(b1, b2, scope1, scope2, false)
};
let could_refer_to = |b: NameBinding<'_>, scope: Scope<'ra>, also: &str| {
let what = self.binding_description(b, ident, scope);
let could_refer_to = |b: Decl<'_>, scope: Scope<'ra>, also: &str| {
let what = self.decl_description(b, ident, scope);
let note_msg = format!("`{ident}` could{also} refer to {what}");
let thing = b.res().descr();
@ -2075,11 +2071,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
/// If the binding refers to a tuple struct constructor with fields,
/// returns the span of its fields.
fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option<Span> {
let NameBindingKind::Res(Res::Def(
DefKind::Ctor(CtorOf::Struct, CtorKind::Fn),
ctor_def_id,
)) = binding.kind
fn ctor_fields_span(&self, decl: Decl<'_>) -> Option<Span> {
let DeclKind::Def(Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id)) =
decl.kind
else {
return None;
};
@ -2091,7 +2085,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
let PrivacyError {
ident,
binding,
decl,
outermost_res,
parent_scope,
single_nested,
@ -2099,17 +2093,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ref source,
} = *privacy_error;
let res = binding.res();
let ctor_fields_span = self.ctor_fields_span(binding);
let res = decl.res();
let ctor_fields_span = self.ctor_fields_span(decl);
let plain_descr = res.descr().to_string();
let nonimport_descr =
if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
let import_descr = nonimport_descr.clone() + " import";
let get_descr =
|b: NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
let get_descr = |b: Decl<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
// Print the primary message.
let ident_descr = get_descr(binding);
let ident_descr = get_descr(decl);
let mut err =
self.dcx().create_err(errors::IsPrivate { span: ident.span, ident_descr, ident });
@ -2209,30 +2202,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
// Print the whole import chain to make it easier to see what happens.
let first_binding = binding;
let mut next_binding = Some(binding);
let first_binding = decl;
let mut next_binding = Some(decl);
let mut next_ident = ident;
let mut path = vec![];
while let Some(binding) = next_binding {
let name = next_ident;
next_binding = match binding.kind {
_ if res == Res::Err => None,
NameBindingKind::Import { binding, import, .. } => match import.kind {
_ if binding.span.is_dummy() => None,
DeclKind::Import { source_decl, import, .. } => match import.kind {
_ if source_decl.span.is_dummy() => None,
ImportKind::Single { source, .. } => {
next_ident = source;
Some(binding)
Some(source_decl)
}
ImportKind::Glob { .. }
| ImportKind::MacroUse { .. }
| ImportKind::MacroExport => Some(binding),
| ImportKind::MacroExport => Some(source_decl),
ImportKind::ExternCrate { .. } => None,
},
_ => None,
};
match binding.kind {
NameBindingKind::Import { import, .. } => {
DeclKind::Import { import, .. } => {
for segment in import.module_path.iter().skip(1) {
// Don't include `{{root}}` in suggestions - it's an internal symbol
// that should never be shown to users.
@ -2245,14 +2238,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
true, // re-export
));
}
NameBindingKind::Res(_) => {}
DeclKind::Def(_) => {}
}
let first = binding == first_binding;
let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
let mut note_span = MultiSpan::from_span(def_span);
if !first && binding.vis.is_public() {
let desc = match binding.kind {
NameBindingKind::Import { .. } => "re-export",
DeclKind::Import { .. } => "re-export",
_ => "directly",
};
note_span.push_span_label(def_span, format!("you could import this {desc}"));
@ -2418,7 +2411,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
opt_ns: Option<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'ra>,
ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
ignore_import: Option<Import<'ra>>,
module: Option<ModuleOrUniformRoot<'ra>>,
failed_segment_idx: usize,
@ -2514,7 +2507,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ns_to_try,
parent_scope,
None,
ignore_binding,
ignore_decl,
ignore_import,
)
.ok()
@ -2528,11 +2521,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
None,
&ribs[ns_to_try],
ignore_binding,
ignore_decl,
diag_metadata,
) {
// we found a locally-imported or available item/module
Some(LexicalScopeBinding::Item(binding)) => Some(binding),
Some(LateDecl::Decl(binding)) => Some(binding),
_ => None,
}
} else {
@ -2543,7 +2536,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
None,
false,
ignore_binding,
ignore_decl,
ignore_import,
)
.ok()
@ -2579,7 +2572,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
None,
&ribs[ValueNS],
ignore_binding,
ignore_decl,
diag_metadata,
)
} else {
@ -2594,7 +2587,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// // variable `Foo`.
// }
// ```
Some(LexicalScopeBinding::Res(Res::Local(id))) => {
Some(LateDecl::RibDef(Res::Local(id))) => {
Some(*self.pat_span_map.get(&id).unwrap())
}
// Name matches item from a local name binding
@ -2608,7 +2601,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// // binding `Foo`.
// }
// ```
Some(LexicalScopeBinding::Item(name_binding)) => Some(name_binding.span),
Some(LateDecl::Decl(name_binding)) => Some(name_binding.span),
_ => None,
};
let suggestion = match_span.map(|span| {
@ -2647,7 +2640,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
None,
false,
ignore_binding,
ignore_decl,
ignore_import,
) {
let descr = binding.res().descr();

View file

@ -8,12 +8,12 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility,
use rustc_middle::ty::Visibility;
use tracing::info;
use crate::{NameBinding, NameBindingKind, Resolver};
use crate::{Decl, DeclKind, Resolver};
#[derive(Clone, Copy)]
enum ParentId<'ra> {
Def(LocalDefId),
Import(NameBinding<'ra>),
Import(Decl<'ra>),
}
impl ParentId<'_> {
@ -28,10 +28,10 @@ impl ParentId<'_> {
pub(crate) struct EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
r: &'a mut Resolver<'ra, 'tcx>,
def_effective_visibilities: EffectiveVisibilities,
/// While walking import chains we need to track effective visibilities per-binding, and def id
/// While walking import chains we need to track effective visibilities per-decl, and def id
/// keys in `Resolver::effective_visibilities` are not enough for that, because multiple
/// bindings can correspond to a single def id in imports. So we keep a separate table.
import_effective_visibilities: EffectiveVisibilities<NameBinding<'ra>>,
/// declarations can correspond to a single def id in imports. So we keep a separate table.
import_effective_visibilities: EffectiveVisibilities<Decl<'ra>>,
// It's possible to recalculate this at any point, but it's relatively expensive.
current_private_vis: Visibility,
changed: bool,
@ -42,8 +42,8 @@ impl Resolver<'_, '_> {
self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local()
}
fn private_vis_import(&self, binding: NameBinding<'_>) -> Visibility {
let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
fn private_vis_import(&self, decl: Decl<'_>) -> Visibility {
let DeclKind::Import { import, .. } = decl.kind else { unreachable!() };
Visibility::Restricted(
import
.id()
@ -70,7 +70,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
pub(crate) fn compute_effective_visibilities<'c>(
r: &'a mut Resolver<'ra, 'tcx>,
krate: &'c Crate,
) -> FxHashSet<NameBinding<'ra>> {
) -> FxHashSet<Decl<'ra>> {
let mut visitor = EffectiveVisibilitiesVisitor {
r,
def_effective_visibilities: Default::default(),
@ -91,17 +91,17 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
let mut exported_ambiguities = FxHashSet::default();
// Update visibilities for import def ids. These are not used during the
// `EffectiveVisibilitiesVisitor` pass, because we have more detailed binding-based
// `EffectiveVisibilitiesVisitor` pass, because we have more detailed declaration-based
// information, but are used by later passes. Effective visibility of an import def id
// is the maximum value among visibilities of bindings corresponding to that def id.
for (binding, eff_vis) in visitor.import_effective_visibilities.iter() {
let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() };
if !binding.is_ambiguity_recursive() {
// is the maximum value among visibilities of declarations corresponding to that def id.
for (decl, eff_vis) in visitor.import_effective_visibilities.iter() {
let DeclKind::Import { import, .. } = decl.kind else { unreachable!() };
if !decl.is_ambiguity_recursive() {
if let Some(node_id) = import.id() {
r.effective_visibilities.update_eff_vis(r.local_def_id(node_id), eff_vis, r.tcx)
}
} else if binding.ambiguity.is_some() && eff_vis.is_public_at_level(Level::Reexported) {
exported_ambiguities.insert(*binding);
} else if decl.ambiguity.is_some() && eff_vis.is_public_at_level(Level::Reexported) {
exported_ambiguities.insert(*decl);
}
}
@ -110,12 +110,12 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
exported_ambiguities
}
/// Update effective visibilities of bindings in the given module,
/// Update effective visibilities of name declarations in the given module,
/// including their whole reexport chains.
fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) {
let module = self.r.expect_module(module_id.to_def_id());
for (_, name_resolution) in self.r.resolutions(module).borrow().iter() {
let Some(mut binding) = name_resolution.borrow().binding() else {
let Some(mut decl) = name_resolution.borrow().binding() else {
continue;
};
// Set the given effective visibility level to `Level::Direct` and
@ -125,28 +125,27 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
// If the binding is ambiguous, put the root ambiguity binding and all reexports
// leading to it into the table. They are used by the `ambiguous_glob_reexports`
// lint. For all bindings added to the table this way `is_ambiguity` returns true.
let is_ambiguity =
|binding: NameBinding<'ra>, warn: bool| binding.ambiguity.is_some() && !warn;
let is_ambiguity = |decl: Decl<'ra>, warn: bool| decl.ambiguity.is_some() && !warn;
let mut parent_id = ParentId::Def(module_id);
let mut warn_ambiguity = binding.warn_ambiguity;
while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind {
self.update_import(binding, parent_id);
let mut warn_ambiguity = decl.warn_ambiguity;
while let DeclKind::Import { source_decl, .. } = decl.kind {
self.update_import(decl, parent_id);
if is_ambiguity(binding, warn_ambiguity) {
if is_ambiguity(decl, warn_ambiguity) {
// Stop at the root ambiguity, further bindings in the chain should not
// be reexported because the root ambiguity blocks any access to them.
// (Those further bindings are most likely not ambiguities themselves.)
break;
}
parent_id = ParentId::Import(binding);
binding = nested_binding;
warn_ambiguity |= nested_binding.warn_ambiguity;
parent_id = ParentId::Import(decl);
decl = source_decl;
warn_ambiguity |= source_decl.warn_ambiguity;
}
if !is_ambiguity(binding, warn_ambiguity)
&& let Some(def_id) = binding.res().opt_def_id().and_then(|id| id.as_local())
if !is_ambiguity(decl, warn_ambiguity)
&& let Some(def_id) = decl.res().opt_def_id().and_then(|id| id.as_local())
{
self.update_def(def_id, binding.vis.expect_local(), parent_id);
self.update_def(def_id, decl.vis.expect_local(), parent_id);
}
}
}
@ -188,15 +187,15 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> {
}
}
fn update_import(&mut self, binding: NameBinding<'ra>, parent_id: ParentId<'ra>) {
let nominal_vis = binding.vis.expect_local();
fn update_import(&mut self, decl: Decl<'ra>, parent_id: ParentId<'ra>) {
let nominal_vis = decl.vis.expect_local();
let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return };
let inherited_eff_vis = self.effective_vis_or_private(parent_id);
let tcx = self.r.tcx;
self.changed |= self.import_effective_visibilities.update(
binding,
decl,
Some(nominal_vis),
|| cheap_private_vis.unwrap_or_else(|| self.r.private_vis_import(binding)),
|| cheap_private_vis.unwrap_or_else(|| self.r.private_vis_import(decl)),
inherited_eff_vis,
parent_id.level(),
tcx,

View file

@ -19,10 +19,9 @@ use crate::late::{
};
use crate::macros::{MacroRulesScope, sub_namespace_match};
use crate::{
AmbiguityError, AmbiguityKind, BindingKey, CmResolver, Determinacy, Finalize, ImportKind,
LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind,
ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet,
Segment, Stage, Used, errors,
AmbiguityError, AmbiguityKind, BindingKey, CmResolver, Decl, DeclKind, Determinacy, Finalize,
ImportKind, LateDecl, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult,
PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, Stage, Used, errors,
};
#[derive(Copy, Clone)]
@ -183,7 +182,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules),
Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() {
MacroRulesScope::Binding(binding) => {
MacroRulesScope::Def(binding) => {
Scope::MacroRules(binding.parent_macro_rules_scope)
}
MacroRulesScope::Invocation(invoc_id) => {
@ -305,9 +304,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope: &ParentScope<'ra>,
finalize: Option<Finalize>,
ribs: &[Rib<'ra>],
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
diag_metadata: Option<&DiagMetadata<'_>>,
) -> Option<LexicalScopeBinding<'ra>> {
) -> Option<LateDecl<'ra>> {
let orig_ident = ident;
let (general_span, normalized_span) = if ident.name == kw::SelfUpper {
// FIXME(jseyfried) improve `Self` hygiene
@ -330,7 +329,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let rib_ident = if rib.kind.contains_params() { normalized_ident } else { ident };
if let Some((original_rib_ident_def, res)) = rib.bindings.get_key_value(&rib_ident) {
// The ident resolves to a type parameter or local variable.
return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
return Some(LateDecl::RibDef(self.validate_res_from_ribs(
i,
rib_ident,
*res,
@ -346,12 +345,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
finalize.is_some(),
ignore_binding,
ignore_decl,
None,
)
{
// The ident resolves to an item in a block.
return Some(LexicalScopeBinding::Item(binding));
return Some(LateDecl::Decl(binding));
} else if let RibKind::Module(module) = rib.kind {
// Encountered a module item, abandon ribs and look into that module and preludes.
let parent_scope = &ParentScope { module, ..*parent_scope };
@ -364,11 +363,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
finalize,
finalize.is_some(),
ignore_binding,
ignore_decl,
None,
)
.ok()
.map(LexicalScopeBinding::Item);
.map(LateDecl::Decl);
}
if let RibKind::MacroDefinition(def) = rib.kind
@ -392,9 +391,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope: &ParentScope<'ra>,
finalize: Option<Finalize>,
force: bool,
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, Determinacy> {
) -> Result<Decl<'ra>, Determinacy> {
assert!(force || finalize.is_none()); // `finalize` implies `force`
// Make sure `self`, `super` etc produce an error when passed to here.
@ -425,7 +424,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// }
// So we have to save the innermost solution and continue searching in outer scopes
// to detect potential ambiguities.
let mut innermost_results: Vec<(NameBinding<'_>, Scope<'_>)> = Vec::new();
let mut innermost_results: Vec<(Decl<'_>, Scope<'_>)> = Vec::new();
let mut determinacy = Determinacy::Determined;
// Go through all the scopes and try to resolve the name.
@ -443,13 +442,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ctxt,
scope_set,
parent_scope,
// Shadowed bindings don't need to be marked as used or non-speculatively loaded.
// Shadowed decls don't need to be marked as used or non-speculatively loaded.
if innermost_results.is_empty() { finalize } else { None },
force,
ignore_binding,
ignore_decl,
ignore_import,
) {
Ok(binding) => Ok(binding),
Ok(decl) => Ok(decl),
// We can break with an error at this step, it means we cannot determine the
// resolution right now, but we must block and wait until we can, instead of
// considering outer scopes. Although there's no need to do that if we already
@ -460,32 +459,32 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
Err(determinacy) => Err(determinacy.into_value()),
};
match res {
Ok(binding) if sub_namespace_match(binding.macro_kinds(), macro_kind) => {
Ok(decl) if sub_namespace_match(decl.macro_kinds(), macro_kind) => {
// Below we report various ambiguity errors.
// We do not need to report them if we are either in speculative resolution,
// or in late resolution when everything is already imported and expanded
// and no ambiguities exist.
if matches!(finalize, None | Some(Finalize { stage: Stage::Late, .. })) {
return ControlFlow::Break(Ok(binding));
return ControlFlow::Break(Ok(decl));
}
if let Some(&(innermost_binding, _)) = innermost_results.first() {
if let Some(&(innermost_decl, _)) = innermost_results.first() {
// Found another solution, if the first one was "weak", report an error.
if this.get_mut().maybe_push_ambiguity(
orig_ident,
ns,
scope_set,
parent_scope,
binding,
decl,
scope,
&innermost_results,
) {
// No need to search for more potential ambiguities, one is enough.
return ControlFlow::Break(Ok(innermost_binding));
return ControlFlow::Break(Ok(innermost_decl));
}
}
innermost_results.push((binding, scope));
innermost_results.push((decl, scope));
}
Ok(_) | Err(Determinacy::Determined) => {}
Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined,
@ -502,7 +501,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Scope visiting walked all the scopes and maybe found something in one of them.
match innermost_results.first() {
Some(&(binding, ..)) => Ok(binding),
Some(&(decl, ..)) => Ok(decl),
None => Err(Determinacy::determined(determinacy == Determinacy::Determined || force)),
}
}
@ -518,16 +517,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope: &ParentScope<'ra>,
finalize: Option<Finalize>,
force: bool,
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
) -> Result<Decl<'ra>, ControlFlow<Determinacy, Determinacy>> {
let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
let ret = match scope {
Scope::DeriveHelpers(expn_id) => {
if let Some(binding) = self.helper_attrs.get(&expn_id).and_then(|attrs| {
attrs.iter().rfind(|(i, _)| ident == *i).map(|(_, binding)| *binding)
}) {
Ok(binding)
if let Some(decl) = self
.helper_attrs
.get(&expn_id)
.and_then(|attrs| attrs.iter().rfind(|(i, _)| ident == *i).map(|(_, d)| *d))
{
Ok(decl)
} else {
Err(Determinacy::Determined)
}
@ -544,12 +545,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
) {
Ok((Some(ext), _)) => {
if ext.helper_attrs.contains(&ident.name) {
let binding = self.arenas.new_pub_res_binding(
let decl = self.arenas.new_pub_def_decl(
Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat),
derive.span,
LocalExpnId::ROOT,
);
result = Ok(binding);
result = Ok(decl);
break;
}
}
@ -560,10 +561,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
result
}
Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() {
MacroRulesScope::Binding(macro_rules_binding)
if ident == macro_rules_binding.ident =>
{
Ok(macro_rules_binding.binding)
MacroRulesScope::Def(macro_rules_def) if ident == macro_rules_def.ident => {
Ok(macro_rules_def.decl)
}
MacroRulesScope::Invocation(_) => Err(Determinacy::Undetermined),
_ => Err(Determinacy::Determined),
@ -580,7 +579,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
finalize.map(|f| Finalize { used: Used::Scope, ..f }),
)
};
let binding = self.reborrow().resolve_ident_in_module_non_globs_unadjusted(
let decl = self.reborrow().resolve_ident_in_module_non_globs_unadjusted(
module,
ident,
ns,
@ -591,11 +590,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
Shadowing::Restricted
},
adjusted_finalize,
ignore_binding,
ignore_decl,
ignore_import,
);
match binding {
Ok(binding) => {
match decl {
Ok(decl) => {
if let Some(lint_id) = derive_fallback_lint_id {
self.get_mut().lint_buffer.buffer_lint(
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
@ -608,7 +607,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
},
);
}
Ok(binding)
Ok(decl)
}
Err(ControlFlow::Continue(determinacy)) => Err(determinacy),
Err(ControlFlow::Break(determinacy)) => {
@ -641,7 +640,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
Shadowing::Restricted
},
adjusted_finalize,
ignore_binding,
ignore_decl,
ignore_import,
);
match binding {
@ -669,18 +668,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}
Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() {
Some(binding) => Ok(binding),
Some(decl) => Ok(decl),
None => Err(Determinacy::determined(
self.graph_root.unexpanded_invocations.borrow().is_empty(),
)),
},
Scope::BuiltinAttrs => match self.builtin_attrs_bindings.get(&ident.name) {
Some(binding) => Ok(*binding),
Scope::BuiltinAttrs => match self.builtin_attr_decls.get(&ident.name) {
Some(decl) => Ok(*decl),
None => Err(Determinacy::Determined),
},
Scope::ExternPreludeItems => {
match self.reborrow().extern_prelude_get_item(ident, finalize.is_some()) {
Some(binding) => Ok(binding),
Some(decl) => Ok(decl),
None => Err(Determinacy::determined(
self.graph_root.unexpanded_invocations.borrow().is_empty(),
)),
@ -688,36 +687,35 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
Scope::ExternPreludeFlags => {
match self.extern_prelude_get_flag(ident, finalize.is_some()) {
Some(binding) => Ok(binding),
Some(decl) => Ok(decl),
None => Err(Determinacy::Determined),
}
}
Scope::ToolPrelude => match self.registered_tool_bindings.get(&ident) {
Some(binding) => Ok(*binding),
Scope::ToolPrelude => match self.registered_tool_decls.get(&ident) {
Some(decl) => Ok(*decl),
None => Err(Determinacy::Determined),
},
Scope::StdLibPrelude => {
let mut result = Err(Determinacy::Determined);
if let Some(prelude) = self.prelude
&& let Ok(binding) = self.reborrow().resolve_ident_in_scope_set(
&& let Ok(decl) = self.reborrow().resolve_ident_in_scope_set(
ident,
ScopeSet::Module(ns, prelude),
parent_scope,
None,
false,
ignore_binding,
ignore_decl,
ignore_import,
)
&& (matches!(use_prelude, UsePrelude::Yes)
|| self.is_builtin_macro(binding.res()))
&& (matches!(use_prelude, UsePrelude::Yes) || self.is_builtin_macro(decl.res()))
{
result = Ok(binding)
result = Ok(decl)
}
result
}
Scope::BuiltinTypes => match self.builtin_types_bindings.get(&ident.name) {
Some(binding) => {
Scope::BuiltinTypes => match self.builtin_type_decls.get(&ident.name) {
Some(decl) => {
if matches!(ident.name, sym::f16)
&& !self.tcx.features().f16()
&& !ident.span.allows_unstable(sym::f16)
@ -744,7 +742,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
)
.emit();
}
Ok(*binding)
Ok(*decl)
}
None => Err(Determinacy::Determined),
},
@ -759,12 +757,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ns: Namespace,
scope_set: ScopeSet<'ra>,
parent_scope: &ParentScope<'ra>,
binding: NameBinding<'ra>,
decl: Decl<'ra>,
scope: Scope<'ra>,
innermost_results: &[(NameBinding<'ra>, Scope<'ra>)],
innermost_results: &[(Decl<'ra>, Scope<'ra>)],
) -> bool {
let (innermost_binding, innermost_scope) = *innermost_results.first().unwrap();
let (res, innermost_res) = (binding.res(), innermost_binding.res());
let (innermost_decl, innermost_scope) = innermost_results[0];
let (res, innermost_res) = (decl.res(), innermost_decl.res());
if res == innermost_res {
return false;
}
@ -784,7 +782,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
span_bug!(orig_ident.span, "impossible inner resolution kind")
} else if matches!(innermost_scope, Scope::MacroRules(_))
&& matches!(scope, Scope::ModuleNonGlobs(..) | Scope::ModuleGlobs(..))
&& !self.disambiguate_macro_rules_vs_modularized(innermost_binding, binding)
&& !self.disambiguate_macro_rules_vs_modularized(innermost_decl, decl)
{
Some(AmbiguityKind::MacroRulesVsModularized)
} else if matches!(scope, Scope::MacroRules(_))
@ -800,13 +798,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
"ambiguous scoped macro resolutions with path-based \
scope resolution as first candidate"
)
} else if innermost_binding.is_glob_import() {
} else if innermost_decl.is_glob_import() {
Some(AmbiguityKind::GlobVsOuter)
} else if !module_only
&& innermost_binding.may_appear_after(parent_scope.expansion, binding)
{
} else if !module_only && innermost_decl.may_appear_after(parent_scope.expansion, decl) {
Some(AmbiguityKind::MoreExpandedVsOuter)
} else if innermost_binding.expansion != LocalExpnId::ROOT
} else if innermost_decl.expansion != LocalExpnId::ROOT
&& (!module_only || ns == MacroNS)
&& let Scope::ModuleGlobs(m1, _) = scope
&& let Scope::ModuleNonGlobs(m2, _) = innermost_scope
@ -825,9 +821,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// by extern item bindings.
// FIXME: Remove with lang team approval.
let issue_145575_hack = matches!(scope, Scope::ExternPreludeFlags)
&& innermost_results[1..].iter().any(|(b, s)| {
matches!(s, Scope::ExternPreludeItems) && *b != innermost_binding
});
&& innermost_results[1..]
.iter()
.any(|(b, s)| matches!(s, Scope::ExternPreludeItems) && *b != innermost_decl);
// Skip ambiguity errors for nonglob module bindings "overridden"
// by glob module bindings in the same module.
// FIXME: Remove with lang team approval.
@ -848,8 +844,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.ambiguity_errors.push(AmbiguityError {
kind,
ident: orig_ident,
b1: innermost_binding,
b2: binding,
b1: innermost_decl,
b2: decl,
scope1: innermost_scope,
scope2: scope,
warning: false,
@ -869,7 +865,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ns: Namespace,
parent_scope: &ParentScope<'ra>,
ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, Determinacy> {
) -> Result<Decl<'ra>, Determinacy> {
self.resolve_ident_in_module(module, ident, ns, parent_scope, None, None, ignore_import)
}
@ -881,9 +877,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ns: Namespace,
parent_scope: &ParentScope<'ra>,
finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, Determinacy> {
) -> Result<Decl<'ra>, Determinacy> {
let tmp_parent_scope;
let mut adjusted_parent_scope = parent_scope;
match module {
@ -907,7 +903,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ns,
adjusted_parent_scope,
finalize,
ignore_binding,
ignore_decl,
ignore_import,
)
}
@ -921,9 +917,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ns: Namespace,
parent_scope: &ParentScope<'ra>,
finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, Determinacy> {
) -> Result<Decl<'ra>, Determinacy> {
match module {
ModuleOrUniformRoot::Module(module) => self.resolve_ident_in_scope_set(
ident,
@ -931,7 +927,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
finalize,
finalize.is_some(),
ignore_binding,
ignore_decl,
ignore_import,
),
ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set(
@ -940,7 +936,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
finalize,
finalize.is_some(),
ignore_binding,
ignore_decl,
ignore_import,
),
ModuleOrUniformRoot::ExternPrelude => {
@ -953,7 +949,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
finalize,
finalize.is_some(),
ignore_binding,
ignore_decl,
ignore_import,
)
}
@ -962,7 +958,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if ns == TypeNS {
if ident.name == kw::Crate || ident.name == kw::DollarCrate {
let module = self.resolve_crate_root(ident);
return Ok(module.self_binding.unwrap());
return Ok(module.self_decl.unwrap());
} else if ident.name == kw::Super || ident.name == kw::SelfLower {
// FIXME: Implement these with renaming requirements so that e.g.
// `use super;` doesn't work, but `use super as name;` does.
@ -976,7 +972,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
finalize,
finalize.is_some(),
ignore_binding,
ignore_decl,
ignore_import,
)
}
@ -994,9 +990,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
finalize: Option<Finalize>,
// This binding should be ignored during in-module resolution, so that we don't get
// "self-confirming" import resolutions during import validation and checking.
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
) -> Result<Decl<'ra>, ControlFlow<Determinacy, Determinacy>> {
let key = BindingKey::new(ident, ns);
// `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding
// doesn't need to be mutable. It will fail when there is a cycle of imports, and without
@ -1006,7 +1002,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
.try_borrow_mut_unchecked()
.map_err(|_| ControlFlow::Continue(Determined))?;
let binding = resolution.non_glob_binding.filter(|b| Some(*b) != ignore_binding);
let binding = resolution.non_glob_decl.filter(|b| Some(*b) != ignore_decl);
if let Some(finalize) = finalize {
return self.get_mut().finalize_module_binding(
@ -1031,7 +1027,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None,
ns,
ignore_import,
ignore_binding,
ignore_decl,
parent_scope,
) {
return Err(ControlFlow::Break(Undetermined));
@ -1055,9 +1051,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope: &ParentScope<'ra>,
shadowing: Shadowing,
finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
) -> Result<Decl<'ra>, ControlFlow<Determinacy, Determinacy>> {
let key = BindingKey::new(ident, ns);
// `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding
// doesn't need to be mutable. It will fail when there is a cycle of imports, and without
@ -1067,7 +1063,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
.try_borrow_mut_unchecked()
.map_err(|_| ControlFlow::Continue(Determined))?;
let binding = resolution.glob_binding.filter(|b| Some(*b) != ignore_binding);
let binding = resolution.glob_decl.filter(|b| Some(*b) != ignore_decl);
if let Some(finalize) = finalize {
return self.get_mut().finalize_module_binding(
@ -1087,7 +1083,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
binding,
ns,
ignore_import,
ignore_binding,
ignore_decl,
parent_scope,
) {
return Err(ControlFlow::Break(Undetermined));
@ -1157,7 +1153,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
adjusted_parent_scope,
None,
false,
ignore_binding,
ignore_decl,
ignore_import,
);
@ -1179,12 +1175,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
fn finalize_module_binding(
&mut self,
ident: Ident,
binding: Option<NameBinding<'ra>>,
binding: Option<Decl<'ra>>,
parent_scope: &ParentScope<'ra>,
module: Module<'ra>,
finalize: Finalize,
shadowing: Shadowing,
) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
) -> Result<Decl<'ra>, ControlFlow<Determinacy, Determinacy>> {
let Finalize { path_span, report_private, used, root_span, .. } = finalize;
let Some(binding) = binding else {
@ -1195,7 +1191,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if report_private {
self.privacy_errors.push(PrivacyError {
ident,
binding,
decl: binding,
dedup_span: path_span,
outermost_res: None,
source: None,
@ -1209,7 +1205,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if shadowing == Shadowing::Unrestricted
&& binding.expansion != LocalExpnId::ROOT
&& let NameBindingKind::Import { import, .. } = binding.kind
&& let DeclKind::Import { import, .. } = binding.kind
&& matches!(import.kind, ImportKind::MacroExport)
{
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
@ -1255,15 +1251,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
fn single_import_can_define_name<'r>(
mut self: CmResolver<'r, 'ra, 'tcx>,
resolution: &NameResolution<'ra>,
binding: Option<NameBinding<'ra>>,
binding: Option<Decl<'ra>>,
ns: Namespace,
ignore_import: Option<Import<'ra>>,
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
parent_scope: &ParentScope<'ra>,
) -> bool {
for single_import in &resolution.single_imports {
if let Some(binding) = resolution.non_glob_binding
&& let NameBindingKind::Import { import, .. } = binding.kind
if let Some(decl) = resolution.non_glob_decl
&& let DeclKind::Import { import, .. } = decl.kind
&& import == *single_import
{
// Single import has already defined the name and we are aware of it,
@ -1276,8 +1272,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
if !self.is_accessible_from(single_import.vis, parent_scope.module) {
continue;
}
if let Some(ignored) = ignore_binding
&& let NameBindingKind::Import { import, .. } = ignored.kind
if let Some(ignored) = ignore_decl
&& let DeclKind::Import { import, .. } = ignored.kind
&& import == *single_import
{
continue;
@ -1286,13 +1282,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let Some(module) = single_import.imported_module.get() else {
return true;
};
let ImportKind::Single { source, target, bindings, .. } = &single_import.kind else {
let ImportKind::Single { source, target, decls, .. } = &single_import.kind else {
unreachable!();
};
if source != target {
if bindings.iter().all(|binding| binding.get().binding().is_none()) {
if decls.iter().all(|d| d.get().decl().is_none()) {
return true;
} else if bindings[ns].get().binding().is_none() && binding.is_some() {
} else if decls[ns].get().decl().is_none() && binding.is_some() {
return true;
}
}
@ -1303,7 +1299,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ns,
&single_import.parent_scope,
None,
ignore_binding,
ignore_decl,
ignore_import,
) {
Err(Determined) => continue,
@ -1668,7 +1664,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
opt_ns: Option<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'ra>,
finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
ignore_import: Option<Import<'ra>>,
) -> PathResult<'ra> {
self.resolve_path_with_ribs(
@ -1678,7 +1674,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None,
finalize,
None,
ignore_binding,
ignore_decl,
ignore_import,
None,
)
@ -1692,7 +1688,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
source: Option<PathSource<'_, '_, '_>>,
finalize: Option<Finalize>,
ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
ignore_binding: Option<NameBinding<'ra>>,
ignore_decl: Option<Decl<'ra>>,
ignore_import: Option<Import<'ra>>,
diag_metadata: Option<&DiagMetadata<'_>>,
) -> PathResult<'ra> {
@ -1819,7 +1815,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ns,
parent_scope,
finalize,
ignore_binding,
ignore_decl,
ignore_import,
)
} else if let Some(ribs) = ribs
@ -1832,13 +1828,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
finalize,
&ribs[ns],
ignore_binding,
ignore_decl,
diag_metadata,
) {
// we found a locally-imported or available item/module
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
Some(LateDecl::Decl(binding)) => Ok(binding),
// we found a local variable or type param
Some(LexicalScopeBinding::Res(res)) => {
Some(LateDecl::RibDef(res)) => {
record_segment_res(self.reborrow(), finalize, res, id);
return PathResult::NonModule(PartialRes::with_unresolved_segments(
res,
@ -1854,7 +1850,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope,
finalize,
finalize.is_some(),
ignore_binding,
ignore_decl,
ignore_import,
)
};
@ -1954,7 +1950,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
opt_ns,
parent_scope,
ribs,
ignore_binding,
ignore_decl,
ignore_import,
module,
segment_idx,

View file

@ -32,26 +32,27 @@ use crate::errors::{
};
use crate::ref_mut::CmCell;
use crate::{
AmbiguityError, BindingKey, CmResolver, Determinacy, Finalize, ImportSuggestion, Module,
ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult,
PerNS, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string,
AmbiguityError, BindingKey, CmResolver, Decl, DeclData, DeclKind, Determinacy, Finalize,
ImportSuggestion, Module, ModuleOrUniformRoot, ParentScope, PathResult, PerNS, ResolutionError,
Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string,
};
type Res = def::Res<NodeId>;
/// A [`NameBinding`] in the process of being resolved.
/// A potential import declaration in the process of being planted into a module.
/// Also used for lazily planting names from `--extern` flags to extern prelude.
#[derive(Clone, Copy, Default, PartialEq)]
pub(crate) enum PendingBinding<'ra> {
Ready(Option<NameBinding<'ra>>),
pub(crate) enum PendingDecl<'ra> {
Ready(Option<Decl<'ra>>),
#[default]
Pending,
}
impl<'ra> PendingBinding<'ra> {
pub(crate) fn binding(self) -> Option<NameBinding<'ra>> {
impl<'ra> PendingDecl<'ra> {
pub(crate) fn decl(self) -> Option<Decl<'ra>> {
match self {
PendingBinding::Ready(binding) => binding,
PendingBinding::Pending => None,
PendingDecl::Ready(decl) => decl,
PendingDecl::Pending => None,
}
}
}
@ -65,8 +66,8 @@ pub(crate) enum ImportKind<'ra> {
/// `target` in `use prefix::source as target`.
/// It will directly use `source` when the format is `use prefix::source`.
target: Ident,
/// Bindings introduced by the import.
bindings: PerNS<CmCell<PendingBinding<'ra>>>,
/// Name declarations introduced by the import.
decls: PerNS<CmCell<PendingDecl<'ra>>>,
/// `true` for `...::{self [as target]}` imports, `false` otherwise.
type_ns_only: bool,
/// Did this import result from a nested import? ie. `use foo::{bar, baz};`
@ -109,14 +110,14 @@ impl<'ra> std::fmt::Debug for ImportKind<'ra> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use ImportKind::*;
match self {
Single { source, target, bindings, type_ns_only, nested, id, .. } => f
Single { source, target, decls, type_ns_only, nested, id, .. } => f
.debug_struct("Single")
.field("source", source)
.field("target", target)
// Ignore the nested bindings to avoid an infinite loop while printing.
.field(
"bindings",
&bindings.clone().map(|b| b.into_inner().binding().map(|_| format_args!(".."))),
"decls",
&decls.clone().map(|b| b.into_inner().decl().map(|_| format_args!(".."))),
)
.field("type_ns_only", type_ns_only)
.field("nested", nested)
@ -243,16 +244,16 @@ pub(crate) struct NameResolution<'ra> {
/// Single imports that may define the name in the namespace.
/// Imports are arena-allocated, so it's ok to use pointers as keys.
pub single_imports: FxIndexSet<Import<'ra>>,
/// The non-glob binding for this name, if it is known to exist.
pub non_glob_binding: Option<NameBinding<'ra>>,
/// The glob binding for this name, if it is known to exist.
pub glob_binding: Option<NameBinding<'ra>>,
/// The non-glob declaration for this name, if it is known to exist.
pub non_glob_decl: Option<Decl<'ra>>,
/// The glob declaration for this name, if it is known to exist.
pub glob_decl: Option<Decl<'ra>>,
}
impl<'ra> NameResolution<'ra> {
/// Returns the binding for the name if it is known or None if it not known.
pub(crate) fn binding(&self) -> Option<NameBinding<'ra>> {
self.best_binding().and_then(|binding| {
pub(crate) fn binding(&self) -> Option<Decl<'ra>> {
self.best_decl().and_then(|binding| {
if !binding.is_glob_import() || self.single_imports.is_empty() {
Some(binding)
} else {
@ -261,8 +262,8 @@ impl<'ra> NameResolution<'ra> {
})
}
pub(crate) fn best_binding(&self) -> Option<NameBinding<'ra>> {
self.non_glob_binding.or(self.glob_binding)
pub(crate) fn best_decl(&self) -> Option<Decl<'ra>> {
self.non_glob_decl.or(self.glob_decl)
}
}
@ -282,13 +283,10 @@ struct UnresolvedImportError {
// Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`
// are permitted for backward-compatibility under a deprecation lint.
fn pub_use_of_private_extern_crate_hack(
import: Import<'_>,
binding: NameBinding<'_>,
) -> Option<NodeId> {
match (&import.kind, &binding.kind) {
(ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. })
if let ImportKind::ExternCrate { id, .. } = binding_import.kind
fn pub_use_of_private_extern_crate_hack(import: Import<'_>, decl: Decl<'_>) -> Option<NodeId> {
match (&import.kind, &decl.kind) {
(ImportKind::Single { .. }, DeclKind::Import { import: decl_import, .. })
if let ImportKind::ExternCrate { id, .. } = decl_import.kind
&& import.vis.is_public() =>
{
Some(id)
@ -298,20 +296,16 @@ fn pub_use_of_private_extern_crate_hack(
}
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
/// Given a binding and an import that resolves to it,
/// return the corresponding binding defined by the import.
pub(crate) fn import(
&self,
binding: NameBinding<'ra>,
import: Import<'ra>,
) -> NameBinding<'ra> {
/// Given an import and the declaration that it points to,
/// create the corresponding import declaration.
pub(crate) fn new_import_decl(&self, decl: Decl<'ra>, import: Import<'ra>) -> Decl<'ra> {
let import_vis = import.vis.to_def_id();
let vis = if binding.vis.is_at_least(import_vis, self.tcx)
|| pub_use_of_private_extern_crate_hack(import, binding).is_some()
let vis = if decl.vis.is_at_least(import_vis, self.tcx)
|| pub_use_of_private_extern_crate_hack(import, decl).is_some()
{
import_vis
} else {
binding.vis
decl.vis
};
if let ImportKind::Glob { ref max_vis, .. } = import.kind
@ -321,8 +315,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
max_vis.set_unchecked(Some(vis.expect_local()))
}
self.arenas.alloc_name_binding(NameBindingData {
kind: NameBindingKind::Import { binding, import },
self.arenas.alloc_decl(DeclData {
kind: DeclKind::Import { source_decl: decl, import },
ambiguity: None,
warn_ambiguity: false,
span: import.span,
@ -331,18 +325,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
})
}
/// Define the name or return the existing binding if there is a collision.
pub(crate) fn try_define_local(
/// Attempt to put the declaration with the given name and namespace into the module,
/// and return existing declaration if there is a collision.
pub(crate) fn try_plant_decl_into_local_module(
&mut self,
module: Module<'ra>,
ident: Ident,
ns: Namespace,
binding: NameBinding<'ra>,
decl: Decl<'ra>,
warn_ambiguity: bool,
) -> Result<(), NameBinding<'ra>> {
let res = binding.res();
) -> Result<(), Decl<'ra>> {
let res = decl.res();
self.check_reserved_macro_name(ident, res);
self.set_binding_parent_module(binding, module);
self.set_decl_parent_module(decl, module);
// Even if underscore names cannot be looked up, we still need to add them to modules,
// because they can be fetched by glob imports from those modules, and bring traits
// into scope both directly and through glob imports.
@ -351,67 +346,66 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
module.underscore_disambiguator.get()
});
self.update_local_resolution(module, key, warn_ambiguity, |this, resolution| {
if let Some(old_binding) = resolution.best_binding() {
if res == Res::Err && old_binding.res() != Res::Err {
// Do not override real bindings with `Res::Err`s from error recovery.
if let Some(old_decl) = resolution.best_decl() {
if res == Res::Err && old_decl.res() != Res::Err {
// Do not override real declarations with `Res::Err`s from error recovery.
return Ok(());
}
match (old_binding.is_glob_import(), binding.is_glob_import()) {
match (old_decl.is_glob_import(), decl.is_glob_import()) {
(true, true) => {
let (glob_binding, old_glob_binding) = (binding, old_binding);
// FIXME: remove `!binding.is_ambiguity_recursive()` after delete the warning ambiguity.
if !binding.is_ambiguity_recursive()
&& let NameBindingKind::Import { import: old_import, .. } =
old_glob_binding.kind
&& let NameBindingKind::Import { import, .. } = glob_binding.kind
let (glob_decl, old_glob_decl) = (decl, old_decl);
// FIXME: remove `!decl.is_ambiguity_recursive()` after delete the warning ambiguity.
if !decl.is_ambiguity_recursive()
&& let DeclKind::Import { import: old_import, .. } = old_glob_decl.kind
&& let DeclKind::Import { import, .. } = glob_decl.kind
&& old_import == import
{
// When imported from the same glob-import statement, we should replace
// `old_glob_binding` with `glob_binding`, regardless of whether
// `old_glob_decl` with `glob_decl`, regardless of whether
// they have the same resolution or not.
resolution.glob_binding = Some(glob_binding);
} else if res != old_glob_binding.res() {
resolution.glob_binding = Some(this.new_ambiguity_binding(
old_glob_binding,
glob_binding,
resolution.glob_decl = Some(glob_decl);
} else if res != old_glob_decl.res() {
resolution.glob_decl = Some(this.new_decl_with_ambiguity(
old_glob_decl,
glob_decl,
warn_ambiguity,
));
} else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
} else if !old_decl.vis.is_at_least(decl.vis, this.tcx) {
// We are glob-importing the same item but with greater visibility.
resolution.glob_binding = Some(glob_binding);
} else if binding.is_ambiguity_recursive() {
resolution.glob_binding =
Some(this.new_warn_ambiguity_binding(glob_binding));
resolution.glob_decl = Some(glob_decl);
} else if decl.is_ambiguity_recursive() {
resolution.glob_decl =
Some(this.new_decl_with_warn_ambiguity(glob_decl));
}
}
(old_glob @ true, false) | (old_glob @ false, true) => {
let (glob_binding, non_glob_binding) =
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
resolution.non_glob_binding = Some(non_glob_binding);
if let Some(old_glob_binding) = resolution.glob_binding {
assert!(old_glob_binding.is_glob_import());
if glob_binding.res() != old_glob_binding.res() {
resolution.glob_binding = Some(this.new_ambiguity_binding(
old_glob_binding,
glob_binding,
let (glob_decl, non_glob_decl) =
if old_glob { (old_decl, decl) } else { (decl, old_decl) };
resolution.non_glob_decl = Some(non_glob_decl);
if let Some(old_glob_decl) = resolution.glob_decl {
assert!(old_glob_decl.is_glob_import());
if glob_decl.res() != old_glob_decl.res() {
resolution.glob_decl = Some(this.new_decl_with_ambiguity(
old_glob_decl,
glob_decl,
false,
));
} else if !old_glob_binding.vis.is_at_least(binding.vis, this.tcx) {
resolution.glob_binding = Some(glob_binding);
} else if !old_glob_decl.vis.is_at_least(decl.vis, this.tcx) {
resolution.glob_decl = Some(glob_decl);
}
} else {
resolution.glob_binding = Some(glob_binding);
resolution.glob_decl = Some(glob_decl);
}
}
(false, false) => {
return Err(old_binding);
return Err(old_decl);
}
}
} else {
if binding.is_glob_import() {
resolution.glob_binding = Some(binding);
if decl.is_glob_import() {
resolution.glob_decl = Some(decl);
} else {
resolution.non_glob_binding = Some(binding);
resolution.non_glob_decl = Some(decl);
}
}
@ -419,20 +413,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
})
}
fn new_ambiguity_binding(
fn new_decl_with_ambiguity(
&self,
primary_binding: NameBinding<'ra>,
secondary_binding: NameBinding<'ra>,
primary_decl: Decl<'ra>,
secondary_decl: Decl<'ra>,
warn_ambiguity: bool,
) -> NameBinding<'ra> {
let ambiguity = Some(secondary_binding);
let data = NameBindingData { ambiguity, warn_ambiguity, ..*primary_binding };
self.arenas.alloc_name_binding(data)
) -> Decl<'ra> {
let ambiguity = Some(secondary_decl);
let data = DeclData { ambiguity, warn_ambiguity, ..*primary_decl };
self.arenas.alloc_decl(data)
}
fn new_warn_ambiguity_binding(&self, binding: NameBinding<'ra>) -> NameBinding<'ra> {
assert!(binding.is_ambiguity_recursive());
self.arenas.alloc_name_binding(NameBindingData { warn_ambiguity: true, ..*binding })
fn new_decl_with_warn_ambiguity(&self, decl: Decl<'ra>) -> Decl<'ra> {
assert!(decl.is_ambiguity_recursive());
self.arenas.alloc_decl(DeclData { warn_ambiguity: true, ..*decl })
}
// Use `f` to mutate the resolution of the name in the module.
@ -451,14 +445,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// during which the resolution might end up getting re-defined via a glob cycle.
let (binding, t, warn_ambiguity) = {
let resolution = &mut *self.resolution_or_default(module, key).borrow_mut_unchecked();
let old_binding = resolution.binding();
let old_decl = resolution.binding();
let t = f(self, resolution);
if let Some(binding) = resolution.binding()
&& old_binding != Some(binding)
&& old_decl != Some(binding)
{
(binding, t, warn_ambiguity || old_binding.is_some())
(binding, t, warn_ambiguity || old_decl.is_some())
} else {
return t;
}
@ -477,12 +471,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None => continue,
};
if self.is_accessible_from(binding.vis, scope) {
let imported_binding = self.import(binding, *import);
let _ = self.try_define_local(
let import_decl = self.new_import_decl(binding, *import);
let _ = self.try_plant_decl_into_local_module(
import.parent_scope.module,
ident.0,
key.ns,
imported_binding,
import_decl,
warn_ambiguity,
);
}
@ -494,17 +488,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Define a dummy resolution containing a `Res::Err` as a placeholder for a failed
// or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.
fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool) {
if let ImportKind::Single { target, ref bindings, .. } = import.kind {
if !(is_indeterminate
|| bindings.iter().all(|binding| binding.get().binding().is_none()))
{
if let ImportKind::Single { target, ref decls, .. } = import.kind {
if !(is_indeterminate || decls.iter().all(|d| d.get().decl().is_none())) {
return; // Has resolution, do not create the dummy binding
}
let dummy_binding = self.dummy_binding;
let dummy_binding = self.import(dummy_binding, import);
let dummy_decl = self.dummy_decl;
let dummy_decl = self.new_import_decl(dummy_decl, import);
self.per_ns(|this, ns| {
let module = import.parent_scope.module;
let _ = this.try_define_local(module, target, ns, dummy_binding, false);
let _ =
this.try_plant_decl_into_local_module(module, target, ns, dummy_decl, false);
// Don't remove underscores from `single_imports`, they were never added.
if target.name != kw::Underscore {
let key = BindingKey::new(target, ns);
@ -513,7 +506,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
})
}
});
self.record_use(target, dummy_binding, Used::Other);
self.record_use(target, dummy_decl, Used::Other);
} else if import.imported_module.get().is_none() {
self.import_use_map.insert(import, Used::Other);
if let Some(id) = import.id() {
@ -581,10 +574,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
glob_error |= import.is_glob();
if let ImportKind::Single { source, ref bindings, .. } = import.kind
if let ImportKind::Single { source, ref decls, .. } = import.kind
&& source.name == kw::SelfLower
// Silence `unresolved import` error if E0429 is already emitted
&& let PendingBinding::Ready(None) = bindings.value_ns.get()
&& let PendingDecl::Ready(None) = decls.value_ns.get()
{
continue;
}
@ -634,13 +627,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}
pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<NameBinding<'ra>>) {
pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<Decl<'ra>>) {
for module in &self.local_modules {
for (key, resolution) in self.resolutions(*module).borrow().iter() {
let resolution = resolution.borrow();
let Some(binding) = resolution.best_binding() else { continue };
let Some(binding) = resolution.best_decl() else { continue };
if let NameBindingKind::Import { import, .. } = binding.kind
if let DeclKind::Import { import, .. } = binding.kind
&& let Some(amb_binding) = binding.ambiguity
&& binding.res() != Res::Err
&& exported_ambiguities.contains(&binding)
@ -658,24 +651,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
);
}
if let Some(glob_binding) = resolution.glob_binding
&& resolution.non_glob_binding.is_some()
if let Some(glob_decl) = resolution.glob_decl
&& resolution.non_glob_decl.is_some()
{
if binding.res() != Res::Err
&& glob_binding.res() != Res::Err
&& let NameBindingKind::Import { import: glob_import, .. } =
glob_binding.kind
&& glob_decl.res() != Res::Err
&& let DeclKind::Import { import: glob_import, .. } = glob_decl.kind
&& let Some(glob_import_id) = glob_import.id()
&& let glob_import_def_id = self.local_def_id(glob_import_id)
&& self.effective_visibilities.is_exported(glob_import_def_id)
&& glob_binding.vis.is_public()
&& glob_decl.vis.is_public()
&& !binding.vis.is_public()
{
let binding_id = match binding.kind {
NameBindingKind::Res(res) => {
DeclKind::Def(res) => {
Some(self.def_id_to_node_id(res.def_id().expect_local()))
}
NameBindingKind::Import { import, .. } => import.id(),
DeclKind::Import { import, .. } => import.id(),
};
if let Some(binding_id) = binding_id {
self.lint_buffer.buffer_lint(
@ -685,7 +677,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
BuiltinLintDiag::HiddenGlobReexports {
name: key.ident.name.to_string(),
namespace: key.ns.descr().to_owned(),
glob_reexport_span: glob_binding.span,
glob_reexport_span: glob_decl.span,
private_item_span: binding.span,
},
);
@ -693,7 +685,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}
}
if let NameBindingKind::Import { import, .. } = binding.kind
if let DeclKind::Import { import, .. } = binding.kind
&& let Some(binding_id) = import.id()
&& let import_def_id = self.local_def_id(binding_id)
&& self.effective_visibilities.is_exported(import_def_id)
@ -846,8 +838,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
import.imported_module.set_unchecked(Some(module));
let (source, target, bindings, type_ns_only) = match import.kind {
ImportKind::Single { source, target, ref bindings, type_ns_only, .. } => {
(source, target, bindings, type_ns_only)
ImportKind::Single { source, target, ref decls, type_ns_only, .. } => {
(source, target, decls, type_ns_only)
}
ImportKind::Glob { .. } => {
self.get_mut_unchecked().resolve_glob_import(import);
@ -859,7 +851,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let mut indeterminate_count = 0;
self.per_ns_cm(|this, ns| {
if !type_ns_only || ns == TypeNS {
if bindings[ns].get() != PendingBinding::Pending {
if bindings[ns].get() != PendingDecl::Pending {
return;
};
let binding_result = this.reborrow().maybe_resolve_ident_in_module(
@ -884,14 +876,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
.emit();
}
// We need the `target`, `source` can be extracted.
let imported_binding = this.import(binding, import);
this.get_mut_unchecked().define_binding_local(
let import_decl = this.new_import_decl(binding, import);
this.get_mut_unchecked().plant_decl_into_local_module(
parent,
target,
ns,
imported_binding,
import_decl,
);
PendingBinding::Ready(Some(imported_binding))
PendingDecl::Ready(Some(import_decl))
}
Err(Determinacy::Determined) => {
// Don't remove underscores from `single_imports`, they were never added.
@ -906,11 +898,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
},
);
}
PendingBinding::Ready(None)
PendingDecl::Ready(None)
}
Err(Determinacy::Undetermined) => {
indeterminate_count += 1;
PendingBinding::Pending
PendingDecl::Pending
}
};
bindings[ns].set_unchecked(binding);
@ -925,8 +917,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
/// Optionally returns an unresolved import error. This error is buffered and used to
/// consolidate multiple unresolved import errors into a single diagnostic.
fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportError> {
let ignore_binding = match &import.kind {
ImportKind::Single { bindings, .. } => bindings[TypeNS].get().binding(),
let ignore_decl = match &import.kind {
ImportKind::Single { decls, .. } => decls[TypeNS].get().decl(),
_ => None,
};
let ambiguity_errors_len =
@ -942,7 +934,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None,
&import.parent_scope,
Some(finalize),
ignore_binding,
ignore_decl,
Some(import),
);
@ -1045,8 +1037,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};
let (ident, target, bindings, type_ns_only, import_id) = match import.kind {
ImportKind::Single { source, target, ref bindings, type_ns_only, id, .. } => {
(source, target, bindings, type_ns_only, id)
ImportKind::Single { source, target, ref decls, type_ns_only, id, .. } => {
(source, target, decls, type_ns_only, id)
}
ImportKind::Glob { ref max_vis, id } => {
if import.module_path.len() <= 1 {
@ -1102,7 +1094,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None,
&import.parent_scope,
Some(finalize),
ignore_binding,
ignore_decl,
None,
) {
let res = module.res().map(|r| (r, ident));
@ -1121,14 +1113,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ns,
&import.parent_scope,
Some(Finalize { report_private: false, ..finalize }),
bindings[ns].get().binding(),
bindings[ns].get().decl(),
Some(import),
);
match binding {
Ok(binding) => {
// Consistency checks, analogous to `finalize_macro_resolutions`.
let initial_res = bindings[ns].get().binding().map(|binding| {
let initial_res = bindings[ns].get().decl().map(|binding| {
let initial_binding = binding.import_source();
all_ns_err = false;
if target.name == kw::Underscore
@ -1205,13 +1197,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
} // Never suggest the same name
let resolution = resolution.borrow();
if let Some(name_binding) = resolution.best_binding() {
if let Some(name_binding) = resolution.best_decl() {
match name_binding.kind {
NameBindingKind::Import { binding, .. } => {
match binding.kind {
// Never suggest the name that has binding error
// i.e., the name that cannot be previously resolved
NameBindingKind::Res(Res::Err) => None,
DeclKind::Import { source_decl, .. } => {
match source_decl.kind {
// Never suggest names that previously could not
// be resolved.
DeclKind::Def(Res::Err) => None,
_ => Some(i.name),
}
}
@ -1295,7 +1287,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let mut any_successful_reexport = false;
let mut crate_private_reexport = false;
self.per_ns(|this, ns| {
let Some(binding) = bindings[ns].get().binding().map(|b| b.import_source()) else {
let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) else {
return;
};
@ -1342,7 +1334,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};
match binding.kind {
NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id))
DeclKind::Def(Res::Def(DefKind::Macro(_), def_id))
// exclude decl_macro
if self.get_macro_by_def_id(def_id).macro_rules =>
{
@ -1370,7 +1362,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let mut full_path = import.module_path.clone();
full_path.push(Segment::from_ident(ident));
self.per_ns(|this, ns| {
if let Some(binding) = bindings[ns].get().binding().map(|b| b.import_source()) {
if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) {
this.lint_if_path_starts_with_module(finalize, &full_path, Some(binding));
}
});
@ -1380,7 +1372,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// this may resolve to either a value or a type, but for documentation
// purposes it's good enough to just favor one over the other.
self.per_ns(|this, ns| {
if let Some(binding) = bindings[ns].get().binding().map(|b| b.import_source()) {
if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) {
this.import_res_map.entry(import_id).or_default()[ns] = Some(binding.res());
}
});
@ -1391,7 +1383,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> bool {
// This function is only called for single imports.
let ImportKind::Single { source, target, ref bindings, id, .. } = import.kind else {
let ImportKind::Single { source, target, ref decls, id, .. } = import.kind else {
unreachable!()
};
@ -1418,7 +1410,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let mut is_redundant = true;
let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
self.per_ns(|this, ns| {
let binding = bindings[ns].get().binding().map(|b| b.import_source());
let binding = decls[ns].get().decl().map(|b| b.import_source());
if is_redundant && let Some(binding) = binding {
if binding.res() == Res::Err {
return;
@ -1430,7 +1422,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
&import.parent_scope,
None,
false,
bindings[ns].get().binding(),
decls[ns].get().decl(),
None,
) {
Ok(other_binding) => {
@ -1505,16 +1497,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None => continue,
};
if self.is_accessible_from(binding.vis, scope) {
let imported_binding = self.import(binding, import);
let import_decl = self.new_import_decl(binding, import);
let warn_ambiguity = self
.resolution(import.parent_scope.module, key)
.and_then(|r| r.binding())
.is_some_and(|binding| binding.warn_ambiguity_recursive());
let _ = self.try_define_local(
let _ = self.try_plant_decl_into_local_module(
import.parent_scope.module,
key.ident.0,
key.ns,
imported_binding,
import_decl,
warn_ambiguity,
);
}

View file

@ -43,9 +43,9 @@ use thin_vec::ThinVec;
use tracing::{debug, instrument, trace};
use crate::{
BindingError, BindingKey, Finalize, LexicalScopeBinding, Module, ModuleOrUniformRoot,
NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, Stage, TyCtxt,
UseError, Used, errors, path_names_to_string, rustdoc,
BindingError, BindingKey, Decl, Finalize, LateDecl, Module, ModuleOrUniformRoot, ParentScope,
PathResult, ResolutionError, Resolver, Segment, Stage, TyCtxt, UseError, Used, errors,
path_names_to_string, rustdoc,
};
mod diagnostics;
@ -677,7 +677,7 @@ impl MaybeExported<'_> {
/// Used for recording UnnecessaryQualification.
#[derive(Debug)]
pub(crate) struct UnnecessaryQualification<'ra> {
pub binding: LexicalScopeBinding<'ra>,
pub decl: LateDecl<'ra>,
pub node_id: NodeId,
pub path_span: Span,
pub removal_span: Span,
@ -1472,7 +1472,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
&mut self,
ident: Ident,
ns: Namespace,
) -> Option<LexicalScopeBinding<'ra>> {
) -> Option<LateDecl<'ra>> {
self.r.resolve_ident_in_lexical_scope(
ident,
ns,
@ -1489,15 +1489,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
ident: Ident,
ns: Namespace,
finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'ra>>,
) -> Option<LexicalScopeBinding<'ra>> {
ignore_decl: Option<Decl<'ra>>,
) -> Option<LateDecl<'ra>> {
self.r.resolve_ident_in_lexical_scope(
ident,
ns,
&self.parent_scope,
finalize,
&self.ribs[ns],
ignore_binding,
ignore_decl,
Some(&self.diag_metadata),
)
}
@ -2685,11 +2685,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
for &ns in nss {
match self.maybe_resolve_ident_in_lexical_scope(ident, ns) {
Some(LexicalScopeBinding::Res(..)) => {
Some(LateDecl::RibDef(..)) => {
report_error(self, ns);
}
Some(LexicalScopeBinding::Item(binding)) => {
if let Some(LexicalScopeBinding::Res(..)) =
Some(LateDecl::Decl(binding)) => {
if let Some(LateDecl::RibDef(..)) =
self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding))
{
report_error(self, ns);
@ -3630,9 +3630,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
};
ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
let key = BindingKey::new(ident, ns);
let mut binding = self.r.resolution(module, key).and_then(|r| r.best_binding());
debug!(?binding);
if binding.is_none() {
let mut decl = self.r.resolution(module, key).and_then(|r| r.best_decl());
debug!(?decl);
if decl.is_none() {
// We could not find the trait item in the correct namespace.
// Check the other namespace to report an error.
let ns = match ns {
@ -3641,8 +3641,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
_ => ns,
};
let key = BindingKey::new(ident, ns);
binding = self.r.resolution(module, key).and_then(|r| r.best_binding());
debug!(?binding);
decl = self.r.resolution(module, key).and_then(|r| r.best_decl());
debug!(?decl);
}
let feed_visibility = |this: &mut Self, def_id| {
@ -3659,7 +3659,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
this.r.feed_visibility(this.r.feed(id), vis);
};
let Some(binding) = binding else {
let Some(decl) = decl else {
// We could not find the method: report an error.
let candidate = self.find_similarly_named_assoc_item(ident.name, kind);
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
@ -3669,7 +3669,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
return;
};
let res = binding.res();
let res = decl.res();
let Res::Def(def_kind, id_in_trait) = res else { bug!() };
feed_visibility(self, id_in_trait);
@ -3680,7 +3680,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
ResolutionError::TraitImplDuplicate {
name: ident,
old_span: *entry.get(),
trait_item_span: binding.span,
trait_item_span: decl.span,
},
);
return;
@ -3720,7 +3720,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
kind,
code,
trait_path,
trait_item_span: binding.span,
trait_item_span: decl.span,
},
);
}
@ -4257,7 +4257,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?;
let (res, binding) = match ls_binding {
LexicalScopeBinding::Item(binding)
LateDecl::Decl(binding)
if is_syntactic_ambiguity && binding.is_ambiguity_recursive() =>
{
// For ambiguous bindings we don't know all their definitions and cannot check
@ -4267,8 +4267,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
self.r.record_use(ident, binding, Used::Other);
return None;
}
LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)),
LexicalScopeBinding::Res(res) => (res, None),
LateDecl::Decl(binding) => (binding.res(), Some(binding)),
LateDecl::RibDef(res) => (res, None),
};
match res {
@ -4641,13 +4641,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
fn self_type_is_available(&mut self) -> bool {
let binding = self
.maybe_resolve_ident_in_lexical_scope(Ident::with_dummy_span(kw::SelfUpper), TypeNS);
if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
if let Some(LateDecl::RibDef(res)) = binding { res != Res::Err } else { false }
}
fn self_value_is_available(&mut self, self_span: Span) -> bool {
let ident = Ident::new(kw::SelfLower, self_span);
let binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS);
if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
if let Some(LateDecl::RibDef(res)) = binding { res != Res::Err } else { false }
}
/// A wrapper around [`Resolver::report_error`].
@ -5356,9 +5356,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
(res == binding.res()).then_some((seg, binding))
});
if let Some((seg, binding)) = unqualified {
if let Some((seg, decl)) = unqualified {
self.r.potentially_unnecessary_qualifications.push(UnnecessaryQualification {
binding,
decl,
node_id: finalize.node_id,
path_span: finalize.path_span,
removal_span: path[0].ident.span.until(seg.ident.span),

View file

@ -891,10 +891,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
fn lookup_doc_alias_name(&mut self, path: &[Segment], ns: Namespace) -> Option<(DefId, Ident)> {
let find_doc_alias_name = |r: &mut Resolver<'ra, '_>, m: Module<'ra>, item_name: Symbol| {
for resolution in r.resolutions(m).borrow().values() {
let Some(did) = resolution
.borrow()
.best_binding()
.and_then(|binding| binding.res().opt_def_id())
let Some(did) =
resolution.borrow().best_decl().and_then(|binding| binding.res().opt_def_id())
else {
continue;
};
@ -1589,19 +1587,17 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
self.resolve_path(mod_path, None, None, *source)
{
let targets: Vec<_> = self
.r
.resolutions(module)
.borrow()
.iter()
.filter_map(|(key, resolution)| {
resolution
.borrow()
.best_binding()
.map(|binding| binding.res())
.and_then(|res| if filter_fn(res) { Some((*key, res)) } else { None })
})
.collect();
let targets: Vec<_> =
self.r
.resolutions(module)
.borrow()
.iter()
.filter_map(|(key, resolution)| {
resolution.borrow().best_decl().map(|binding| binding.res()).and_then(
|res| if filter_fn(res) { Some((*key, res)) } else { None },
)
})
.collect();
if let [target] = targets.as_slice() {
return Some(TypoSuggestion::single_item_from_ident(
target.0.ident.0,
@ -2486,9 +2482,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
.resolutions(*module)
.borrow()
.iter()
.filter_map(|(key, res)| {
res.borrow().best_binding().map(|binding| (key, binding.res()))
})
.filter_map(|(key, res)| res.borrow().best_decl().map(|binding| (key, binding.res())))
.filter(|(_, res)| match (kind, res) {
(AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true,
(AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true,

View file

@ -33,12 +33,12 @@ use std::sync::Arc;
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
use effective_visibilities::EffectiveVisibilitiesVisitor;
use errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
use imports::{Import, ImportData, ImportKind, NameResolution, PendingBinding};
use imports::{Import, ImportData, ImportKind, NameResolution, PendingDecl};
use late::{
ForwardGenericParamBanReason, HasGenericParams, PathSource, PatternSource,
UnnecessaryQualification,
};
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
use macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef};
use rustc_arena::{DroplessArena, TypedArena};
use rustc_ast::node_id::NodeMap;
use rustc_ast::{
@ -424,22 +424,21 @@ impl<'a> From<&'a ast::PathSegment> for Segment {
}
}
/// An intermediate resolution result.
///
/// This refers to the thing referred by a name. The difference between `Res` and `Item` is that
/// items are visible in their whole block, while `Res`es only from the place they are defined
/// forward.
/// Name declaration used during late resolution.
#[derive(Debug, Copy, Clone)]
enum LexicalScopeBinding<'ra> {
Item(NameBinding<'ra>),
Res(Res),
enum LateDecl<'ra> {
/// A regular name declaration.
Decl(Decl<'ra>),
/// A name definition from a rib, e.g. a local variable.
/// Omits most of the data from regular `Decl` for performance reasons.
RibDef(Res),
}
impl<'ra> LexicalScopeBinding<'ra> {
impl<'ra> LateDecl<'ra> {
fn res(self) -> Res {
match self {
LexicalScopeBinding::Item(binding) => binding.res(),
LexicalScopeBinding::Res(res) => res,
LateDecl::Decl(binding) => binding.res(),
LateDecl::RibDef(res) => res,
}
}
}
@ -624,17 +623,16 @@ struct ModuleData<'ra> {
globs: CmRefCell<Vec<Import<'ra>>>,
/// Used to memoize the traits in this module for faster searches through all traits in scope.
traits:
CmRefCell<Option<Box<[(Macros20NormalizedIdent, NameBinding<'ra>, Option<Module<'ra>>)]>>>,
traits: CmRefCell<Option<Box<[(Macros20NormalizedIdent, Decl<'ra>, Option<Module<'ra>>)]>>>,
/// Span of the module itself. Used for error reporting.
span: Span,
expansion: ExpnId,
/// Binding for implicitly declared names that come with a module,
/// Declaration for implicitly declared names that come with a module,
/// like `self` (not yet used), or `crate`/`$crate` (for root modules).
self_binding: Option<NameBinding<'ra>>,
self_decl: Option<Decl<'ra>>,
}
/// All modules are unique and allocated on a same arena,
@ -663,7 +661,7 @@ impl<'ra> ModuleData<'ra> {
expansion: ExpnId,
span: Span,
no_implicit_prelude: bool,
self_binding: Option<NameBinding<'ra>>,
self_decl: Option<Decl<'ra>>,
) -> Self {
let is_foreign = match kind {
ModuleKind::Def(_, def_id, _) => !def_id.is_local(),
@ -682,7 +680,7 @@ impl<'ra> ModuleData<'ra> {
traits: CmRefCell::new(None),
span,
expansion,
self_binding,
self_decl,
}
}
}
@ -691,11 +689,11 @@ impl<'ra> Module<'ra> {
fn for_each_child<'tcx, R: AsRef<Resolver<'ra, 'tcx>>>(
self,
resolver: &R,
mut f: impl FnMut(&R, Macros20NormalizedIdent, Namespace, NameBinding<'ra>),
mut f: impl FnMut(&R, Macros20NormalizedIdent, Namespace, Decl<'ra>),
) {
for (key, name_resolution) in resolver.as_ref().resolutions(self).borrow().iter() {
if let Some(binding) = name_resolution.borrow().best_binding() {
f(resolver, key.ident, key.ns, binding);
if let Some(decl) = name_resolution.borrow().best_decl() {
f(resolver, key.ident, key.ns, decl);
}
}
}
@ -703,11 +701,11 @@ impl<'ra> Module<'ra> {
fn for_each_child_mut<'tcx, R: AsMut<Resolver<'ra, 'tcx>>>(
self,
resolver: &mut R,
mut f: impl FnMut(&mut R, Macros20NormalizedIdent, Namespace, NameBinding<'ra>),
mut f: impl FnMut(&mut R, Macros20NormalizedIdent, Namespace, Decl<'ra>),
) {
for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
if let Some(binding) = name_resolution.borrow().best_binding() {
f(resolver, key.ident, key.ns, binding);
if let Some(decl) = name_resolution.borrow().best_decl() {
f(resolver, key.ident, key.ns, decl);
}
}
}
@ -803,11 +801,11 @@ impl<'ra> fmt::Debug for Module<'ra> {
}
}
/// Records a possibly-private value, type, or module definition.
/// Data associated with any name declaration.
#[derive(Clone, Copy, Debug)]
struct NameBindingData<'ra> {
kind: NameBindingKind<'ra>,
ambiguity: Option<NameBinding<'ra>>,
struct DeclData<'ra> {
kind: DeclKind<'ra>,
ambiguity: Option<Decl<'ra>>,
/// Produce a warning instead of an error when reporting ambiguities inside this binding.
/// May apply to indirect ambiguities under imports, so `ambiguity.is_some()` is not required.
warn_ambiguity: bool,
@ -816,15 +814,15 @@ struct NameBindingData<'ra> {
vis: Visibility<DefId>,
}
/// All name bindings are unique and allocated on a same arena,
/// All name declarations are unique and allocated on a same arena,
/// so we can use referential equality to compare them.
type NameBinding<'ra> = Interned<'ra, NameBindingData<'ra>>;
type Decl<'ra> = Interned<'ra, DeclData<'ra>>;
// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the
// contained data.
// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees
// are upheld.
impl std::hash::Hash for NameBindingData<'_> {
impl std::hash::Hash for DeclData<'_> {
fn hash<H>(&self, _: &mut H)
where
H: std::hash::Hasher,
@ -833,23 +831,27 @@ impl std::hash::Hash for NameBindingData<'_> {
}
}
/// Name declaration kind.
#[derive(Clone, Copy, Debug)]
enum NameBindingKind<'ra> {
Res(Res),
Import { binding: NameBinding<'ra>, import: Import<'ra> },
enum DeclKind<'ra> {
/// The name declaration is a definition (possibly without a `DefId`),
/// can be provided by source code or built into the language.
Def(Res),
/// The name declaration is a link to another name declaration.
Import { source_decl: Decl<'ra>, import: Import<'ra> },
}
impl<'ra> NameBindingKind<'ra> {
/// Is this a name binding of an import?
impl<'ra> DeclKind<'ra> {
/// Is this an import declaration?
fn is_import(&self) -> bool {
matches!(*self, NameBindingKind::Import { .. })
matches!(*self, DeclKind::Import { .. })
}
}
#[derive(Debug)]
struct PrivacyError<'ra> {
ident: Ident,
binding: NameBinding<'ra>,
decl: Decl<'ra>,
dedup_span: Span,
outermost_res: Option<(Res, Ident)>,
parent_scope: ParentScope<'ra>,
@ -912,36 +914,34 @@ impl AmbiguityKind {
struct AmbiguityError<'ra> {
kind: AmbiguityKind,
ident: Ident,
b1: NameBinding<'ra>,
b2: NameBinding<'ra>,
b1: Decl<'ra>,
b2: Decl<'ra>,
// `empty_module` in module scope serves as an unknown module here.
scope1: Scope<'ra>,
scope2: Scope<'ra>,
warning: bool,
}
impl<'ra> NameBindingData<'ra> {
impl<'ra> DeclData<'ra> {
fn res(&self) -> Res {
match self.kind {
NameBindingKind::Res(res) => res,
NameBindingKind::Import { binding, .. } => binding.res(),
DeclKind::Def(res) => res,
DeclKind::Import { source_decl, .. } => source_decl.res(),
}
}
fn import_source(&self) -> NameBinding<'ra> {
fn import_source(&self) -> Decl<'ra> {
match self.kind {
NameBindingKind::Import { binding, .. } => binding,
DeclKind::Import { source_decl, .. } => source_decl,
_ => unreachable!(),
}
}
fn descent_to_ambiguity(
self: NameBinding<'ra>,
) -> Option<(NameBinding<'ra>, NameBinding<'ra>)> {
fn descent_to_ambiguity(self: Decl<'ra>) -> Option<(Decl<'ra>, Decl<'ra>)> {
match self.ambiguity {
Some(ambig_binding) => Some((self, ambig_binding)),
None => match self.kind {
NameBindingKind::Import { binding, .. } => binding.descent_to_ambiguity(),
DeclKind::Import { source_decl, .. } => source_decl.descent_to_ambiguity(),
_ => None,
},
}
@ -950,7 +950,7 @@ impl<'ra> NameBindingData<'ra> {
fn is_ambiguity_recursive(&self) -> bool {
self.ambiguity.is_some()
|| match self.kind {
NameBindingKind::Import { binding, .. } => binding.is_ambiguity_recursive(),
DeclKind::Import { source_decl, .. } => source_decl.is_ambiguity_recursive(),
_ => false,
}
}
@ -958,46 +958,45 @@ impl<'ra> NameBindingData<'ra> {
fn warn_ambiguity_recursive(&self) -> bool {
self.warn_ambiguity
|| match self.kind {
NameBindingKind::Import { binding, .. } => binding.warn_ambiguity_recursive(),
DeclKind::Import { source_decl, .. } => source_decl.warn_ambiguity_recursive(),
_ => false,
}
}
fn is_possibly_imported_variant(&self) -> bool {
match self.kind {
NameBindingKind::Import { binding, .. } => binding.is_possibly_imported_variant(),
NameBindingKind::Res(Res::Def(
DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..),
_,
)) => true,
NameBindingKind::Res(..) => false,
DeclKind::Import { source_decl, .. } => source_decl.is_possibly_imported_variant(),
DeclKind::Def(Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), _)) => {
true
}
DeclKind::Def(..) => false,
}
}
fn is_extern_crate(&self) -> bool {
match self.kind {
NameBindingKind::Import { import, .. } => {
DeclKind::Import { import, .. } => {
matches!(import.kind, ImportKind::ExternCrate { .. })
}
NameBindingKind::Res(Res::Def(_, def_id)) => def_id.is_crate_root(),
DeclKind::Def(Res::Def(_, def_id)) => def_id.is_crate_root(),
_ => false,
}
}
fn is_import(&self) -> bool {
matches!(self.kind, NameBindingKind::Import { .. })
matches!(self.kind, DeclKind::Import { .. })
}
/// The binding introduced by `#[macro_export] macro_rules` is a public import, but it might
/// not be perceived as such by users, so treat it as a non-import in some diagnostics.
fn is_import_user_facing(&self) -> bool {
matches!(self.kind, NameBindingKind::Import { import, .. }
matches!(self.kind, DeclKind::Import { import, .. }
if !matches!(import.kind, ImportKind::MacroExport))
}
fn is_glob_import(&self) -> bool {
match self.kind {
NameBindingKind::Import { import, .. } => import.is_glob(),
DeclKind::Import { import, .. } => import.is_glob(),
_ => false,
}
}
@ -1010,12 +1009,12 @@ impl<'ra> NameBindingData<'ra> {
self.res().macro_kinds()
}
fn reexport_chain(self: NameBinding<'ra>, r: &Resolver<'_, '_>) -> SmallVec<[Reexport; 2]> {
fn reexport_chain(self: Decl<'ra>, r: &Resolver<'_, '_>) -> SmallVec<[Reexport; 2]> {
let mut reexport_chain = SmallVec::new();
let mut next_binding = self;
while let NameBindingKind::Import { binding, import, .. } = next_binding.kind {
while let DeclKind::Import { source_decl, import, .. } = next_binding.kind {
reexport_chain.push(import.simplify(r));
next_binding = binding;
next_binding = source_decl;
}
reexport_chain
}
@ -1026,16 +1025,12 @@ impl<'ra> NameBindingData<'ra> {
// in some later round and screw up our previously found resolution.
// See more detailed explanation in
// https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049
fn may_appear_after(
&self,
invoc_parent_expansion: LocalExpnId,
binding: NameBinding<'_>,
) -> bool {
// self > max(invoc, binding) => !(self <= invoc || self <= binding)
fn may_appear_after(&self, invoc_parent_expansion: LocalExpnId, decl: Decl<'_>) -> bool {
// self > max(invoc, decl) => !(self <= invoc || self <= decl)
// Expansions are partially ordered, so "may appear after" is an inversion of
// "certainly appears before or simultaneously" and includes unordered cases.
let self_parent_expansion = self.expansion;
let other_parent_expansion = binding.expansion;
let other_parent_expansion = decl.expansion;
let certainly_before_other_or_simultaneously =
other_parent_expansion.is_descendant_of(self_parent_expansion);
let certainly_before_invoc_or_simultaneously =
@ -1048,9 +1043,9 @@ impl<'ra> NameBindingData<'ra> {
// FIXME: How can we integrate it with the `update_resolution`?
fn determined(&self) -> bool {
match &self.kind {
NameBindingKind::Import { binding, import, .. } if import.is_glob() => {
DeclKind::Import { source_decl, import, .. } if import.is_glob() => {
import.parent_scope.module.unexpanded_invocations.borrow().is_empty()
&& binding.determined()
&& source_decl.determined()
}
_ => true,
}
@ -1058,23 +1053,23 @@ impl<'ra> NameBindingData<'ra> {
}
struct ExternPreludeEntry<'ra> {
/// Binding from an `extern crate` item.
/// The boolean flag is true is `item_binding` is non-redundant, happens either when
/// `flag_binding` is `None`, or when `extern crate` introducing `item_binding` used renaming.
item_binding: Option<(NameBinding<'ra>, /* introduced by item */ bool)>,
/// Binding from an `--extern` flag, lazily populated on first use.
flag_binding: Option<CacheCell<(PendingBinding<'ra>, /* finalized */ bool)>>,
/// Name declaration from an `extern crate` item.
/// The boolean flag is true is `item_decl` is non-redundant, happens either when
/// `flag_decl` is `None`, or when `extern crate` introducing `item_decl` used renaming.
item_decl: Option<(Decl<'ra>, /* introduced by item */ bool)>,
/// Name declaration from an `--extern` flag, lazily populated on first use.
flag_decl: Option<CacheCell<(PendingDecl<'ra>, /* finalized */ bool)>>,
}
impl ExternPreludeEntry<'_> {
fn introduced_by_item(&self) -> bool {
matches!(self.item_binding, Some((_, true)))
matches!(self.item_decl, Some((_, true)))
}
fn flag() -> Self {
ExternPreludeEntry {
item_binding: None,
flag_binding: Some(CacheCell::new((PendingBinding::Pending, false))),
item_decl: None,
flag_decl: Some(CacheCell::new((PendingDecl::Pending, false))),
}
}
}
@ -1181,7 +1176,7 @@ pub struct Resolver<'ra, 'tcx> {
local_module_map: FxIndexMap<LocalDefId, Module<'ra>>,
/// Lazily populated cache of modules loaded from external crates.
extern_module_map: CacheRefCell<FxIndexMap<DefId, Module<'ra>>>,
binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
decl_parent_modules: FxHashMap<Decl<'ra>, Module<'ra>>,
/// Maps glob imports to the names of items actually imported.
glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
@ -1206,14 +1201,14 @@ pub struct Resolver<'ra, 'tcx> {
inaccessible_ctor_reexport: FxHashMap<Span, Span>,
arenas: &'ra ResolverArenas<'ra>,
dummy_binding: NameBinding<'ra>,
builtin_types_bindings: FxHashMap<Symbol, NameBinding<'ra>>,
builtin_attrs_bindings: FxHashMap<Symbol, NameBinding<'ra>>,
registered_tool_bindings: FxHashMap<Ident, NameBinding<'ra>>,
dummy_decl: Decl<'ra>,
builtin_type_decls: FxHashMap<Symbol, Decl<'ra>>,
builtin_attr_decls: FxHashMap<Symbol, Decl<'ra>>,
registered_tool_decls: FxHashMap<Ident, Decl<'ra>>,
macro_names: FxHashSet<Ident>,
builtin_macros: FxHashMap<Symbol, SyntaxExtensionKind>,
registered_tools: &'tcx RegisteredTools,
macro_use_prelude: FxIndexMap<Symbol, NameBinding<'ra>>,
macro_use_prelude: FxIndexMap<Symbol, Decl<'ra>>,
/// Eagerly populated map of all local macro definitions.
local_macro_map: FxHashMap<LocalDefId, &'ra MacroData>,
/// Lazily populated cache of macro definitions loaded from external crates.
@ -1229,7 +1224,7 @@ pub struct Resolver<'ra, 'tcx> {
proc_macro_stubs: FxHashSet<LocalDefId>,
/// Traces collected during macro resolution and validated when it's complete.
single_segment_macro_resolutions:
CmRefCell<Vec<(Ident, MacroKind, ParentScope<'ra>, Option<NameBinding<'ra>>, Option<Span>)>>,
CmRefCell<Vec<(Ident, MacroKind, ParentScope<'ra>, Option<Decl<'ra>>, Option<Span>)>>,
multi_segment_macro_resolutions:
CmRefCell<Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'ra>, Option<Res>, Namespace)>>,
builtin_attrs: Vec<(Ident, ParentScope<'ra>)>,
@ -1246,7 +1241,7 @@ pub struct Resolver<'ra, 'tcx> {
/// `macro_rules` scopes produced by `macro_rules` item definitions.
macro_rules_scopes: FxHashMap<LocalDefId, MacroRulesScopeRef<'ra>>,
/// Helper attributes that are in scope for the given expansion.
helper_attrs: FxHashMap<LocalExpnId, Vec<(Ident, NameBinding<'ra>)>>,
helper_attrs: FxHashMap<LocalExpnId, Vec<(Ident, Decl<'ra>)>>,
/// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute
/// with the given `ExpnId`.
derive_data: FxHashMap<LocalExpnId, DeriveData>,
@ -1338,15 +1333,15 @@ pub struct ResolverArenas<'ra> {
}
impl<'ra> ResolverArenas<'ra> {
fn new_res_binding(
fn new_def_decl(
&'ra self,
res: Res,
vis: Visibility<DefId>,
span: Span,
expansion: LocalExpnId,
) -> NameBinding<'ra> {
self.alloc_name_binding(NameBindingData {
kind: NameBindingKind::Res(res),
) -> Decl<'ra> {
self.alloc_decl(DeclData {
kind: DeclKind::Def(res),
ambiguity: None,
warn_ambiguity: false,
vis,
@ -1355,13 +1350,8 @@ impl<'ra> ResolverArenas<'ra> {
})
}
fn new_pub_res_binding(
&'ra self,
res: Res,
span: Span,
expn_id: LocalExpnId,
) -> NameBinding<'ra> {
self.new_res_binding(res, Visibility::Public, span, expn_id)
fn new_pub_def_decl(&'ra self, res: Res, span: Span, expn_id: LocalExpnId) -> Decl<'ra> {
self.new_def_decl(res, Visibility::Public, span, expn_id)
}
fn new_module(
@ -1372,9 +1362,9 @@ impl<'ra> ResolverArenas<'ra> {
span: Span,
no_implicit_prelude: bool,
) -> Module<'ra> {
let self_binding = match kind {
let self_decl = match kind {
ModuleKind::Def(def_kind, def_id, _) => {
Some(self.new_pub_res_binding(Res::Def(def_kind, def_id), span, LocalExpnId::ROOT))
Some(self.new_pub_def_decl(Res::Def(def_kind, def_id), span, LocalExpnId::ROOT))
}
ModuleKind::Block => None,
};
@ -1384,11 +1374,11 @@ impl<'ra> ResolverArenas<'ra> {
expn_id,
span,
no_implicit_prelude,
self_binding,
self_decl,
))))
}
fn alloc_name_binding(&'ra self, name_binding: NameBindingData<'ra>) -> NameBinding<'ra> {
Interned::new_unchecked(self.dropless.alloc(name_binding))
fn alloc_decl(&'ra self, data: DeclData<'ra>) -> Decl<'ra> {
Interned::new_unchecked(self.dropless.alloc(data))
}
fn alloc_import(&'ra self, import: ImportData<'ra>) -> Import<'ra> {
Interned::new_unchecked(self.imports.alloc(import))
@ -1399,11 +1389,8 @@ impl<'ra> ResolverArenas<'ra> {
fn alloc_macro_rules_scope(&'ra self, scope: MacroRulesScope<'ra>) -> MacroRulesScopeRef<'ra> {
self.dropless.alloc(CacheCell::new(scope))
}
fn alloc_macro_rules_binding(
&'ra self,
binding: MacroRulesBinding<'ra>,
) -> &'ra MacroRulesBinding<'ra> {
self.dropless.alloc(binding)
fn alloc_macro_rules_decl(&'ra self, decl: MacroRulesDecl<'ra>) -> &'ra MacroRulesDecl<'ra> {
self.dropless.alloc(decl)
}
fn alloc_ast_paths(&'ra self, paths: &[ast::Path]) -> &'ra [ast::Path] {
self.ast_paths.alloc_from_iter(paths.iter().cloned())
@ -1619,7 +1606,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
local_module_map,
extern_module_map: Default::default(),
block_map: Default::default(),
binding_parent_modules: FxHashMap::default(),
decl_parent_modules: FxHashMap::default(),
ast_transform_scopes: FxHashMap::default(),
glob_map: Default::default(),
@ -1628,29 +1615,29 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
inaccessible_ctor_reexport: Default::default(),
arenas,
dummy_binding: arenas.new_pub_res_binding(Res::Err, DUMMY_SP, LocalExpnId::ROOT),
builtin_types_bindings: PrimTy::ALL
dummy_decl: arenas.new_pub_def_decl(Res::Err, DUMMY_SP, LocalExpnId::ROOT),
builtin_type_decls: PrimTy::ALL
.iter()
.map(|prim_ty| {
let res = Res::PrimTy(*prim_ty);
let binding = arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT);
(prim_ty.name(), binding)
let decl = arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT);
(prim_ty.name(), decl)
})
.collect(),
builtin_attrs_bindings: BUILTIN_ATTRIBUTES
builtin_attr_decls: BUILTIN_ATTRIBUTES
.iter()
.map(|builtin_attr| {
let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(builtin_attr.name));
let binding = arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT);
(builtin_attr.name, binding)
let decl = arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT);
(builtin_attr.name, decl)
})
.collect(),
registered_tool_bindings: registered_tools
registered_tool_decls: registered_tools
.iter()
.map(|ident| {
let res = Res::ToolMod;
let binding = arenas.new_pub_res_binding(res, ident.span, LocalExpnId::ROOT);
(*ident, binding)
let decl = arenas.new_pub_def_decl(res, ident.span, LocalExpnId::ROOT);
(*ident, decl)
})
.collect(),
macro_names: FxHashSet::default(),
@ -1994,18 +1981,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
fn find_transitive_imports(
&mut self,
mut kind: &NameBindingKind<'_>,
mut kind: &DeclKind<'_>,
trait_name: Ident,
) -> SmallVec<[LocalDefId; 1]> {
let mut import_ids = smallvec![];
while let NameBindingKind::Import { import, binding, .. } = kind {
while let DeclKind::Import { import, source_decl, .. } = kind {
if let Some(node_id) = import.id() {
let def_id = self.local_def_id(node_id);
self.maybe_unused_trait_imports.insert(def_id);
import_ids.push(def_id);
}
self.add_to_glob_map(*import, trait_name);
kind = &binding.kind;
kind = &source_decl.kind;
}
import_ids
}
@ -2053,22 +2040,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
false
}
fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'ra>, used: Used) {
self.record_use_inner(ident, used_binding, used, used_binding.warn_ambiguity);
fn record_use(&mut self, ident: Ident, used_decl: Decl<'ra>, used: Used) {
self.record_use_inner(ident, used_decl, used, used_decl.warn_ambiguity);
}
fn record_use_inner(
&mut self,
ident: Ident,
used_binding: NameBinding<'ra>,
used_decl: Decl<'ra>,
used: Used,
warn_ambiguity: bool,
) {
if let Some(b2) = used_binding.ambiguity {
if let Some(b2) = used_decl.ambiguity {
let ambiguity_error = AmbiguityError {
kind: AmbiguityKind::GlobVsGlob,
ident,
b1: used_binding,
b1: used_decl,
b2,
scope1: Scope::ModuleGlobs(self.empty_module, None),
scope2: Scope::ModuleGlobs(self.empty_module, None),
@ -2079,7 +2066,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.ambiguity_errors.push(ambiguity_error);
}
}
if let NameBindingKind::Import { import, binding } = used_binding.kind {
if let DeclKind::Import { import, source_decl } = used_decl.kind {
if let ImportKind::MacroUse { warn_private: true } = import.kind {
// Do not report the lint if the macro name resolves in stdlib prelude
// even without the problematic `macro_use` import.
@ -2109,7 +2096,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// but not introduce it, as used if they are accessed from lexical scope.
if used == Used::Scope
&& let Some(entry) = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident))
&& entry.item_binding == Some((used_binding, false))
&& entry.item_decl == Some((used_decl, false))
{
return;
}
@ -2123,9 +2110,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
self.add_to_glob_map(import, ident);
self.record_use_inner(
ident,
binding,
source_decl,
Used::Other,
warn_ambiguity || binding.warn_ambiguity,
warn_ambiguity || source_decl.warn_ambiguity,
);
}
}
@ -2236,18 +2223,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
vis.is_accessible_from(module.nearest_parent_mod(), self.tcx)
}
fn set_binding_parent_module(&mut self, binding: NameBinding<'ra>, module: Module<'ra>) {
if let Some(old_module) = self.binding_parent_modules.insert(binding, module) {
fn set_decl_parent_module(&mut self, decl: Decl<'ra>, module: Module<'ra>) {
if let Some(old_module) = self.decl_parent_modules.insert(decl, module) {
if module != old_module {
span_bug!(binding.span, "parent module is reset for binding");
span_bug!(decl.span, "parent module is reset for a name declaration");
}
}
}
fn disambiguate_macro_rules_vs_modularized(
&self,
macro_rules: NameBinding<'ra>,
modularized: NameBinding<'ra>,
macro_rules: Decl<'ra>,
modularized: Decl<'ra>,
) -> bool {
// Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules"
// is disambiguated to mitigate regressions from macro modularization.
@ -2256,8 +2243,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// panic on index should be impossible, the only name_bindings passed in should be from
// `resolve_ident_in_scope_set` which will always refer to a local binding from an
// import or macro definition
let macro_rules = &self.binding_parent_modules[&macro_rules];
let modularized = &self.binding_parent_modules[&modularized];
let macro_rules = &self.decl_parent_modules[&macro_rules];
let modularized = &self.decl_parent_modules[&modularized];
macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod()
&& modularized.is_ancestor_of(*macro_rules)
}
@ -2266,9 +2253,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
mut self: CmResolver<'r, 'ra, 'tcx>,
ident: Ident,
finalize: bool,
) -> Option<NameBinding<'ra>> {
) -> Option<Decl<'ra>> {
let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident));
entry.and_then(|entry| entry.item_binding).map(|(binding, _)| {
entry.and_then(|entry| entry.item_decl).map(|(binding, _)| {
if finalize {
self.get_mut().record_use(ident, binding, Used::Scope);
}
@ -2276,18 +2263,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
})
}
fn extern_prelude_get_flag(&self, ident: Ident, finalize: bool) -> Option<NameBinding<'ra>> {
fn extern_prelude_get_flag(&self, ident: Ident, finalize: bool) -> Option<Decl<'ra>> {
let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident));
entry.and_then(|entry| entry.flag_binding.as_ref()).and_then(|flag_binding| {
let (pending_binding, finalized) = flag_binding.get();
let binding = match pending_binding {
PendingBinding::Ready(binding) => {
entry.and_then(|entry| entry.flag_decl.as_ref()).and_then(|flag_decl| {
let (pending_decl, finalized) = flag_decl.get();
let decl = match pending_decl {
PendingDecl::Ready(decl) => {
if finalize && !finalized {
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span);
}
binding
decl
}
PendingBinding::Pending => {
PendingDecl::Pending => {
debug_assert!(!finalized);
let crate_id = if finalize {
self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span)
@ -2296,12 +2283,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
};
crate_id.map(|crate_id| {
let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT)
self.arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT)
})
}
};
flag_binding.set((PendingBinding::Ready(binding), finalize || finalized));
binding.or_else(|| finalize.then_some(self.dummy_binding))
flag_decl.set((PendingDecl::Ready(decl), finalize || finalized));
decl.or_else(|| finalize.then_some(self.dummy_decl))
})
}

View file

@ -38,18 +38,18 @@ use crate::errors::{
};
use crate::imports::Import;
use crate::{
BindingKey, CacheCell, CmResolver, DeriveData, Determinacy, Finalize, InvocationParent,
MacroData, ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope,
PathResult, ResolutionError, Resolver, ScopeSet, Segment, Used,
BindingKey, CacheCell, CmResolver, Decl, DeclKind, DeriveData, Determinacy, Finalize,
InvocationParent, MacroData, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult,
ResolutionError, Resolver, ScopeSet, Segment, Used,
};
type Res = def::Res<NodeId>;
/// Binding produced by a `macro_rules` item.
/// Not modularized, can shadow previous `macro_rules` bindings, etc.
/// Name declaration produced by a `macro_rules` item definition.
/// Not modularized, can shadow previous `macro_rules` definitions, etc.
#[derive(Debug)]
pub(crate) struct MacroRulesBinding<'ra> {
pub(crate) binding: NameBinding<'ra>,
pub(crate) struct MacroRulesDecl<'ra> {
pub(crate) decl: Decl<'ra>,
/// `macro_rules` scope into which the `macro_rules` item was planted.
pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'ra>,
pub(crate) ident: Ident,
@ -65,7 +65,7 @@ pub(crate) enum MacroRulesScope<'ra> {
/// Empty "root" scope at the crate start containing no names.
Empty,
/// The scope introduced by a `macro_rules!` macro definition.
Binding(&'ra MacroRulesBinding<'ra>),
Def(&'ra MacroRulesDecl<'ra>),
/// The scope introduced by a macro invocation that can potentially
/// create a `macro_rules!` macro definition.
Invocation(LocalExpnId),
@ -431,8 +431,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
.iter()
.map(|(_, ident)| {
let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
let binding = self.arenas.new_pub_res_binding(res, ident.span, expn_id);
(*ident, binding)
(*ident, self.arenas.new_pub_def_decl(res, ident.span, expn_id))
})
.collect();
self.helper_attrs.insert(expn_id, helper_attrs);
@ -1062,18 +1061,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
fn prohibit_imported_non_macro_attrs(
&self,
binding: Option<NameBinding<'ra>>,
decl: Option<Decl<'ra>>,
res: Option<Res>,
span: Span,
) {
if let Some(Res::NonMacroAttr(kind)) = res {
if kind != NonMacroAttrKind::Tool && binding.is_none_or(|b| b.is_import()) {
let binding_span = binding.map(|binding| binding.span);
if kind != NonMacroAttrKind::Tool && decl.is_none_or(|b| b.is_import()) {
self.dcx().emit_err(errors::CannotUseThroughAnImport {
span,
article: kind.article(),
descr: kind.descr(),
binding_span,
binding_span: decl.map(|d| d.span),
});
}
}
@ -1084,12 +1082,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
path: &ast::Path,
parent_scope: &ParentScope<'ra>,
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
binding: Option<NameBinding<'ra>>,
decl: Option<Decl<'ra>>,
) {
if let Some((mod_def_id, node_id)) = invoc_in_mod_inert_attr
&& let Some(binding) = binding
&& let Some(decl) = decl
// This is a `macro_rules` itself, not some import.
&& let NameBindingKind::Res(res) = binding.kind
&& let DeclKind::Def(res) = decl.kind
&& let Res::Def(DefKind::Macro(kinds), def_id) = res
&& kinds.contains(MacroKinds::BANG)
// And the `macro_rules` is defined inside the attribute's module,

View file

@ -1,17 +0,0 @@
//@ known-bug: #132985
//@ aux-build:aux132985.rs
#![allow(incomplete_features)]
#![feature(min_generic_const_args)]
#![feature(adt_const_params)]
extern crate aux132985;
use aux132985::Foo;
fn bar<const N: Foo>() {}
fn baz() {
bar::<{ Foo }>();
}
fn main() {}

View file

@ -1,7 +0,0 @@
//@ known-bug: #136138
#![feature(min_generic_const_args)]
struct U;
struct S<const N: U>()
where
S<{ U }>:;
fn main() {}

View file

@ -1,10 +0,0 @@
//@ known-bug: #139596
#![feature(min_generic_const_args)]
struct Colour;
struct Led<const C: Colour>;
fn main() {
Led::<{ Colour}>;
}

View file

@ -1,16 +0,0 @@
//@ known-bug: #132980
// Originally a rustdoc test. Should be moved back there with @has checks
// readded once fixed.
// Previous issue (before mgca): https://github.com/rust-lang/rust/issues/105952
#![crate_name = "foo"]
#![feature(min_generic_const_args)]
pub enum ParseMode {
Raw,
}
pub trait Parse {
#[type_const]
const PARSE_MODE: ParseMode;
}
pub trait RenderRaw {}
impl<T: Parse<PARSE_MODE = { ParseMode::Raw }>> RenderRaw for T {}

View file

@ -0,0 +1,20 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/105952>
#![crate_name = "foo"]
#![feature(min_generic_const_args, adt_const_params)]
#![expect(incomplete_features)]
use std::marker::ConstParamTy;
#[derive(PartialEq, Eq, ConstParamTy)]
pub enum ParseMode {
Raw,
}
pub trait Parse {
#[type_const]
const PARSE_MODE: ParseMode;
}
pub trait RenderRaw {}
//@ hasraw foo/trait.RenderRaw.html 'impl'
//@ hasraw foo/trait.RenderRaw.html 'ParseMode::Raw'
impl<T: Parse<PARSE_MODE = { ParseMode::Raw }>> RenderRaw for T {}

View file

@ -1,5 +1,4 @@
//@ known-bug: #110395
//@ compile-flags: -Znext-solver
//@ check-pass
#![allow(incomplete_features)]
#![feature(const_trait_impl, generic_const_exprs)]

View file

@ -1,95 +0,0 @@
error: `-Znext-solver=globally` and `generic_const_exprs` are incompatible, using them at the same time is not allowed
--> $DIR/issue-88119.rs:4:30
|
LL | #![feature(const_trait_impl, generic_const_exprs)]
| ^^^^^^^^^^^^^^^^^^^
|
= help: remove one of these features
error[E0275]: overflow evaluating the requirement `&T: [const] ConstName`
--> $DIR/issue-88119.rs:18:49
|
LL | impl<T: ?Sized + ConstName> const ConstName for &T
| ^^
error[E0275]: overflow evaluating the requirement `&T: ConstName`
--> $DIR/issue-88119.rs:18:49
|
LL | impl<T: ?Sized + ConstName> const ConstName for &T
| ^^
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
--> $DIR/issue-88119.rs:20:5
|
LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^^^^^^^
|
note: required by a bound in `<&T as ConstName>`
--> $DIR/issue-88119.rs:20:5
|
LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
--> $DIR/issue-88119.rs:20:10
|
LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^
|
note: required by a bound in `<&T as ConstName>`
--> $DIR/issue-88119.rs:20:5
|
LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&T as ConstName>`
error[E0275]: overflow evaluating the requirement `&mut T: [const] ConstName`
--> $DIR/issue-88119.rs:25:49
|
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
| ^^^^^^
error[E0275]: overflow evaluating the requirement `&mut T: ConstName`
--> $DIR/issue-88119.rs:25:49
|
LL | impl<T: ?Sized + ConstName> const ConstName for &mut T
| ^^^^^^
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
--> $DIR/issue-88119.rs:27:5
|
LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^^^^^^^
|
note: required by a bound in `<&mut T as ConstName>`
--> $DIR/issue-88119.rs:27:5
|
LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
error[E0275]: overflow evaluating the requirement `[(); name_len::<T>()] well-formed`
--> $DIR/issue-88119.rs:27:10
|
LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^
|
note: required by a bound in `<&mut T as ConstName>`
--> $DIR/issue-88119.rs:27:5
|
LL | [(); name_len::<T>()]:,
| ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `<&mut T as ConstName>`
error[E0275]: overflow evaluating the requirement `&&mut u8: ConstName`
--> $DIR/issue-88119.rs:32:35
|
LL | pub const ICE_1: &'static [u8] = <&&mut u8 as ConstName>::NAME_BYTES;
| ^^^^^^^^
error[E0275]: overflow evaluating the requirement `&mut &u8: ConstName`
--> $DIR/issue-88119.rs:33:35
|
LL | pub const ICE_2: &'static [u8] = <&mut &u8 as ConstName>::NAME_BYTES;
| ^^^^^^^^
error: aborting due to 11 previous errors
For more information about this error, try `rustc --explain E0275`.

View file

@ -0,0 +1,19 @@
#![feature(min_generic_const_args, adt_const_params)]
#![expect(incomplete_features)]
use std::marker::ConstParamTy;
#[derive(ConstParamTy, PartialEq, Eq)]
struct U;
#[derive(ConstParamTy, PartialEq, Eq)]
//~^ ERROR overflow evaluating the requirement `S<U> well-formed`
//~| ERROR overflow evaluating the requirement `S<U> well-formed`
struct S<const N: U>()
where
S<{ U }>:;
//~^ ERROR overflow evaluating the requirement `S<U> well-formed`
//~| ERROR overflow evaluating the requirement `S<U> well-formed`
//~| ERROR overflow evaluating the requirement `S<U> well-formed`
fn main() {}

View file

@ -0,0 +1,80 @@
error[E0275]: overflow evaluating the requirement `S<U> well-formed`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | S<{ U }>:;
| ^^^^^^^^
|
note: required by a bound in `S`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | struct S<const N: U>()
| - required by a bound in this struct
LL | where
LL | S<{ U }>:;
| ^^^^^^^^ required by this bound in `S`
error[E0275]: overflow evaluating the requirement `S<U> well-formed`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | S<{ U }>:;
| ^^^^^^^^
|
note: required by a bound in `S`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | struct S<const N: U>()
| - required by a bound in this struct
LL | where
LL | S<{ U }>:;
| ^^^^^^^^ required by this bound in `S`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0275]: overflow evaluating the requirement `S<U> well-formed`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | S<{ U }>:;
| ^^^^^^^^
|
note: required by a bound in `S`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | struct S<const N: U>()
| - required by a bound in this struct
LL | where
LL | S<{ U }>:;
| ^^^^^^^^ required by this bound in `S`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0275]: overflow evaluating the requirement `S<U> well-formed`
--> $DIR/const-ctor-overflow-eval.rs:8:24
|
LL | #[derive(ConstParamTy, PartialEq, Eq)]
| ^^^^^^^^^
|
note: required by a bound in `S`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | struct S<const N: U>()
| - required by a bound in this struct
LL | where
LL | S<{ U }>:;
| ^^^^^^^^ required by this bound in `S`
error[E0275]: overflow evaluating the requirement `S<U> well-formed`
--> $DIR/const-ctor-overflow-eval.rs:8:35
|
LL | #[derive(ConstParamTy, PartialEq, Eq)]
| ^^
|
note: required by a bound in `S`
--> $DIR/const-ctor-overflow-eval.rs:14:5
|
LL | struct S<const N: U>()
| - required by a bound in this struct
LL | where
LL | S<{ U }>:;
| ^^^^^^^^ required by this bound in `S`
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0275`.

View file

@ -0,0 +1,19 @@
// to ensure it does not ices like before
#![feature(min_generic_const_args, adt_const_params)]
#![expect(incomplete_features)]
use std::marker::ConstParamTy;
#[derive(ConstParamTy, PartialEq, Eq)]
enum Option<T> {
#[allow(dead_code)]
Some(T),
None,
}
fn pass_enum<const P: Option<u32>>() {}
fn main() {
pass_enum::<{ None }>();
//~^ ERROR missing generics for enum `std::option::Option`
}

View file

@ -0,0 +1,14 @@
error[E0107]: missing generics for enum `std::option::Option`
--> $DIR/const-ctor-with-error.rs:17:19
|
LL | pass_enum::<{ None }>();
| ^^^^ expected 1 generic argument
|
help: add missing generic argument
|
LL | pass_enum::<{ None<T> }>();
| +++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0107`.

View file

@ -0,0 +1,49 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/139596>
//! <https://github.com/rust-lang/rust/issues/136138>
//! <https://github.com/rust-lang/rust/issues/132985>
//@ check-pass
#![feature(
min_generic_const_args,
adt_const_params,
generic_const_parameter_types,
unsized_const_params
)]
#![expect(incomplete_features)]
use std::marker::{ConstParamTy, ConstParamTy_};
#[derive(ConstParamTy, PartialEq, Eq)]
struct Colour;
#[derive(ConstParamTy, PartialEq, Eq)]
enum A {
B,
}
#[derive(ConstParamTy, PartialEq, Eq)]
enum MyOption<T> {
#[allow(dead_code)]
Some(T),
None,
}
#[derive(ConstParamTy, PartialEq, Eq)]
struct Led<const C: Colour>;
#[derive(Eq, PartialEq, ConstParamTy)]
struct Foo<const N: usize>;
fn pass_enum<const P: MyOption<u32>>() {}
fn accepts_foo<const N: usize, const M: Foo<N>>() {}
fn accepts_bar<T: ConstParamTy_, const B: MyOption<T>>() {}
fn test<T: ConstParamTy_, const N: usize>() {
accepts_foo::<N, { Foo::<N> }>();
accepts_bar::<T, { MyOption::None::<T> }>();
}
fn main() {
Led::<{ Colour }>;
}

View file

@ -1,11 +0,0 @@
error: const `impl` for trait `Debug` which is not `const`
--> $DIR/rustc-impl-const-stability.rs:15:12
|
LL | impl const std::fmt::Debug for Data {
| ^^^^^^^^^^^^^^^ this trait is not `const`
|
= note: marking a trait with `const` ensures all default method bodies are `const`
= note: adding a non-const method body in the future would be a breaking change
error: aborting due to 1 previous error

View file

@ -0,0 +1,35 @@
//@ check-pass
#![feature(macro_metavar_expr_concat)]
struct A;
struct B;
const AA: A = A;
const BB: B = B;
macro_rules! define_ioctl_data {
(struct $s:ident {
$($field:ident: $ty:ident $([$opt:ident])?,)*
}) => {
pub struct $s {
$($field: $ty,)*
}
impl $s {
$($(
fn ${concat(get_, $field)}(&self) -> $ty {
let _ = $opt;
todo!()
}
)?)*
}
};
}
define_ioctl_data! {
struct Foo {
a: A [AA],
b: B [BB],
}
}
fn main() {}

View file

@ -11,7 +11,7 @@ macro_rules! InRepetition {
) => {
$(
$(
${concat(_, $arg)} //~ ERROR nested repetitions with `${concat(...)}` metavariable expressions are not yet supported
${concat(_, $arg)} //~ ERROR macro expansion ends with an incomplete expression: expected one of `!` or `::`
)*
)*
};

View file

@ -1,8 +1,8 @@
error: nested repetitions with `${concat(...)}` metavariable expressions are not yet supported
--> $DIR/in-repetition.rs:14:30
error: macro expansion ends with an incomplete expression: expected one of `!` or `::`
--> $DIR/in-repetition.rs:14:35
|
LL | ${concat(_, $arg)}
| ^^^
| ^ expected one of `!` or `::`
error: aborting due to 1 previous error

View file

@ -11,8 +11,7 @@ macro_rules! one_rep {
macro_rules! issue_128346 {
( $($a:ident)* ) => {
A(
const ${concat($a, Z)}: i32 = 3;
//~^ ERROR invalid syntax
const ${concat($a, Z)}: i32 = 3; //~ ERROR `${concat(...)}` variable is still repeating at this depth
)*
};
}
@ -20,8 +19,8 @@ macro_rules! issue_128346 {
macro_rules! issue_131393 {
($t:ident $($en:ident)?) => {
read::<${concat($t, $en)}>()
//~^ ERROR invalid syntax
//~| ERROR invalid syntax
//~^ ERROR `${concat(...)}` variable is still repeating at this depth
//~| ERROR `${concat(...)}` variable is still repeating at this depth
}
}

View file

@ -1,20 +1,20 @@
error: invalid syntax
--> $DIR/concat-repetitions.rs:14:20
error: `${concat(...)}` variable is still repeating at this depth
--> $DIR/concat-repetitions.rs:14:29
|
LL | const ${concat($a, Z)}: i32 = 3;
| ^^^^^^^^^^^^^^^
| ^
error: invalid syntax
--> $DIR/concat-repetitions.rs:22:17
error: `${concat(...)}` variable is still repeating at this depth
--> $DIR/concat-repetitions.rs:21:30
|
LL | read::<${concat($t, $en)}>()
| ^^^^^^^^^^^^^^^^^
| ^^
error: invalid syntax
--> $DIR/concat-repetitions.rs:22:17
error: `${concat(...)}` variable is still repeating at this depth
--> $DIR/concat-repetitions.rs:21:30
|
LL | read::<${concat($t, $en)}>()
| ^^^^^^^^^^^^^^^^^
| ^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`

View file

@ -1,59 +0,0 @@
error: `[const]` can only be applied to `const` traits
--> $DIR/const_trait_impl.rs:33:9
|
LL | impl<T: [const] Debug> const A for T {
| ^^^^^^^ can't be applied to `Debug`
|
note: `Debug` can't be used with `[const]` because it isn't `const`
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
error: `[const]` can only be applied to `const` traits
--> $DIR/const_trait_impl.rs:39:9
|
LL | impl<T: [const] Debug + [const] Sup> const A for T {
| ^^^^^^^ can't be applied to `Debug`
|
note: `Debug` can't be used with `[const]` because it isn't `const`
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
error: `[const]` can only be applied to `const` traits
--> $DIR/const_trait_impl.rs:45:9
|
LL | impl<T: [const] Debug + [const] Sub> const A for T {
| ^^^^^^^ can't be applied to `Debug`
|
note: `Debug` can't be used with `[const]` because it isn't `const`
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
error: `[const]` can only be applied to `const` traits
--> $DIR/const_trait_impl.rs:39:9
|
LL | impl<T: [const] Debug + [const] Sup> const A for T {
| ^^^^^^^ can't be applied to `Debug`
|
note: `Debug` can't be used with `[const]` because it isn't `const`
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `[const]` can only be applied to `const` traits
--> $DIR/const_trait_impl.rs:33:9
|
LL | impl<T: [const] Debug> const A for T {
| ^^^^^^^ can't be applied to `Debug`
|
note: `Debug` can't be used with `[const]` because it isn't `const`
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: `[const]` can only be applied to `const` traits
--> $DIR/const_trait_impl.rs:45:9
|
LL | impl<T: [const] Debug + [const] Sub> const A for T {
| ^^^^^^^ can't be applied to `Debug`
|
note: `Debug` can't be used with `[const]` because it isn't `const`
--> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 6 previous errors

View file

@ -1,15 +1,15 @@
//@ known-bug: #110395
#![feature(derive_const)]
#![feature(const_default, derive_const)]
pub struct A;
impl std::fmt::Debug for A {
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
panic!()
impl Default for A {
fn default() -> A {
A
}
}
#[derive_const(Debug)]
#[derive_const(Default)]
pub struct S(A);
//~^ ERROR: cannot call non-const associated function
fn main() {}

View file

@ -1,20 +1,13 @@
error: const `impl` for trait `Debug` which is not `const`
--> $DIR/derive-const-non-const-type.rs:12:16
error[E0015]: cannot call non-const associated function `<A as Default>::default` in constant functions
--> $DIR/derive-const-non-const-type.rs:12:14
|
LL | #[derive_const(Debug)]
| ^^^^^ this trait is not `const`
|
= note: marking a trait with `const` ensures all default method bodies are `const`
= note: adding a non-const method body in the future would be a breaking change
error[E0015]: cannot call non-const method `Formatter::<'_>::debug_tuple_field1_finish` in constant functions
--> $DIR/derive-const-non-const-type.rs:12:16
|
LL | #[derive_const(Debug)]
| ^^^^^
LL | #[derive_const(Default)]
| ------- in this derive macro expansion
LL | pub struct S(A);
| ^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0015`.

View file

@ -1,5 +1,4 @@
//@ compile-flags: -Znext-solver
//@ known-bug: #110395
//@ check-pass
#![crate_type = "lib"]
#![feature(staged_api, const_trait_impl, const_default)]
@ -12,8 +11,8 @@ pub struct Data {
#[stable(feature = "potato", since = "1.27.0")]
#[rustc_const_unstable(feature = "data_foo", issue = "none")]
impl const std::fmt::Debug for Data {
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
Ok(())
impl const Default for Data {
fn default() -> Data {
Data { _data: 0xbeef }
}
}

View file

@ -1,7 +1,5 @@
// Tests that trait bounds on specializing trait impls must be `[const]` if the
// same bound is present on the default impl and is `[const]` there.
//@ known-bug: #110395
// FIXME(const_trait_impl) ^ should error
#![feature(const_trait_impl)]
#![feature(rustc_attrs)]
@ -23,9 +21,9 @@ where
default fn bar() {}
}
impl<T> Bar for T
impl<T> Bar for T //~ ERROR conflicting implementations of trait `Bar`
where
T: Foo, //FIXME ~ ERROR missing `[const]` qualifier
T: Foo,
T: Specialize,
{
fn bar() {}
@ -42,7 +40,7 @@ where
default fn baz() {}
}
impl<T> const Baz for T //FIXME ~ ERROR conflicting implementations of trait `Baz`
impl<T> const Baz for T //~ ERROR conflicting implementations of trait `Baz`
where
T: Foo,
T: Specialize,

View file

@ -1,5 +1,5 @@
error[E0119]: conflicting implementations of trait `Bar`
--> $DIR/const-default-bound-non-const-specialized-bound.rs:26:1
--> $DIR/const-default-bound-non-const-specialized-bound.rs:24:1
|
LL | / impl<T> const Bar for T
LL | | where
@ -8,19 +8,19 @@ LL | | T: [const] Foo,
...
LL | / impl<T> Bar for T
LL | | where
LL | | T: Foo, //FIXME ~ ERROR missing `[const]` qualifier
LL | | T: Foo,
LL | | T: Specialize,
| |__________________^ conflicting implementation
error[E0119]: conflicting implementations of trait `Baz`
--> $DIR/const-default-bound-non-const-specialized-bound.rs:45:1
--> $DIR/const-default-bound-non-const-specialized-bound.rs:43:1
|
LL | / impl<T> const Baz for T
LL | | where
LL | | T: [const] Foo,
| |___________________- first implementation here
...
LL | / impl<T> const Baz for T //FIXME ~ ERROR conflicting implementations of trait `Baz`
LL | / impl<T> const Baz for T
LL | | where
LL | | T: Foo,
LL | | T: Specialize,

View file

@ -1,8 +1,6 @@
//@ known-bug: #110395
#![feature(const_trait_impl, min_specialization, rustc_attrs)]
use std::fmt::Debug;
//@ check-pass
#![feature(const_trait_impl, const_default, min_specialization, rustc_attrs)]
#![allow(internal_features)]
#[rustc_specialization_trait]
pub const unsafe trait Sup {
@ -30,19 +28,19 @@ pub const trait A {
fn a() -> u32;
}
impl<T: [const] Debug> const A for T {
impl<T: [const] Default> const A for T {
default fn a() -> u32 {
2
}
}
impl<T: [const] Debug + [const] Sup> const A for T {
impl<T: [const] Default + [const] Sup> const A for T {
default fn a() -> u32 {
3
}
}
impl<T: [const] Debug + [const] Sub> const A for T {
impl<T: [const] Default + [const] Sub> const A for T {
fn a() -> u32 {
T::foo()
}

View file

@ -1,5 +1,6 @@
#![feature(const_trait_impl, min_specialization, rustc_attrs)]
//@ known-bug: #110395
#![allow(internal_features)]
#[rustc_specialization_trait]
pub const trait Sup {}
@ -23,7 +24,7 @@ impl<T: Default + [const] Sup> const A for T {
const fn generic<T: Default>() {
<T as A>::a();
//FIXME ~^ ERROR: the trait bound `T: [const] Sup` is not satisfied
//~^ ERROR: the trait bound `T: [const] A` is not satisfied
}
fn main() {}

View file

@ -1,5 +1,5 @@
error[E0277]: the trait bound `T: [const] A` is not satisfied
--> $DIR/specializing-constness-2.rs:25:6
--> $DIR/specializing-constness-2.rs:26:6
|
LL | <T as A>::a();
| ^