diff options
Diffstat (limited to 'compiler/rustc_resolve')
| -rw-r--r-- | compiler/rustc_resolve/src/build_reduced_graph.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 168 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/ident.rs | 139 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/imports.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 389 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 93 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/lifetimes.rs | 109 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 103 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/macros.rs | 9 |
9 files changed, 597 insertions, 458 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index d97d9199b77..43c1062f32e 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -265,6 +265,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }) } ast::VisibilityKind::Restricted { ref path, id, .. } => { + // Make `PRIVATE_IN_PUBLIC` lint a hard error. + self.r.has_pub_restricted = true; // For visibilities we are not ready to provide correct implementation of "uniform // paths" right now, so on 2018 edition we only allow module-relative paths for now. // On 2015 edition visibilities are resolved as crate-relative by default, @@ -296,7 +298,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { &segments, Some(TypeNS), parent_scope, - if finalize { Finalize::SimplePath(id, path.span) } else { Finalize::No }, + finalize.then(|| Finalize::new(id, path.span)), None, ) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => { @@ -458,6 +460,14 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let mut source = module_path.pop().unwrap(); let mut type_ns_only = false; + self.r.visibilities.insert(self.r.local_def_id(id), vis); + if id1 != ast::DUMMY_NODE_ID { + self.r.visibilities.insert(self.r.local_def_id(id1), vis); + } + if id2 != ast::DUMMY_NODE_ID { + self.r.visibilities.insert(self.r.local_def_id(id2), vis); + } + if nested { // Correctly handle `self` if source.ident.name == kw::SelfLower { @@ -580,6 +590,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { is_prelude: self.r.session.contains_name(&item.attrs, sym::prelude_import), max_vis: Cell::new(ty::Visibility::Invisible), }; + self.r.visibilities.insert(self.r.local_def_id(id), vis); self.add_import(prefix, kind, use_tree.span, id, item, root_span, item.id, vis); } ast::UseTreeKind::Nested(ref items) => { @@ -840,7 +851,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { .span_suggestion( item.span, "rename the `self` crate to be able to import it", - "extern crate self as name;".into(), + "extern crate self as name;", Applicability::HasPlaceholders, ) .emit(); @@ -1256,13 +1267,15 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.insert_unused_macro(ident, def_id, item.id); } self.r.visibilities.insert(def_id, vis); - self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding( + let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding( self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding { parent_macro_rules_scope: parent_scope.macro_rules, binding, ident, }), - )) + )); + self.r.macro_rules_scopes.insert(def_id, scope); + scope } else { let module = parent_scope.module; let vis = match item.kind { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 899980a4c08..7d40ecb18b7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -123,7 +123,7 @@ impl<'a> Resolver<'a> { let (span, found_use) = if let Some(def_id) = def_id.as_local() { UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id]) } else { - (None, false) + (None, FoundUse::No) }; if !candidates.is_empty() { show_candidates( @@ -132,8 +132,9 @@ impl<'a> Resolver<'a> { &mut err, span, &candidates, - instead, + if instead { Instead::Yes } else { Instead::No }, found_use, + IsPattern::No, ); } else if let Some((span, msg, sugg, appl)) = suggestion { err.span_suggestion(span, msg, sugg, appl); @@ -416,15 +417,12 @@ impl<'a> Resolver<'a> { crate fn lint_if_path_starts_with_module( &mut self, - finalize: Finalize, + finalize: Option<Finalize>, path: &[Segment], second_binding: Option<&NameBinding<'_>>, ) { - let (diag_id, diag_span) = match finalize { - Finalize::No => return, - Finalize::SimplePath(id, path_span) => (id, path_span), - Finalize::UsePath { root_id, root_span, .. } => (root_id, root_span), - Finalize::QPathTrait { qpath_id, qpath_span, .. } => (qpath_id, qpath_span), + let Some(Finalize { node_id, root_span, .. }) = finalize else { + return; }; let first_name = match path.get(0) { @@ -462,11 +460,11 @@ impl<'a> Resolver<'a> { } } - let diag = BuiltinLintDiagnostics::AbsPathWithModule(diag_span); + let diag = BuiltinLintDiagnostics::AbsPathWithModule(root_span); self.lint_buffer.buffer_lint_with_diagnostic( ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, - diag_id, - diag_span, + node_id, + root_span, "absolute paths must start with `self`, `super`, \ `crate`, or an external crate name in the 2018 edition", diag, @@ -493,14 +491,14 @@ impl<'a> Resolver<'a> { /// /// This takes the error provided, combines it with the span and any additional spans inside the /// error and emits it. - crate fn report_error(&self, span: Span, resolution_error: ResolutionError<'_>) { + crate fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'a>) { self.into_struct_error(span, resolution_error).emit(); } crate fn into_struct_error( - &self, + &mut self, span: Span, - resolution_error: ResolutionError<'_>, + resolution_error: ResolutionError<'a>, ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { match resolution_error { ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => { @@ -650,7 +648,7 @@ impl<'a> Resolver<'a> { } err } - ResolutionError::VariableNotBoundInPattern(binding_error) => { + ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => { let BindingError { name, target, origin, could_be_path } = binding_error; let target_sp = target.iter().copied().collect::<Vec<_>>(); @@ -670,13 +668,41 @@ impl<'a> Resolver<'a> { for sp in origin_sp { err.span_label(sp, "variable not in all patterns"); } - if *could_be_path { - let help_msg = format!( - "if you meant to match on a variant or a `const` item, consider \ - making the path in the pattern qualified: `?::{}`", - name, + if could_be_path { + let import_suggestions = self.lookup_import_candidates( + Ident::with_dummy_span(name), + Namespace::ValueNS, + &parent_scope, + &|res: Res| match res { + Res::Def( + DefKind::Ctor(CtorOf::Variant, CtorKind::Const) + | DefKind::Ctor(CtorOf::Struct, CtorKind::Const) + | DefKind::Const + | DefKind::AssocConst, + _, + ) => true, + _ => false, + }, + ); + + if import_suggestions.is_empty() { + let help_msg = format!( + "if you meant to match on a variant or a `const` item, consider \ + making the path in the pattern qualified: `path::to::ModOrType::{}`", + name, + ); + err.span_help(span, &help_msg); + } + show_candidates( + &self.definitions, + self.session, + &mut err, + Some(span), + &import_suggestions, + Instead::No, + FoundUse::Yes, + IsPattern::Yes, ); - err.span_help(span, &help_msg); } err } @@ -1014,7 +1040,7 @@ impl<'a> Resolver<'a> { } ResolutionError::InvalidAsmSym => { let mut err = self.session.struct_span_err(span, "invalid `sym` operand"); - err.span_label(span, &format!("is a local variable")); + err.span_label(span, "is a local variable"); err.help("`sym` operands must refer to either a function or a static"); err } @@ -1022,7 +1048,7 @@ impl<'a> Resolver<'a> { } crate fn report_vis_error( - &self, + &mut self, vis_resolution_error: VisResolutionError<'_>, ) -> ErrorGuaranteed { match vis_resolution_error { @@ -1453,8 +1479,9 @@ impl<'a> Resolver<'a> { err, None, &import_suggestions, - false, - true, + Instead::No, + FoundUse::Yes, + IsPattern::No, ); if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) { @@ -1473,7 +1500,6 @@ impl<'a> Resolver<'a> { &parent_scope, None, false, - false, None, ) { let desc = match binding.res() { @@ -1781,7 +1807,7 @@ impl<'a> Resolver<'a> { opt_ns: Option<Namespace>, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, ribs: Option<&PerNS<Vec<Rib<'a>>>>, - unusable_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option<&'a NameBinding<'a>>, module: Option<ModuleOrUniformRoot<'a>>, i: usize, ident: Ident, @@ -1833,8 +1859,7 @@ impl<'a> Resolver<'a> { ns_to_try, parent_scope, None, - false, - unusable_binding, + ignore_binding, ).ok() } else if let Some(ribs) = ribs && let Some(TypeNS | ValueNS) = opt_ns @@ -1843,9 +1868,9 @@ impl<'a> Resolver<'a> { ident, ns_to_try, parent_scope, - Finalize::No, + None, &ribs[ns_to_try], - unusable_binding, + ignore_binding, ) { // we found a locally-imported or available item/module Some(LexicalScopeBinding::Item(binding)) => Some(binding), @@ -1859,8 +1884,7 @@ impl<'a> Resolver<'a> { parent_scope, None, false, - false, - unusable_binding, + ignore_binding, ).ok() }; if let Some(binding) = binding { @@ -1891,9 +1915,9 @@ impl<'a> Resolver<'a> { ident, ValueNS, parent_scope, - Finalize::No, + None, &ribs[ValueNS], - unusable_binding, + ignore_binding, ) } else { None @@ -2390,6 +2414,27 @@ fn find_span_immediately_after_crate_name( (next_left_bracket == after_second_colon, from_second_colon) } +/// A suggestion has already been emitted, change the wording slightly to clarify that both are +/// independent options. +enum Instead { + Yes, + No, +} + +/// Whether an existing place with an `use` item was found. +enum FoundUse { + Yes, + No, +} + +/// Whether a binding is part of a pattern or an expression. Used for diagnostics. +enum IsPattern { + /// The binding is part of a pattern + Yes, + /// The binding is part of an expression + No, +} + /// When an entity with a given name is not available in scope, we search for /// entities with that name in all crates. This method allows outputting the /// results of this search in a programmer-friendly way @@ -2400,8 +2445,9 @@ fn show_candidates( // This is `None` if all placement locations are inside expansions use_placement_span: Option<Span>, candidates: &[ImportSuggestion], - instead: bool, - found_use: bool, + instead: Instead, + found_use: FoundUse, + is_pattern: IsPattern, ) { if candidates.is_empty() { return; @@ -2428,24 +2474,38 @@ fn show_candidates( } if !accessible_path_strings.is_empty() { - let (determiner, kind) = if accessible_path_strings.len() == 1 { - ("this", accessible_path_strings[0].1) + let (determiner, kind, name) = if accessible_path_strings.len() == 1 { + ("this", accessible_path_strings[0].1, format!(" `{}`", accessible_path_strings[0].0)) } else { - ("one of these", "items") + ("one of these", "items", String::new()) }; - let instead = if instead { " instead" } else { "" }; - let mut msg = format!("consider importing {} {}{}", determiner, kind, instead); + let instead = if let Instead::Yes = instead { " instead" } else { "" }; + let mut msg = if let IsPattern::Yes = is_pattern { + format!( + "if you meant to match on {}{}{}, use the full path in the pattern", + kind, instead, name + ) + } else { + format!("consider importing {} {}{}", determiner, kind, instead) + }; for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) { err.note(note); } - if let Some(span) = use_placement_span { + if let (IsPattern::Yes, Some(span)) = (is_pattern, use_placement_span) { + err.span_suggestions( + span, + &msg, + accessible_path_strings.into_iter().map(|a| a.0), + Applicability::MaybeIncorrect, + ); + } else if let Some(span) = use_placement_span { for candidate in &mut accessible_path_strings { // produce an additional newline to separate the new use statement // from the directly following item. - let additional_newline = if found_use { "" } else { "\n" }; + let additional_newline = if let FoundUse::Yes = found_use { "" } else { "\n" }; candidate.0 = format!("use {};\n{}", &candidate.0, additional_newline); } @@ -2453,7 +2513,7 @@ fn show_candidates( span, &msg, accessible_path_strings.into_iter().map(|a| a.0), - Applicability::Unspecified, + Applicability::MaybeIncorrect, ); } else { msg.push(':'); @@ -2468,9 +2528,17 @@ fn show_candidates( } else { assert!(!inaccessible_path_strings.is_empty()); + let prefix = + if let IsPattern::Yes = is_pattern { "you might have meant to match on " } else { "" }; if inaccessible_path_strings.len() == 1 { let (name, descr, def_id, note) = &inaccessible_path_strings[0]; - let msg = format!("{} `{}` exists but is inaccessible", descr, name); + let msg = format!( + "{}{} `{}`{} exists but is inaccessible", + prefix, + descr, + name, + if let IsPattern::Yes = is_pattern { ", which" } else { "" } + ); if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) { let span = definitions.def_span(local_def_id); @@ -2496,7 +2564,7 @@ fn show_candidates( "item".to_string() }; - let mut msg = format!("these {}s exist but are inaccessible", descr); + let mut msg = format!("{}these {}s exist but are inaccessible", prefix, descr); let mut has_colon = false; let mut spans = Vec::new(); @@ -2537,14 +2605,14 @@ struct UsePlacementFinder { } impl UsePlacementFinder { - fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, bool) { + fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, FoundUse) { let mut finder = UsePlacementFinder { target_module, first_legal_span: None, first_use_span: None }; finder.visit_crate(krate); if let Some(use_span) = finder.first_use_span { - (Some(use_span), true) + (Some(use_span), FoundUse::Yes) } else { - (finder.first_legal_span, false) + (finder.first_legal_span, FoundUse::No) } } } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 84fe0ec83d2..18ce359524d 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -279,9 +279,9 @@ impl<'a> Resolver<'a> { mut ident: Ident, ns: Namespace, parent_scope: &ParentScope<'a>, - finalize_full: Finalize, + finalize: Option<Finalize>, ribs: &[Rib<'a>], - unusable_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option<&'a NameBinding<'a>>, ) -> Option<LexicalScopeBinding<'a>> { assert!(ns == TypeNS || ns == ValueNS); let orig_ident = ident; @@ -302,7 +302,6 @@ impl<'a> Resolver<'a> { let normalized_ident = Ident { span: normalized_span, ..ident }; // Walk backwards up the ribs in scope. - let finalize = finalize_full.path_span(); let mut module = self.graph_root; for i in (0..ribs.len()).rev() { debug!("walk rib\n{:?}", ribs[i].bindings); @@ -316,7 +315,7 @@ impl<'a> Resolver<'a> { i, rib_ident, *res, - finalize, + finalize.map(|finalize| finalize.path_span), *original_rib_ident_def, ribs, ))); @@ -344,8 +343,7 @@ impl<'a> Resolver<'a> { ns, parent_scope, finalize, - false, - unusable_binding, + ignore_binding, ); if let Ok(binding) = item { // The ident resolves to an item. @@ -354,12 +352,11 @@ impl<'a> Resolver<'a> { } self.early_resolve_ident_in_lexical_scope( orig_ident, - ScopeSet::Late(ns, module, finalize_full.node_id()), + ScopeSet::Late(ns, module, finalize.map(|finalize| finalize.node_id)), parent_scope, finalize, finalize.is_some(), - false, - unusable_binding, + ignore_binding, ) .ok() .map(LexicalScopeBinding::Item) @@ -376,10 +373,9 @@ impl<'a> Resolver<'a> { orig_ident: Ident, scope_set: ScopeSet<'a>, parent_scope: &ParentScope<'a>, - finalize: Option<Span>, + finalize: Option<Finalize>, force: bool, - last_import_segment: bool, - unusable_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option<&'a NameBinding<'a>>, ) -> Result<&'a NameBinding<'a>, Determinacy> { bitflags::bitflags! { struct Flags: u8 { @@ -499,8 +495,7 @@ impl<'a> Resolver<'a> { ns, parent_scope, finalize, - last_import_segment, - unusable_binding, + ignore_binding, ); match binding { Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)), @@ -522,8 +517,7 @@ impl<'a> Resolver<'a> { adjusted_parent_scope, !matches!(scope_set, ScopeSet::Late(..)), finalize, - last_import_segment, - unusable_binding, + ignore_binding, ); match binding { Ok(binding) => { @@ -608,8 +602,7 @@ impl<'a> Resolver<'a> { ns, parent_scope, None, - last_import_segment, - unusable_binding, + ignore_binding, ) { if use_prelude || this.is_builtin_macro(binding.res()) { result = Ok((binding, Flags::MISC_FROM_PRELUDE)); @@ -731,7 +724,7 @@ impl<'a> Resolver<'a> { ns: Namespace, parent_scope: &ParentScope<'a>, ) -> Result<&'a NameBinding<'a>, Determinacy> { - self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, false, None) + self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None) .map_err(|(determinacy, _)| determinacy) } @@ -742,23 +735,11 @@ impl<'a> Resolver<'a> { ident: Ident, ns: Namespace, parent_scope: &ParentScope<'a>, - finalize: Option<Span>, - // We are resolving a last import segment during import validation. - last_import_segment: bool, - // This binding should be ignored during in-module resolution, so that we don't get - // "self-confirming" import resolutions during import validation. - unusable_binding: Option<&'a NameBinding<'a>>, + finalize: Option<Finalize>, + ignore_binding: Option<&'a NameBinding<'a>>, ) -> Result<&'a NameBinding<'a>, Determinacy> { - self.resolve_ident_in_module_ext( - module, - ident, - ns, - parent_scope, - finalize, - last_import_segment, - unusable_binding, - ) - .map_err(|(determinacy, _)| determinacy) + self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding) + .map_err(|(determinacy, _)| determinacy) } #[tracing::instrument(level = "debug", skip(self))] @@ -768,9 +749,8 @@ impl<'a> Resolver<'a> { mut ident: Ident, ns: Namespace, parent_scope: &ParentScope<'a>, - finalize: Option<Span>, - last_import_segment: bool, - unusable_binding: Option<&'a NameBinding<'a>>, + finalize: Option<Finalize>, + ignore_binding: Option<&'a NameBinding<'a>>, ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { let tmp_parent_scope; let mut adjusted_parent_scope = parent_scope; @@ -796,8 +776,7 @@ impl<'a> Resolver<'a> { adjusted_parent_scope, false, finalize, - last_import_segment, - unusable_binding, + ignore_binding, ) } @@ -808,9 +787,8 @@ impl<'a> Resolver<'a> { ident: Ident, ns: Namespace, parent_scope: &ParentScope<'a>, - finalize: Option<Span>, - last_import_segment: bool, - unusable_binding: Option<&'a NameBinding<'a>>, + finalize: Option<Finalize>, + ignore_binding: Option<&'a NameBinding<'a>>, ) -> Result<&'a NameBinding<'a>, Determinacy> { self.resolve_ident_in_module_unadjusted_ext( module, @@ -819,8 +797,7 @@ impl<'a> Resolver<'a> { parent_scope, false, finalize, - last_import_segment, - unusable_binding, + ignore_binding, ) .map_err(|(determinacy, _)| determinacy) } @@ -835,9 +812,10 @@ impl<'a> Resolver<'a> { ns: Namespace, parent_scope: &ParentScope<'a>, restricted_shadowing: bool, - finalize: Option<Span>, - last_import_segment: bool, - unusable_binding: Option<&'a NameBinding<'a>>, + 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<&'a NameBinding<'a>>, ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, @@ -849,8 +827,7 @@ impl<'a> Resolver<'a> { parent_scope, finalize, finalize.is_some(), - last_import_segment, - unusable_binding, + ignore_binding, ); return binding.map_err(|determinacy| (determinacy, Weak::No)); } @@ -890,8 +867,7 @@ impl<'a> Resolver<'a> { parent_scope, finalize, finalize.is_some(), - last_import_segment, - unusable_binding, + ignore_binding, ); return binding.map_err(|determinacy| (determinacy, Weak::No)); } @@ -901,19 +877,15 @@ impl<'a> Resolver<'a> { let resolution = self.resolution(module, key).try_borrow_mut().map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports. - if let Some(path_span) = finalize { + if let Some(Finalize { path_span, report_private, .. }) = finalize { // If the primary binding is unusable, search further and return the shadowed glob // binding if it exists. What we really want here is having two separate scopes in // a module - one for non-globs and one for globs, but until that's done use this // hack to avoid inconsistent resolution ICEs during import validation. let binding = [resolution.binding, resolution.shadowed_glob] .into_iter() - .filter_map(|binding| match (binding, unusable_binding) { - (Some(binding), Some(unusable_binding)) - if ptr::eq(binding, unusable_binding) => - { - None - } + .filter_map(|binding| match (binding, ignore_binding) { + (Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None, _ => binding, }) .next(); @@ -922,14 +894,14 @@ impl<'a> Resolver<'a> { }; if !self.is_accessible_from(binding.vis, parent_scope.module) { - if last_import_segment { - return Err((Determined, Weak::No)); - } else { + if report_private { self.privacy_errors.push(PrivacyError { ident, binding, dedup_span: path_span, }); + } else { + return Err((Determined, Weak::No)); } } @@ -960,10 +932,8 @@ impl<'a> Resolver<'a> { } let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { - if let Some(unusable_binding) = unusable_binding { - if ptr::eq(binding, unusable_binding) { - return Err((Determined, Weak::No)); - } + if let Some(ignored) = ignore_binding && ptr::eq(binding, ignored) { + return Err((Determined, Weak::No)); } let usable = this.is_accessible_from(binding.vis, parent_scope.module); if usable { Ok(binding) } else { Err((Determined, Weak::No)) } @@ -996,8 +966,7 @@ impl<'a> Resolver<'a> { ns, &single_import.parent_scope, None, - last_import_segment, - unusable_binding, + ignore_binding, ) { Err(Determined) => continue, Ok(binding) @@ -1073,8 +1042,7 @@ impl<'a> Resolver<'a> { ns, adjusted_parent_scope, None, - last_import_segment, - unusable_binding, + ignore_binding, ); match result { @@ -1371,7 +1339,7 @@ impl<'a> Resolver<'a> { opt_ns: Option<Namespace>, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, ) -> PathResult<'a> { - self.resolve_path_with_ribs(path, opt_ns, parent_scope, Finalize::No, None, None) + self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None) } #[tracing::instrument(level = "debug", skip(self))] @@ -1380,10 +1348,10 @@ impl<'a> Resolver<'a> { path: &[Segment], opt_ns: Option<Namespace>, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, - finalize: Finalize, - unusable_binding: Option<&'a NameBinding<'a>>, + finalize: Option<Finalize>, + ignore_binding: Option<&'a NameBinding<'a>>, ) -> PathResult<'a> { - self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, unusable_binding) + self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding) } crate fn resolve_path_with_ribs( @@ -1391,13 +1359,12 @@ impl<'a> Resolver<'a> { path: &[Segment], opt_ns: Option<Namespace>, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, - finalize_full: Finalize, + finalize: Option<Finalize>, ribs: Option<&PerNS<Vec<Rib<'a>>>>, - unusable_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option<&'a NameBinding<'a>>, ) -> PathResult<'a> { - debug!("resolve_path(path={:?}, opt_ns={:?}, finalize={:?})", path, opt_ns, finalize_full); + debug!("resolve_path(path={:?}, opt_ns={:?}, finalize={:?})", path, opt_ns, finalize); - let finalize = finalize_full.path_span(); let mut module = None; let mut allow_super = true; let mut second_binding = None; @@ -1497,8 +1464,7 @@ impl<'a> Resolver<'a> { ns, parent_scope, finalize, - false, - unusable_binding, + ignore_binding, ) } else if let Some(ribs) = ribs && let Some(TypeNS | ValueNS) = opt_ns @@ -1507,9 +1473,9 @@ impl<'a> Resolver<'a> { ident, ns, parent_scope, - finalize_full, + finalize, &ribs[ns], - unusable_binding, + ignore_binding, ) { // we found a locally-imported or available item/module Some(LexicalScopeBinding::Item(binding)) => Ok(binding), @@ -1525,8 +1491,7 @@ impl<'a> Resolver<'a> { parent_scope, finalize, finalize.is_some(), - false, - unusable_binding, + ignore_binding, ) }; FindBindingResult::Binding(binding) @@ -1566,7 +1531,7 @@ impl<'a> Resolver<'a> { } else if res == Res::Err { return PathResult::NonModule(PartialRes::new(Res::Err)); } else if opt_ns.is_some() && (is_last || maybe_assoc) { - self.lint_if_path_starts_with_module(finalize_full, path, second_binding); + self.lint_if_path_starts_with_module(finalize, path, second_binding); return PathResult::NonModule(PartialRes::with_unresolved_segments( res, path.len() - i - 1, @@ -1599,7 +1564,7 @@ impl<'a> Resolver<'a> { opt_ns, parent_scope, ribs, - unusable_binding, + ignore_binding, module, i, ident, @@ -1609,7 +1574,7 @@ impl<'a> Resolver<'a> { } } - self.lint_if_path_starts_with_module(finalize_full, path, second_binding); + self.lint_if_path_starts_with_module(finalize, path, second_binding); PathResult::Module(match module { Some(module) => module, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 01dc727737a..ef06ec356bd 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -545,7 +545,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { ns, &import.parent_scope, None, - false, None, ); import.vis.set(orig_vis); @@ -589,22 +588,18 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// consolidate multiple unresolved import errors into a single diagnostic. fn finalize_import(&mut self, import: &'b Import<'b>) -> Option<UnresolvedImportError> { let orig_vis = import.vis.replace(ty::Visibility::Invisible); - let unusable_binding = match &import.kind { + let ignore_binding = match &import.kind { ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(), _ => None, }; let prev_ambiguity_errors_len = self.r.ambiguity_errors.len(); - let finalize = Finalize::UsePath { - root_id: import.root_id, - root_span: import.root_span, - path_span: import.span, - }; + let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span); let path_res = self.r.resolve_path( &import.module_path, None, &import.parent_scope, - finalize, - unusable_binding, + Some(finalize), + ignore_binding, ); let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len; import.vis.set(orig_vis); @@ -685,7 +680,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // 2 segments, so the `resolve_path` above won't trigger it. let mut full_path = import.module_path.clone(); full_path.push(Segment::from_ident(Ident::empty())); - self.r.lint_if_path_starts_with_module(finalize, &full_path, None); + self.r.lint_if_path_starts_with_module(Some(finalize), &full_path, None); } if let ModuleOrUniformRoot::Module(module) = module { @@ -720,8 +715,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { ident, ns, &import.parent_scope, - Some(import.span), - true, + Some(Finalize { report_private: false, ..finalize }), target_bindings[ns].get(), ); import.vis.set(orig_vis); @@ -781,8 +775,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { ident, ns, &import.parent_scope, - Some(import.span), - false, + Some(finalize), None, ); if binding.is_ok() { @@ -948,7 +941,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { full_path.push(Segment::from_ident(ident)); self.r.per_ns(|this, ns| { if let Ok(binding) = source_bindings[ns].get() { - this.lint_if_path_starts_with_module(finalize, &full_path, Some(binding)); + this.lint_if_path_starts_with_module(Some(finalize), &full_path, Some(binding)); } }); } @@ -1003,7 +996,6 @@ impl<'a, 'b> ImportResolver<'a, 'b> { &import.parent_scope, None, false, - false, target_bindings[ns].get(), ) { Ok(other_binding) => { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 591bad70840..ca89f610322 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -12,15 +12,17 @@ use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; use rustc_ast::ptr::P; -use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; +use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; use rustc_ast::*; -use rustc_ast_lowering::ResolverAstLowering; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; +use rustc_hir::definitions::DefPathData; use rustc_hir::{PrimTy, TraitCandidate}; +use rustc_index::vec::Idx; use rustc_middle::ty::DefIdTree; use rustc_middle::{bug, span_bug}; use rustc_session::lint; @@ -195,7 +197,17 @@ enum LifetimeRibKind { Item, /// This rib declares generic parameters. - Generics { span: Span, kind: LifetimeBinderKind }, + Generics { parent: NodeId, span: Span, kind: LifetimeBinderKind }, + + /// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const + /// generics. We are disallowing this until we can decide on how we want to handle non-'static + /// lifetimes in const generics. See issue #74052 for discussion. + ConstGeneric, + + /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`. + /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by + /// `body_id` is an anonymous constant and `lifetime_ref` is non-static. + AnonConst, /// For **Modern** cases, create a new anonymous region parameter /// and reference that. @@ -204,7 +216,7 @@ enum LifetimeRibKind { /// `resolve_lifetime` code. /// /// For **Deprecated** cases, report an error. - AnonymousCreateParameter, + AnonymousCreateParameter(NodeId), /// Give a hard error when either `&` or `'_` is written. Used to /// rule out things like `where T: Foo<'_>`. Does not imply an @@ -212,7 +224,7 @@ enum LifetimeRibKind { AnonymousReportError, /// Pass responsibility to `resolve_lifetime` code for all cases. - AnonymousPassThrough, + AnonymousPassThrough(NodeId), } #[derive(Copy, Clone, Debug)] @@ -242,7 +254,8 @@ impl LifetimeBinderKind { #[derive(Debug)] struct LifetimeRib { kind: LifetimeRibKind, - bindings: IdentMap<()>, + // We need to preserve insertion order for async fns. + bindings: FxIndexMap<Ident, (NodeId, LifetimeRes)>, } impl LifetimeRib { @@ -524,7 +537,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_anon_const(&mut self, constant: &'ast AnonConst) { // We deal with repeat expressions explicitly in `resolve_expr`. - self.resolve_anon_const(constant, IsRepeatExpr::No); + self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| { + this.resolve_anon_const(constant, IsRepeatExpr::No); + }) } fn visit_expr(&mut self, expr: &'ast Expr) { self.resolve_expr(expr, None); @@ -563,7 +578,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { .resolve_ident_in_lexical_scope( self_ty, TypeNS, - Finalize::SimplePath(ty.id, ty.span), + Some(Finalize::new(ty.id, ty.span)), None, ) .map_or(Res::Err, |d| d.res()); @@ -581,12 +596,19 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { self.with_generic_param_rib( &bare_fn.generic_params, NormalRibKind, - LifetimeRibKind::Generics { kind: LifetimeBinderKind::BareFnType, span }, + LifetimeRibKind::Generics { + parent: ty.id, + kind: LifetimeBinderKind::BareFnType, + span, + }, |this| { - this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| { - this.visit_generic_param_vec(&bare_fn.generic_params, false); - visit::walk_fn_decl(this, &bare_fn.decl); - }); + this.with_lifetime_rib( + LifetimeRibKind::AnonymousPassThrough(ty.id), + |this| { + this.visit_generic_param_vec(&bare_fn.generic_params, false); + visit::walk_fn_decl(this, &bare_fn.decl); + }, + ); }, ); self.diagnostic_metadata.current_trait_object = prev; @@ -604,7 +626,11 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { self.with_generic_param_rib( &tref.bound_generic_params, NormalRibKind, - LifetimeRibKind::Generics { kind: LifetimeBinderKind::PolyTrait, span }, + LifetimeRibKind::Generics { + parent: tref.trait_ref.ref_id, + kind: LifetimeBinderKind::PolyTrait, + span, + }, |this| { this.visit_generic_param_vec(&tref.bound_generic_params, false); this.smart_resolve_path( @@ -625,6 +651,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { &generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { + parent: foreign_item.id, kind: LifetimeBinderKind::Item, span: generics.span, }, @@ -638,6 +665,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { &generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { + parent: foreign_item.id, kind: LifetimeBinderKind::Function, span: generics.span, }, @@ -655,13 +683,13 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } } } - fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) { + fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) { let rib_kind = match fn_kind { // Bail if the function is foreign, and thus cannot validly have // a body, or if there's no body for some other reason. FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _) | FnKind::Fn(_, _, sig, _, generics, None) => { - self.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| { + self.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| { // We don't need to deal with patterns in parameters, because // they are not possible for foreign or bodiless functions. this.visit_fn_header(&sig.header); @@ -691,20 +719,50 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { this.visit_generics(generics); } - if async_node_id.is_some() { + if let Some(async_node_id) = async_node_id { // In `async fn`, argument-position elided lifetimes // must be transformed into fresh generic parameters so that // they can be applied to the opaque `impl Trait` return type. - this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter, |this| { - // Add each argument to the rib. - this.resolve_params(&declaration.inputs) - }); + this.with_lifetime_rib( + LifetimeRibKind::AnonymousCreateParameter(fn_id), + |this| { + // Add each argument to the rib. + this.resolve_params(&declaration.inputs) + }, + ); - this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| { - visit::walk_fn_ret_ty(this, &declaration.output) - }); + // Construct the list of in-scope lifetime parameters for async lowering. + // We include all lifetime parameters, either named or "Fresh". + // The order of those parameters does not matter, as long as it is + // deterministic. + let mut extra_lifetime_params = + this.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default(); + for rib in this.lifetime_ribs.iter().rev() { + extra_lifetime_params.extend( + rib.bindings + .iter() + .map(|(&ident, &(node_id, res))| (ident, node_id, res)), + ); + match rib.kind { + LifetimeRibKind::Item => break, + LifetimeRibKind::AnonymousCreateParameter(id) => { + if let Some(earlier_fresh) = + this.r.extra_lifetime_params_map.get(&id) + { + extra_lifetime_params.extend(earlier_fresh); + } + } + _ => {} + } + } + this.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params); + + this.with_lifetime_rib( + LifetimeRibKind::AnonymousPassThrough(async_node_id), + |this| visit::walk_fn_ret_ty(this, &declaration.output), + ); } else { - this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| { + this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| { // Add each argument to the rib. this.resolve_params(&declaration.inputs); @@ -716,13 +774,12 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // Be sure not to set this until the function signature has been resolved. let previous_state = replace(&mut this.in_func_body, true); // Resolve the function body, potentially inside the body of an async closure - this.with_lifetime_rib( - LifetimeRibKind::AnonymousPassThrough, - |this| match fn_kind { + this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(fn_id), |this| { + match fn_kind { FnKind::Fn(.., body) => walk_list!(this, visit_block, body), FnKind::Closure(_, body) => this.visit_expr(body), - }, - ); + } + }); debug!("(resolving function) leaving function"); this.in_func_body = previous_state; @@ -801,10 +858,10 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { if let Some(ref args) = path_segment.args { match &**args { GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, path_span, args), - GenericArgs::Parenthesized(..) => self - .with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, |this| { - visit::walk_generic_args(this, path_span, args) - }), + GenericArgs::Parenthesized(..) => self.with_lifetime_rib( + LifetimeRibKind::AnonymousPassThrough(path_segment.id), + |this| visit::walk_generic_args(this, path_span, args), + ), } } } @@ -830,12 +887,16 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { this.with_generic_param_rib( &bound_generic_params, NormalRibKind, - LifetimeRibKind::Generics { kind: LifetimeBinderKind::WhereBound, span }, + LifetimeRibKind::Generics { + parent: bounded_ty.id, + kind: LifetimeBinderKind::WhereBound, + span, + }, |this| { this.visit_generic_param_vec(&bound_generic_params, false); this.visit_ty(bounded_ty); for bound in bounds { - this.visit_param_bound(bound) + this.visit_param_bound(bound, BoundKind::Bound) } }, ); @@ -897,7 +958,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ident, ns, &self.parent_scope, - Finalize::No, + None, &self.ribs[ns], None, ) @@ -907,8 +968,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &mut self, ident: Ident, ns: Namespace, - finalize: Finalize, - unusable_binding: Option<&'a NameBinding<'a>>, + finalize: Option<Finalize>, + ignore_binding: Option<&'a NameBinding<'a>>, ) -> Option<LexicalScopeBinding<'a>> { self.r.resolve_ident_in_lexical_scope( ident, @@ -916,7 +977,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &self.parent_scope, finalize, &self.ribs[ns], - unusable_binding, + ignore_binding, ) } @@ -924,7 +985,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &mut self, path: &[Segment], opt_ns: Option<Namespace>, // `None` indicates a module path in import - finalize: Finalize, + finalize: Option<Finalize>, ) -> PathResult<'a> { self.r.resolve_path_with_ribs( path, @@ -1026,12 +1087,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { match param.kind { GenericParamKind::Lifetime => { for bound in ¶m.bounds { - this.visit_param_bound(bound); + this.visit_param_bound(bound, BoundKind::Bound); } } GenericParamKind::Type { ref default } => { for bound in ¶m.bounds { - this.visit_param_bound(bound); + this.visit_param_bound(bound, BoundKind::Bound); } if let Some(ref ty) = default { @@ -1053,14 +1114,18 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind)); this.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind)); - this.visit_ty(ty); + this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| { + this.visit_ty(ty) + }); this.ribs[TypeNS].pop().unwrap(); this.ribs[ValueNS].pop().unwrap(); if let Some(ref expr) = default { this.ribs[TypeNS].push(forward_ty_ban_rib); this.ribs[ValueNS].push(forward_const_ban_rib); - this.visit_anon_const(expr); + this.with_lifetime_rib(LifetimeRibKind::ConstGeneric, |this| { + this.resolve_anon_const(expr, IsRepeatExpr::No) + }); forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap(); forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap(); } @@ -1092,6 +1157,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let ident = lifetime.ident; if ident.name == kw::StaticLifetime { + self.record_lifetime_res(lifetime.id, LifetimeRes::Static); return; } @@ -1103,12 +1169,24 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { for i in &mut indices { let rib = &self.lifetime_ribs[i]; let normalized_ident = ident.normalize_to_macros_2_0(); - if let Some(_) = rib.bindings.get_key_value(&normalized_ident) { + if let Some(&(_, region)) = rib.bindings.get(&normalized_ident) { + self.record_lifetime_res(lifetime.id, region); return; } - if let LifetimeRibKind::Item = rib.kind { - break; + match rib.kind { + LifetimeRibKind::Item => break, + LifetimeRibKind::ConstGeneric => { + self.emit_non_static_lt_in_const_generic_error(lifetime); + self.r.lifetimes_res_map.insert(lifetime.id, LifetimeRes::Error); + return; + } + LifetimeRibKind::AnonConst => { + self.maybe_emit_forbidden_non_static_lifetime_error(lifetime); + self.r.lifetimes_res_map.insert(lifetime.id, LifetimeRes::Error); + return; + } + _ => {} } } @@ -1123,6 +1201,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } self.emit_undeclared_lifetime_error(lifetime, outer_res); + self.record_lifetime_res(lifetime.id, LifetimeRes::Error); } #[tracing::instrument(level = "debug", skip(self))] @@ -1132,6 +1211,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { for i in (0..self.lifetime_ribs.len()).rev() { let rib = &mut self.lifetime_ribs[i]; match rib.kind { + LifetimeRibKind::AnonymousCreateParameter(item_node_id) => { + self.create_fresh_lifetime(lifetime.id, lifetime.ident, item_node_id); + return; + } LifetimeRibKind::AnonymousReportError => { let (msg, note) = if elided { ( @@ -1151,35 +1234,73 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { .span_label(lifetime.ident.span, note) .emit(); + self.record_lifetime_res(lifetime.id, LifetimeRes::Error); + return; + } + LifetimeRibKind::AnonymousPassThrough(node_id) => { + self.record_lifetime_res( + lifetime.id, + LifetimeRes::Anonymous { binder: node_id, elided }, + ); return; } - LifetimeRibKind::AnonymousCreateParameter - | LifetimeRibKind::AnonymousPassThrough - | LifetimeRibKind::Item => return, + LifetimeRibKind::Item => break, _ => {} } } + // This resolution is wrong, it passes the work to HIR lifetime resolution. + // We cannot use `LifetimeRes::Error` because we do not emit a diagnostic. + self.record_lifetime_res( + lifetime.id, + LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided }, + ); } #[tracing::instrument(level = "debug", skip(self))] fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) { let id = self.r.next_node_id(); + self.record_lifetime_res( + anchor_id, + LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) }, + ); + let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) }; self.resolve_anonymous_lifetime(<, true); } #[tracing::instrument(level = "debug", skip(self))] + fn create_fresh_lifetime(&mut self, id: NodeId, ident: Ident, item_node_id: NodeId) { + debug_assert_eq!(ident.name, kw::UnderscoreLifetime); + debug!(?ident.span); + let item_def_id = self.r.local_def_id(item_node_id); + let def_node_id = self.r.next_node_id(); + let def_id = self.r.create_def( + item_def_id, + def_node_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + self.parent_scope.expansion.to_expn_id(), + ident.span, + ); + debug!(?def_id); + + let region = LifetimeRes::Fresh { param: def_id, binder: item_node_id }; + self.record_lifetime_res(id, region); + self.r.extra_lifetime_params_map.entry(item_node_id).or_insert_with(Vec::new).push(( + ident, + def_node_id, + region, + )); + } + + #[tracing::instrument(level = "debug", skip(self))] fn resolve_elided_lifetimes_in_path( &mut self, path_id: NodeId, partial_res: PartialRes, path: &[Segment], source: PathSource<'_>, - finalize: Finalize, + path_span: Span, ) { - let Some(path_span) = finalize.path_span() else { - return; - }; let proj_start = path.len() - partial_res.unresolved_segments(); for (i, segment) in path.iter().enumerate() { if segment.has_lifetime_args { @@ -1222,7 +1343,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { | PathSource::Struct | PathSource::TupleStruct(..) => false, }; - let mut error = false; + let mut res = LifetimeRes::Error; for rib in self.lifetime_ribs.iter().rev() { match rib.kind { // In create-parameter mode we error here because we don't want to support @@ -1231,8 +1352,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // // impl Foo for std::cell::Ref<u32> // note lack of '_ // async fn foo(_: std::cell::Ref<u32>) { ... } - LifetimeRibKind::AnonymousCreateParameter => { - error = true; + LifetimeRibKind::AnonymousCreateParameter(_) => { break; } // `PassThrough` is the normal case. @@ -1241,13 +1361,31 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit // lifetime. Instead, we simply create an implicit lifetime, which will be checked // later, at which point a suitable error will be emitted. - LifetimeRibKind::AnonymousPassThrough - | LifetimeRibKind::AnonymousReportError - | LifetimeRibKind::Item => break, + LifetimeRibKind::AnonymousPassThrough(binder) => { + res = LifetimeRes::Anonymous { binder, elided: true }; + break; + } + LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => { + // FIXME(cjgillot) This resolution is wrong, but this does not matter + // since these cases are erroneous anyway. Lifetime resolution should + // emit a "missing lifetime specifier" diagnostic. + res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true }; + break; + } _ => {} } } + let node_ids = self.r.next_node_ids(expected_lifetimes); + self.record_lifetime_res( + segment_id, + LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end }, + ); + for i in 0..expected_lifetimes { + let id = node_ids.start.plus(i); + self.record_lifetime_res(id, res); + } + if !missing { continue; } @@ -1261,7 +1399,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // originating from macros, since the segment's span might be from a macro arg. segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span) }; - if error { + if let LifetimeRes::Error = res { let sess = self.r.session; let mut err = rustc_errors::struct_span_err!( sess, @@ -1296,9 +1434,19 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } } + #[tracing::instrument(level = "debug", skip(self))] + fn record_lifetime_res(&mut self, id: NodeId, res: LifetimeRes) { + if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) { + panic!( + "lifetime {:?} resolved multiple times ({:?} before, {:?} now)", + id, prev_res, res + ) + } + } + /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved /// label and reports an error if the label is not found or is unreachable. - fn resolve_label(&self, mut label: Ident) -> Option<NodeId> { + fn resolve_label(&mut self, mut label: Ident) -> Option<NodeId> { let mut suggestion = None; // Preserve the original span so that errors contain "in this macro invocation" @@ -1318,6 +1466,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let ident = label.normalize_to_macro_rules(); if let Some((ident, id)) = rib.bindings.get_key_value(&ident) { + let definition_span = ident.span; return if self.is_label_valid_from_rib(i) { Some(*id) } else { @@ -1325,7 +1474,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { original_span, ResolutionError::UnreachableLabel { name: label.name, - definition_span: ident.span, + definition_span, suggestion, }, ); @@ -1379,7 +1528,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_generic_param_rib( &generics.params, ItemRibKind(HasGenericParams::Yes), - LifetimeRibKind::Generics { kind: LifetimeBinderKind::Item, span: generics.span }, + LifetimeRibKind::Generics { + parent: item.id, + kind: LifetimeBinderKind::Item, + span: generics.span, + }, |this| { let item_def_id = this.r.local_def_id(item.id).to_def_id(); this.with_self_rib( @@ -1420,8 +1573,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { report_error(self, ns); } Some(LexicalScopeBinding::Item(binding)) => { - if let Some(LexicalScopeBinding::Res(..)) = self - .resolve_ident_in_lexical_scope(ident, ns, Finalize::No, Some(binding)) + if let Some(LexicalScopeBinding::Res(..)) = + self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding)) { report_error(self, ns); } @@ -1446,6 +1599,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { + parent: item.id, kind: LifetimeBinderKind::Item, span: generics.span, }, @@ -1458,6 +1612,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { + parent: item.id, kind: LifetimeBinderKind::Function, span: generics.span, }, @@ -1487,6 +1642,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { + parent: item.id, kind: LifetimeBinderKind::Item, span: generics.span, }, @@ -1496,7 +1652,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { Res::SelfTy { trait_: Some(local_def_id), alias_to: None }, |this| { this.visit_generics(generics); - walk_list!(this, visit_param_bound, bounds); + walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits); let walk_assoc_item = |this: &mut Self, @@ -1506,7 +1662,11 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_generic_param_rib( &generics.params, AssocItemRibKind, - LifetimeRibKind::Generics { span: generics.span, kind }, + LifetimeRibKind::Generics { + parent: item.id, + span: generics.span, + kind, + }, |this| { visit::walk_assoc_item(this, item, AssocCtxt::Trait) }, @@ -1571,6 +1731,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { + parent: item.id, kind: LifetimeBinderKind::Item, span: generics.span, }, @@ -1580,7 +1741,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { Res::SelfTy { trait_: Some(local_def_id), alias_to: None }, |this| { this.visit_generics(generics); - walk_list!(this, visit_param_bound, bounds); + walk_list!(this, visit_param_bound, bounds, BoundKind::Bound); }, ); }, @@ -1696,7 +1857,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { "invalid lifetime parameter name: `{}`", param.ident, ) - .span_label(param.ident.span, format!("'static is a reserved lifetime name")) + .span_label(param.ident.span, "'static is a reserved lifetime name") .emit(); continue; } @@ -1708,7 +1869,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam), GenericParamKind::Const { .. } => (&mut function_value_rib, DefKind::ConstParam), GenericParamKind::Lifetime => { - function_lifetime_rib.bindings.insert(ident, ()); + let LifetimeRibKind::Generics { parent, .. } = lifetime_kind else { panic!() }; + let res = LifetimeRes::Param { param: def_id, binder: parent }; + self.record_lifetime_res(param.id, res); + function_lifetime_rib.bindings.insert(ident, (param.id, res)); continue; } }; @@ -1812,7 +1976,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { None, &path, PathSource::Trait(AliasPossibility::No), - Finalize::SimplePath(trait_ref.ref_id, trait_ref.path.span), + Finalize::new(trait_ref.ref_id, trait_ref.path.span), ); if let Some(def_id) = res.base_res().opt_def_id() { new_id = Some(def_id); @@ -1849,10 +2013,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ) { debug!("resolve_implementation"); // If applicable, create a rib for the type parameters. - self.with_generic_param_rib(&generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::ImplBlock }, |this| { + self.with_generic_param_rib(&generics.params, ItemRibKind(HasGenericParams::Yes), LifetimeRibKind::Generics { span: generics.span, parent: item_id, kind: LifetimeBinderKind::ImplBlock }, |this| { // Dummy self type for better errors if `Self` is used in the trait path. this.with_self_rib(Res::SelfTy { trait_: None, alias_to: None }, |this| { - this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter, |this| { + this.with_lifetime_rib(LifetimeRibKind::AnonymousCreateParameter(item_id), |this| { // Resolve the trait reference, if necessary. this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this, trait_id| { let item_def_id = this.r.local_def_id(item_id); @@ -1876,7 +2040,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.visit_generics(generics); // Resolve the items within the impl. - this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough, + this.with_lifetime_rib(LifetimeRibKind::AnonymousPassThrough(item_id), |this| { this.with_current_self_type(self_type, |this| { this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { @@ -1921,7 +2085,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_generic_param_rib( &generics.params, AssocItemRibKind, - LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::Function }, + LifetimeRibKind::Generics { parent: item.id, span: generics.span, kind: LifetimeBinderKind::Function }, |this| { // If this is a trait impl, ensure the method // exists in trait @@ -1950,7 +2114,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_generic_param_rib( &generics.params, AssocItemRibKind, - LifetimeRibKind::Generics { span: generics.span, kind: LifetimeBinderKind::Item }, + LifetimeRibKind::Generics { parent: item.id, span: generics.span, kind: LifetimeBinderKind::Item }, |this| { // If this is a trait impl, ensure the type // exists in trait @@ -1996,7 +2160,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { span: Span, err: F, ) where - F: FnOnce(Ident, &str, Option<Symbol>) -> ResolutionError<'_>, + F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'a>, { // If there is a TraitRef in scope for an impl, then the method must be in the trait. let Some((module, _)) = &self.current_trait_ref else { return; }; @@ -2020,7 +2184,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // 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; - self.report_error(span, err(ident, &path_names_to_string(path), candidate)); + let path_names = path_names_to_string(path); + self.report_error(span, err(ident, path_names, candidate)); return; }; @@ -2044,13 +2209,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { AssocItemKind::TyAlias(..) => (rustc_errors::error_code!(E0325), "type"), AssocItemKind::MacCall(..) => span_bug!(span, "unexpanded macro"), }; + let trait_path = path_names_to_string(path); self.report_error( span, ResolutionError::TraitImplMismatch { name: ident.name, kind, code, - trait_path: path_names_to_string(path), + trait_path, trait_item_span: binding.span, }, ); @@ -2165,16 +2331,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } // 3) Report all missing variables we found. - let mut missing_vars = missing_vars.iter_mut().collect::<Vec<_>>(); - missing_vars.sort_by_key(|(sym, _err)| sym.as_str()); + let mut missing_vars = missing_vars.into_iter().collect::<Vec<_>>(); + missing_vars.sort_by_key(|&(sym, ref _err)| sym); - for (name, mut v) in missing_vars { - if inconsistent_vars.contains_key(name) { + for (name, mut v) in missing_vars.into_iter() { + if inconsistent_vars.contains_key(&name) { v.could_be_path = false; } self.report_error( *v.origin.iter().next().unwrap(), - ResolutionError::VariableNotBoundInPattern(v), + ResolutionError::VariableNotBoundInPattern(v, self.parent_scope), ); } @@ -2484,7 +2650,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { qself, &Segment::from_path(path), source, - Finalize::SimplePath(id, path.span), + Finalize::new(id, path.span), ); } @@ -2503,8 +2669,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ); let ns = source.namespace(); - let (id, path_span) = - finalize.node_id_and_path_span().expect("unexpected speculative resolution"); + let Finalize { node_id, path_span, .. } = finalize; let report_errors = |this: &mut Self, res: Option<Res>| { if this.should_report_errs() { let (err, candidates) = @@ -2618,7 +2783,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if ns == ValueNS { let item_name = path.last().unwrap().ident; let traits = self.traits_in_scope(item_name, ns); - self.r.trait_map.insert(id, traits); + self.r.trait_map.insert(node_id, traits); } if PrimTy::from_name(path[0].ident.name).is_some() { @@ -2627,7 +2792,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { std_path.push(Segment::from_ident(Ident::with_dummy_span(sym::std))); std_path.extend(path); if let PathResult::Module(_) | PathResult::NonModule(_) = - self.resolve_path(&std_path, Some(ns), Finalize::No) + self.resolve_path(&std_path, Some(ns), None) { // Check if we wrote `str::from_utf8` instead of `std::str::from_utf8` let item_span = @@ -2654,10 +2819,10 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { if !matches!(source, PathSource::TraitItem(..)) { // Avoid recording definition of `A::B` in `<T as A>::B::C`. - self.r.record_partial_res(id, partial_res); + self.r.record_partial_res(node_id, partial_res); + self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span); } - self.resolve_elided_lifetimes_in_path(id, partial_res, path, source, finalize); partial_res } @@ -2676,7 +2841,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { /// A wrapper around [`Resolver::report_error`]. /// /// This doesn't emit errors for function bodies if this is rustdoc. - fn report_error(&self, span: Span, resolution_error: ResolutionError<'_>) { + fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'a>) { if self.should_report_errs() { self.r.report_error(span, resolution_error); } @@ -2763,21 +2928,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // the trait (the slice upto and including // `qself.position`). And then we recursively resolve that, // but with `qself` set to `None`. - // - // However, setting `qself` to none (but not changing the - // span) loses the information about where this path - // *actually* appears, so for the purposes of the crate - // lint we pass along information that this is the trait - // name from a fully qualified path, and this also - // contains the full span (the `Finalize::QPathTrait`). let ns = if qself.position + 1 == path.len() { ns } else { TypeNS }; let partial_res = self.smart_resolve_path_fragment( None, &path[..=qself.position], PathSource::TraitItem(ns), - finalize.node_id_and_path_span().map_or(Finalize::No, |(qpath_id, path_span)| { - Finalize::QPathTrait { qpath_id, qpath_span: qself.path_span, path_span } - }), + Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span), ); // The remaining segments (the `C` in our example) will @@ -2789,7 +2945,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ))); } - let result = match self.resolve_path(&path, Some(ns), finalize) { + let result = match self.resolve_path(&path, Some(ns), Some(finalize)) { PathResult::NonModule(path_res) => path_res, PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => { PartialRes::new(module.res().unwrap()) @@ -2827,10 +2983,9 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { && result.base_res() != Res::Err && path[0].ident.name != kw::PathRoot && path[0].ident.name != kw::DollarCrate - && let Some((id, path_span)) = finalize.node_id_and_path_span() { let unqualified_result = { - match self.resolve_path(&[*path.last().unwrap()], Some(ns), Finalize::No) { + match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) { PathResult::NonModule(path_res) => path_res.base_res(), PathResult::Module(ModuleOrUniformRoot::Module(module)) => { module.res().unwrap() @@ -2840,7 +2995,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }; if result.base_res() == unqualified_result { let lint = lint::builtin::UNUSED_QUALIFICATIONS; - self.r.lint_buffer.buffer_lint(lint, id, path_span, "unnecessary qualification") + self.r.lint_buffer.buffer_lint( + lint, + finalize.node_id, + finalize.path_span, + "unnecessary qualification", + ) } } @@ -2923,9 +3083,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { is_repeat, constant.value.is_potential_trivial_const_param(), None, - |this| { - visit::walk_anon_const(this, constant); - }, + |this| visit::walk_anon_const(this, constant), ); } @@ -3076,7 +3234,12 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } ExprKind::Repeat(ref elem, ref ct) => { self.visit_expr(elem); - self.resolve_anon_const(ct, IsRepeatExpr::Yes); + self.with_lifetime_rib(LifetimeRibKind::AnonConst, |this| { + this.resolve_anon_const(ct, IsRepeatExpr::Yes) + }); + } + ExprKind::ConstBlock(ref ct) => { + self.resolve_anon_const(ct, IsRepeatExpr::No); } ExprKind::Index(ref elem, ref idx) => { self.resolve_expr(elem, Some(expr)); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d77cc917e2f..3076cc11317 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3,7 +3,7 @@ use crate::late::lifetimes::{ElisionFailureInfo, LifetimeContext}; use crate::late::{AliasPossibility, LateResolutionVisitor, RibKind}; use crate::late::{LifetimeBinderKind, LifetimeRibKind}; use crate::path_names_to_string; -use crate::{Finalize, Module, ModuleKind, ModuleOrUniformRoot}; +use crate::{Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; use rustc_ast::visit::FnKind; @@ -86,7 +86,7 @@ impl ForLifetimeSpanType { } } -impl<'tcx> Into<MissingLifetimeSpot<'tcx>> for &'tcx hir::Generics<'tcx> { +impl<'tcx> Into<MissingLifetimeSpot<'tcx>> for &&'tcx hir::Generics<'tcx> { fn into(self) -> MissingLifetimeSpot<'tcx> { MissingLifetimeSpot::Generics(self) } @@ -189,7 +189,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { (String::new(), "the crate root".to_string()) } else { let mod_path = &path[..path.len() - 1]; - let mod_prefix = match self.resolve_path(mod_path, Some(TypeNS), Finalize::No) { + let mod_prefix = match self.resolve_path(mod_path, Some(TypeNS), None) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => module.res(), _ => None, } @@ -648,7 +648,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { if let crate::PathSource::TraitItem(_) = source { let mod_path = &path[..path.len() - 1]; if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = - self.resolve_path(mod_path, None, Finalize::No) + self.resolve_path(mod_path, None, None) { let resolutions = self.r.resolutions(module).borrow(); let targets: Vec<_> = @@ -1183,9 +1183,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { ident: Symbol, kind: &AssocItemKind, ) -> Option<Symbol> { - let Some((module, _)) = &self.current_trait_ref else { - return None; - }; + let (module, _) = self.current_trait_ref.as_ref()?; if ident == kw::Underscore { // We do nothing for `_`. return None; @@ -1364,7 +1362,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // Search in module. let mod_path = &path[..path.len() - 1]; if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = - self.resolve_path(mod_path, Some(TypeNS), Finalize::No) + self.resolve_path(mod_path, Some(TypeNS), None) { self.r.add_module_candidates(module, &mut names, &filter_fn); } @@ -1824,7 +1822,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { for rib in self.lifetime_ribs.iter().rev() { match rib.kind { - LifetimeRibKind::Generics { span, kind } => { + LifetimeRibKind::Generics { parent: _, span, kind } => { if !span.can_be_used_for_suggestions() && suggest_note { suggest_note = false; // Avoid displaying the same help multiple times. err.span_label( @@ -1888,6 +1886,37 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { err.emit(); } + + crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &ast::Lifetime) { + struct_span_err!( + self.r.session, + lifetime_ref.ident.span, + E0771, + "use of non-static lifetime `{}` in const generic", + lifetime_ref.ident + ) + .note( + "for more information, see issue #74052 \ + <https://github.com/rust-lang/rust/issues/74052>", + ) + .emit(); + } + + /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`. + /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by + /// `body_id` is an anonymous constant and `lifetime_ref` is non-static. + crate fn maybe_emit_forbidden_non_static_lifetime_error(&self, lifetime_ref: &ast::Lifetime) { + let feature_active = self.r.session.features_untracked().generic_const_exprs; + if !feature_active { + feature_err( + &self.r.session.parse_sess, + sym::generic_const_exprs, + lifetime_ref.ident.span, + "a non-static lifetime is not allowed in a `const`", + ) + .emit(); + } + } } impl<'tcx> LifetimeContext<'_, 'tcx> { @@ -1984,24 +2013,6 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { } } - // FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const - // generics. We are disallowing this until we can decide on how we want to handle non-'static - // lifetimes in const generics. See issue #74052 for discussion. - crate fn emit_non_static_lt_in_const_generic_error(&self, lifetime_ref: &hir::Lifetime) { - let mut err = struct_span_err!( - self.tcx.sess, - lifetime_ref.span, - E0771, - "use of non-static lifetime `{}` in const generic", - lifetime_ref - ); - err.note( - "for more information, see issue #74052 \ - <https://github.com/rust-lang/rust/issues/74052>", - ); - err.emit(); - } - crate fn is_trait_ref_fn_scope(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) -> bool { if let def::Res::Def(_, did) = trait_ref.trait_ref.path.res { if [ @@ -2403,32 +2414,4 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { _ => unreachable!(), } } - - /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`. - /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by - /// `body_id` is an anonymous constant and `lifetime_ref` is non-static. - crate fn maybe_emit_forbidden_non_static_lifetime_error( - &self, - body_id: hir::BodyId, - lifetime_ref: &'tcx hir::Lifetime, - ) { - let is_anon_const = matches!( - self.tcx.def_kind(self.tcx.hir().body_owner_def_id(body_id)), - hir::def::DefKind::AnonConst - ); - let is_allowed_lifetime = matches!( - lifetime_ref.name, - hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore - ); - - if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime { - feature_err( - &self.tcx.sess.parse_sess, - sym::generic_const_exprs, - lifetime_ref.span, - "a non-static lifetime is not allowed in a `const`", - ) - .emit(); - } - } } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index d5f2e2db1e3..787536d2a38 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -164,8 +164,6 @@ crate struct LifetimeContext<'a, 'tcx> { map: &'a mut NamedRegionMap, scope: ScopeRef<'a>, - is_in_const_generic: bool, - /// Indicates that we only care about the definition of a trait. This should /// be false if the `Item` we are resolving lifetimes for is not a trait or /// we eventually need lifetimes resolve for trait items. @@ -452,7 +450,6 @@ fn do_resolve( tcx, map: &mut named_region_map, scope: ROOT_SCOPE, - is_in_const_generic: false, trait_definition_only, labels_in_fn: vec![], xcrate_object_lifetime_defaults: Default::default(), @@ -685,8 +682,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { hir_id: hir::HirId, ) { let name = match fk { - intravisit::FnKind::ItemFn(id, _, _, _) => id.name, - intravisit::FnKind::Method(id, _, _) => id.name, + intravisit::FnKind::ItemFn(id, _, _) => id.name, + intravisit::FnKind::Method(id, _) => id.name, intravisit::FnKind::Closure => sym::closure, }; let name = name.as_str(); @@ -1266,10 +1263,6 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.insert_lifetime(lifetime_ref, Region::Static); return; } - if self.is_in_const_generic && lifetime_ref.name != LifetimeName::Error { - self.emit_non_static_lt_in_const_generic_error(lifetime_ref); - return; - } self.resolve_lifetime_ref(lifetime_ref); } @@ -1335,24 +1328,19 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { match param.kind { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { ref default, .. } => { - walk_list!(this, visit_param_bound, param.bounds); if let Some(ref ty) = default { this.visit_ty(&ty); } } GenericParamKind::Const { ref ty, default } => { - let was_in_const_generic = this.is_in_const_generic; - this.is_in_const_generic = true; - walk_list!(this, visit_param_bound, param.bounds); this.visit_ty(&ty); if let Some(default) = default { this.visit_body(this.tcx.hir().body(default.body)); } - this.is_in_const_generic = was_in_const_generic; } } } - for predicate in generics.where_clause.predicates { + for predicate in generics.predicates { match predicate { &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { ref bounded_ty, @@ -1403,6 +1391,32 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }) => { this.visit_lifetime(lifetime); walk_list!(this, visit_param_bound, bounds); + + if lifetime.name != hir::LifetimeName::Static { + for bound in bounds { + let hir::GenericBound::Outlives(ref lt) = bound else { + continue; + }; + if lt.name != hir::LifetimeName::Static { + continue; + } + this.insert_lifetime(lt, Region::Static); + this.tcx + .sess + .struct_span_warn( + lifetime.span, + &format!( + "unnecessary lifetime parameter `{}`", + lifetime.name.ident(), + ), + ) + .help(&format!( + "you can use the `'static` lifetime directly, in place of `{}`", + lifetime.name.ident(), + )) + .emit(); + } + } } &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { ref lhs_ty, @@ -1724,10 +1738,8 @@ fn object_lifetime_defaults_for_item<'tcx>( GenericParamKind::Type { .. } => { let mut set = Set1::Empty; - add_bounds(&mut set, ¶m.bounds); - let param_def_id = tcx.hir().local_def_id(param.hir_id); - for predicate in generics.where_clause.predicates { + for predicate in generics.predicates { // Look for `type: ...` where clauses. let hir::WherePredicate::BoundPredicate(ref data) = *predicate else { continue }; @@ -1798,7 +1810,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { tcx: *tcx, map, scope: &wrap_scope, - is_in_const_generic: self.is_in_const_generic, trait_definition_only: self.trait_definition_only, labels_in_fn, xcrate_object_lifetime_defaults, @@ -2254,10 +2265,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let result = loop { match *scope { Scope::Body { id, s } => { - // Non-static lifetimes are prohibited in anonymous constants without - // `generic_const_exprs`. - self.maybe_emit_forbidden_non_static_lifetime_error(id, lifetime_ref); - outermost_body = Some(id); scope = s; } @@ -3139,50 +3146,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // It is a soft error to shadow a lifetime within a parent scope. self.check_lifetime_param_for_shadowing(old_scope, &lifetime_i); - - for bound in lifetime_i.bounds { - match bound { - hir::GenericBound::Outlives(ref lt) => match lt.name { - hir::LifetimeName::Underscore => { - self.tcx.sess.delay_span_bug( - lt.span, - "use of `'_` in illegal place, but not caught by lowering", - ); - } - hir::LifetimeName::Static => { - self.insert_lifetime(lt, Region::Static); - self.tcx - .sess - .struct_span_warn( - lifetime_i.span.to(lt.span), - &format!( - "unnecessary lifetime parameter `{}`", - lifetime_i.name.ident(), - ), - ) - .help(&format!( - "you can use the `'static` lifetime directly, in place of `{}`", - lifetime_i.name.ident(), - )) - .emit(); - } - hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => { - self.resolve_lifetime_ref(lt); - } - hir::LifetimeName::ImplicitObjectLifetimeDefault => { - self.tcx.sess.delay_span_bug( - lt.span, - "lowering generated `ImplicitObjectLifetimeDefault` \ - outside of an object type", - ); - } - hir::LifetimeName::Error => { - // No need to do anything, error already reported. - } - }, - _ => bug!(), - } - } } } @@ -3341,18 +3304,6 @@ fn insert_late_bound_lifetimes( // ignore binders here and scrape up all names we see. let mut appears_in_where_clause = AllCollector::default(); appears_in_where_clause.visit_generics(generics); - - for param in generics.params { - if let hir::GenericParamKind::Lifetime { .. } = param.kind { - if !param.bounds.is_empty() { - // `'a: 'b` means both `'a` and `'b` are referenced - appears_in_where_clause - .regions - .insert(hir::LifetimeName::Param(param.name.normalize_to_macros_2_0())); - } - } - } - debug!(?appears_in_where_clause.regions); // Late bound regions are those that: diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4dfb7aef86f..92e55a0ccb2 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -29,7 +29,7 @@ use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID}; use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path}; -use rustc_ast_lowering::ResolverAstLowering; +use rustc_ast_lowering::{LifetimeRes, ResolverAstLowering}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; @@ -143,9 +143,9 @@ enum ScopeSet<'a> { /// but not for late resolution yet. #[derive(Clone, Copy, Debug)] pub struct ParentScope<'a> { - module: Module<'a>, + pub module: Module<'a>, expansion: LocalExpnId, - macro_rules: MacroRulesScopeRef<'a>, + pub macro_rules: MacroRulesScopeRef<'a>, derives: &'a [ast::Path], } @@ -201,13 +201,13 @@ enum ResolutionError<'a> { /// parameter list. NameAlreadyUsedInParameterList(Symbol, Span), /// Error E0407: method is not a member of trait. - MethodNotMemberOfTrait(Ident, &'a str, Option<Symbol>), + MethodNotMemberOfTrait(Ident, String, Option<Symbol>), /// Error E0437: type is not a member of trait. - TypeNotMemberOfTrait(Ident, &'a str, Option<Symbol>), + TypeNotMemberOfTrait(Ident, String, Option<Symbol>), /// Error E0438: const is not a member of trait. - ConstNotMemberOfTrait(Ident, &'a str, Option<Symbol>), + ConstNotMemberOfTrait(Ident, String, Option<Symbol>), /// Error E0408: variable `{}` is not bound in all patterns. - VariableNotBoundInPattern(&'a BindingError), + VariableNotBoundInPattern(BindingError, ParentScope<'a>), /// Error E0409: variable `{}` is bound in inconsistent ways within the same match arm. VariableBoundWithDifferentMode(Symbol, Span), /// Error E0415: identifier is bound more than once in this parameter list. @@ -901,6 +901,10 @@ pub struct Resolver<'a> { import_res_map: NodeMap<PerNS<Option<Res>>>, /// Resolutions for labels (node IDs of their corresponding blocks or loops). label_res_map: NodeMap<NodeId>, + /// Resolutions for lifetimes. + lifetimes_res_map: NodeMap<LifetimeRes>, + /// Lifetime parameters that lowering will have to introduce. + extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>>, /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: FxHashMap<LocalDefId, CrateNum>, @@ -934,6 +938,7 @@ pub struct Resolver<'a> { glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, /// Visibilities in "lowered" form, for all entities that have them. visibilities: FxHashMap<LocalDefId, ty::Visibility>, + has_pub_restricted: bool, used_imports: FxHashSet<NodeId>, maybe_unused_trait_imports: FxHashSet<LocalDefId>, maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, @@ -985,6 +990,8 @@ pub struct Resolver<'a> { /// `macro_rules` scopes *produced* by expanding the macro invocations, /// include all the `macro_rules` items and other invocations generated by them. output_macro_rules_scopes: FxHashMap<LocalExpnId, MacroRulesScopeRef<'a>>, + /// `macro_rules` scopes produced by `macro_rules` item definitions. + macro_rules_scopes: FxHashMap<LocalDefId, MacroRulesScopeRef<'a>>, /// Helper attributes that are in scope for the given expansion. helper_attrs: FxHashMap<LocalExpnId, Vec<Ident>>, /// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute @@ -1153,6 +1160,14 @@ impl ResolverAstLowering for Resolver<'_> { self.label_res_map.get(&id).cloned() } + fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes> { + self.lifetimes_res_map.get(&id).copied() + } + + fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> { + self.extra_lifetime_params_map.remove(&id).unwrap_or_default() + } + fn create_stable_hashing_context(&self) -> StableHashingContext<'_> { StableHashingContext::new(self.session, &self.definitions, self.crate_loader.cstore()) } @@ -1301,6 +1316,8 @@ impl<'a> Resolver<'a> { partial_res_map: Default::default(), import_res_map: Default::default(), label_res_map: Default::default(), + lifetimes_res_map: Default::default(), + extra_lifetime_params_map: Default::default(), extern_crate_map: Default::default(), reexport_map: FxHashMap::default(), trait_map: NodeMap::default(), @@ -1313,6 +1330,7 @@ impl<'a> Resolver<'a> { glob_map: Default::default(), visibilities, + has_pub_restricted: false, used_imports: FxHashSet::default(), maybe_unused_trait_imports: Default::default(), maybe_unused_extern_crates: Vec::new(), @@ -1345,6 +1363,7 @@ impl<'a> Resolver<'a> { non_macro_attr: Lrc::new(SyntaxExtension::non_macro_attr(session.edition())), invocation_parent_scopes: Default::default(), output_macro_rules_scopes: Default::default(), + macro_rules_scopes: Default::default(), helper_attrs: Default::default(), derive_data: Default::default(), local_macro_def_scopes: FxHashMap::default(), @@ -1423,6 +1442,7 @@ impl<'a> Resolver<'a> { let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect(); let definitions = self.definitions; let visibilities = self.visibilities; + let has_pub_restricted = self.has_pub_restricted; let extern_crate_map = self.extern_crate_map; let reexport_map = self.reexport_map; let maybe_unused_trait_imports = self.maybe_unused_trait_imports; @@ -1435,6 +1455,7 @@ impl<'a> Resolver<'a> { definitions, cstore: Box::new(self.crate_loader.into_cstore()), visibilities, + has_pub_restricted, access_levels, extern_crate_map, reexport_map, @@ -1461,6 +1482,7 @@ impl<'a> Resolver<'a> { access_levels: self.access_levels.clone(), cstore: Box::new(self.cstore().clone()), visibilities: self.visibilities.clone(), + has_pub_restricted: self.has_pub_restricted, extern_crate_map: self.extern_crate_map.clone(), reexport_map: self.reexport_map.clone(), glob_map: self.glob_map.clone(), @@ -1855,25 +1877,25 @@ impl<'a> Resolver<'a> { &mut self, path_str: &str, ns: Namespace, - mut module_id: DefId, + mut parent_scope: ParentScope<'a>, ) -> Option<Res> { let mut segments = Vec::from_iter(path_str.split("::").map(Ident::from_str).map(Segment::from_ident)); if let Some(segment) = segments.first_mut() { if segment.ident.name == kw::Crate { // FIXME: `resolve_path` always resolves `crate` to the current crate root, but - // rustdoc wants it to resolve to the `module_id`'s crate root. This trick of + // rustdoc wants it to resolve to the `parent_scope`'s crate root. This trick of // replacing `crate` with `self` and changing the current module should achieve // the same effect. segment.ident.name = kw::SelfLower; - module_id = module_id.krate.as_def_id(); + parent_scope.module = + self.expect_module(parent_scope.module.def_id().krate.as_def_id()); } else if segment.ident.name == kw::Empty { segment.ident.name = kw::PathRoot; } } - let module = self.expect_module(module_id); - match self.maybe_resolve_path(&segments, Some(ns), &ParentScope::module(module, self)) { + match self.maybe_resolve_path(&segments, Some(ns), &parent_scope) { PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()), PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => { Some(path_res.base_res()) @@ -1886,11 +1908,6 @@ impl<'a> Resolver<'a> { } // For rustdoc. - pub fn graph_root(&self) -> Module<'a> { - self.graph_root - } - - // For rustdoc. pub fn take_all_macro_rules(&mut self) -> FxHashMap<Symbol, Res> { mem::take(&mut self.all_macro_rules) } @@ -1905,6 +1922,11 @@ impl<'a> Resolver<'a> { } } + /// For rustdoc. + pub fn macro_rules_scope(&self, def_id: LocalDefId) -> MacroRulesScopeRef<'a> { + *self.macro_rules_scopes.get(&def_id).expect("not a `macro_rules` item") + } + /// Retrieves the span of the given `DefId` if `DefId` is in the local crate. #[inline] pub fn opt_span(&self, def_id: DefId) -> Option<Span> { @@ -2025,42 +2047,27 @@ fn module_to_string(module: Module<'_>) -> Option<String> { } #[derive(Copy, Clone, Debug)] -enum Finalize { - /// Do not issue the lint. - No, - - /// This lint applies to some arbitrary path; e.g., `impl ::foo::Bar`. - /// In this case, we can take the span of that path. - SimplePath(NodeId, Span), - - /// This lint comes from a `use` statement. In this case, what we - /// care about really is the *root* `use` statement; e.g., if we - /// have nested things like `use a::{b, c}`, we care about the - /// `use a` part. - UsePath { root_id: NodeId, root_span: Span, path_span: Span }, - - /// This is the "trait item" from a fully qualified path. For example, - /// we might be resolving `X::Y::Z` from a path like `<T as X::Y>::Z`. - /// The `path_span` is the span of the to the trait itself (`X::Y`). - QPathTrait { qpath_id: NodeId, qpath_span: Span, path_span: Span }, +struct Finalize { + /// Node ID for linting. + node_id: NodeId, + /// Span of the whole path or some its characteristic fragment. + /// E.g. span of `b` in `foo::{a, b, c}`, or full span for regular paths. + path_span: Span, + /// Span of the path start, suitable for prepending something to to it. + /// E.g. span of `foo` in `foo::{a, b, c}`, or full span for regular paths. + root_span: Span, + /// Whether to report privacy errors or silently return "no resolution" for them, + /// similarly to speculative resolution. + report_private: bool, } impl Finalize { - fn node_id_and_path_span(&self) -> Option<(NodeId, Span)> { - match *self { - Finalize::No => None, - Finalize::SimplePath(id, path_span) - | Finalize::UsePath { root_id: id, path_span, .. } - | Finalize::QPathTrait { qpath_id: id, path_span, .. } => Some((id, path_span)), - } - } - - fn node_id(&self) -> Option<NodeId> { - self.node_id_and_path_span().map(|(id, _)| id) + fn new(node_id: NodeId, path_span: Span) -> Finalize { + Finalize::with_root_span(node_id, path_span, path_span) } - fn path_span(&self) -> Option<Span> { - self.node_id_and_path_span().map(|(_, path_span)| path_span) + fn with_root_span(node_id: NodeId, path_span: Span, root_span: Span) -> Finalize { + Finalize { node_id, path_span, root_span, report_private: true } } } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 01f0b11f1ac..19a9c1b99fc 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -604,7 +604,6 @@ impl<'a> Resolver<'a> { parent_scope, None, force, - false, None, ); if let Err(Determinacy::Undetermined) = binding { @@ -673,7 +672,7 @@ impl<'a> Resolver<'a> { &path, Some(MacroNS), &parent_scope, - Finalize::SimplePath(ast::CRATE_NODE_ID, path_span), + Some(Finalize::new(ast::CRATE_NODE_ID, path_span)), None, ) { PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => { @@ -708,9 +707,8 @@ impl<'a> Resolver<'a> { ident, ScopeSet::Macro(kind), &parent_scope, - Some(ident.span), + Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)), true, - false, None, ) { Ok(binding) => { @@ -751,9 +749,8 @@ impl<'a> Resolver<'a> { ident, ScopeSet::Macro(MacroKind::Attr), &parent_scope, - Some(ident.span), + Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)), true, - false, None, ); } |
