diff options
Diffstat (limited to 'compiler/rustc_resolve/src')
| -rw-r--r-- | compiler/rustc_resolve/src/build_reduced_graph.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/ident.rs | 66 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 79 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 110 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/macros.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/rustdoc.rs | 75 |
7 files changed, 255 insertions, 113 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 127bec22c17..476b5f733a6 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -870,10 +870,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let imported_binding = self.r.import(binding, import); if parent == self.r.graph_root { if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) { - if expansion != LocalExpnId::ROOT - && orig_name.is_some() - && entry.extern_crate_item.is_none() - { + if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() { let msg = "macro-expanded `extern crate` items cannot \ shadow names passed with `--extern`"; self.r.tcx.sess.span_err(item.span, msg); @@ -884,10 +881,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { return; } } - let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert( - ExternPreludeEntry { extern_crate_item: None, introduced_by_item: true }, - ); - entry.extern_crate_item = Some(imported_binding); + let entry = self + .r + .extern_prelude + .entry(ident.normalize_to_macros_2_0()) + .or_insert(ExternPreludeEntry { binding: None, introduced_by_item: true }); + // Binding from `extern crate` item in source code can replace + // a binding from `--extern` on command line here. + entry.binding = Some(imported_binding); if orig_name.is_some() { entry.introduced_by_item = true; } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index cd1a9b934cf..d99fc07a7cd 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1032,7 +1032,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .get(&expn_id) .into_iter() .flatten() - .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)), + .map(|(ident, _)| TypoSuggestion::typo_from_ident(*ident, res)), ); } } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 3bd9cea27ce..61e05b65f90 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1,7 +1,5 @@ use rustc_ast::{self as ast, NodeId}; -use rustc_feature::is_builtin_attr_name; use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS}; -use rustc_hir::PrimTy; use rustc_middle::bug; use rustc_middle::ty; use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; @@ -9,7 +7,7 @@ use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext}; use rustc_span::symbol::{kw, Ident}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; use crate::late::{ @@ -423,32 +421,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { orig_ident.span.ctxt(), |this, scope, use_prelude, ctxt| { let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt)); - let ok = |res, span, arenas| { - Ok(( - (res, Visibility::Public, span, LocalExpnId::ROOT).to_name_binding(arenas), - Flags::empty(), - )) - }; let result = match scope { Scope::DeriveHelpers(expn_id) => { - if let Some(attr) = this - .helper_attrs - .get(&expn_id) - .and_then(|attrs| attrs.iter().rfind(|i| ident == **i)) - { - let binding = ( - Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper), - Visibility::Public, - attr.span, - expn_id, - ) - .to_name_binding(this.arenas); + if let Some(binding) = this.helper_attrs.get(&expn_id).and_then(|attrs| { + attrs.iter().rfind(|(i, _)| ident == *i).map(|(_, binding)| *binding) + }) { Ok((binding, Flags::empty())) } else { Err(Determinacy::Determined) } } Scope::DeriveHelpersCompat => { + // FIXME: Try running this logic eariler, to allocate name bindings for + // legacy derive helpers when creating an attribute invocation with + // following derives. Legacy derive helpers are not common, so it shouldn't + // affect performance. It should also allow to remove the `derives` + // component from `ParentScope`. let mut result = Err(Determinacy::Determined); for derive in parent_scope.derives { let parent_scope = &ParentScope { derives: &[], ..*parent_scope }; @@ -461,11 +449,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) { Ok((Some(ext), _)) => { if ext.helper_attrs.contains(&ident.name) { - result = ok( + let binding = ( Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat), + Visibility::Public, derive.span, - this.arenas, - ); + LocalExpnId::ROOT, + ) + .to_name_binding(this.arenas); + result = Ok((binding, Flags::empty())); break; } } @@ -562,17 +553,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { )), } } - Scope::BuiltinAttrs => { - if is_builtin_attr_name(ident.name) { - ok( - Res::NonMacroAttr(NonMacroAttrKind::Builtin(ident.name)), - DUMMY_SP, - this.arenas, - ) - } else { - Err(Determinacy::Determined) - } - } + Scope::BuiltinAttrs => match this.builtin_attrs_bindings.get(&ident.name) { + Some(binding) => Ok((*binding, Flags::empty())), + None => Err(Determinacy::Determined), + }, Scope::ExternPrelude => { match this.extern_prelude_get(ident, finalize.is_some()) { Some(binding) => Ok((binding, Flags::empty())), @@ -581,8 +565,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { )), } } - Scope::ToolPrelude => match this.registered_tools.get(&ident).cloned() { - Some(ident) => ok(Res::ToolMod, ident.span, this.arenas), + Scope::ToolPrelude => match this.registered_tool_bindings.get(&ident) { + Some(binding) => Ok((*binding, Flags::empty())), None => Err(Determinacy::Determined), }, Scope::StdLibPrelude => { @@ -603,8 +587,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } result } - Scope::BuiltinTypes => match PrimTy::from_name(ident.name) { - Some(prim_ty) => ok(Res::PrimTy(prim_ty), DUMMY_SP, this.arenas), + Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) { + Some(binding) => Ok((*binding, Flags::empty())), None => Err(Determinacy::Determined), }, }; @@ -842,9 +826,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if ns == TypeNS { if ident.name == kw::Crate || ident.name == kw::DollarCrate { let module = self.resolve_crate_root(ident); - let binding = (module, Visibility::Public, module.span, LocalExpnId::ROOT) - .to_name_binding(self.arenas); - return Ok(binding); + return Ok(self.module_self_bindings[&module]); } 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. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index c87db96a5dd..22d084c8e0b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -311,6 +311,10 @@ enum LifetimeRibKind { /// error on default object bounds (e.g., `Box<dyn Foo>`). AnonymousReportError, + /// Resolves elided lifetimes to `'static`, but gives a warning that this behavior + /// is a bug and will be reverted soon. + AnonymousWarnToStatic(NodeId), + /// Signal we cannot find which should be the anonymous lifetime. ElisionFailure, @@ -1148,6 +1152,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } LifetimeRibKind::AnonymousCreateParameter { .. } | LifetimeRibKind::AnonymousReportError + | LifetimeRibKind::AnonymousWarnToStatic(_) | LifetimeRibKind::Elided(_) | LifetimeRibKind::ElisionFailure | LifetimeRibKind::ConcreteAnonConst(_) @@ -1515,6 +1520,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // lifetime would be illegal. LifetimeRibKind::Item | LifetimeRibKind::AnonymousReportError + | LifetimeRibKind::AnonymousWarnToStatic(_) | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many), // An anonymous lifetime is legal here, and bound to the right // place, go ahead. @@ -1576,7 +1582,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { | LifetimeRibKind::Elided(_) | LifetimeRibKind::Generics { .. } | LifetimeRibKind::ElisionFailure - | LifetimeRibKind::AnonymousReportError => {} + | LifetimeRibKind::AnonymousReportError + | LifetimeRibKind::AnonymousWarnToStatic(_) => {} } } @@ -1616,6 +1623,25 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { self.record_lifetime_res(lifetime.id, res, elision_candidate); return; } + LifetimeRibKind::AnonymousWarnToStatic(node_id) => { + self.record_lifetime_res(lifetime.id, LifetimeRes::Static, elision_candidate); + let msg = if elided { + "`&` without an explicit lifetime name cannot be used here" + } else { + "`'_` cannot be used here" + }; + self.r.lint_buffer.buffer_lint_with_diagnostic( + lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT, + node_id, + lifetime.ident.span, + msg, + lint::BuiltinLintDiagnostics::AssociatedConstElidedLifetime { + elided, + span: lifetime.ident.span, + }, + ); + return; + } LifetimeRibKind::AnonymousReportError => { let (msg, note) = if elided { ( @@ -1811,7 +1837,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // // impl Foo for std::cell::Ref<u32> // note lack of '_ // async fn foo(_: std::cell::Ref<u32>) { ... } - LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } => { + LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } + | LifetimeRibKind::AnonymousWarnToStatic(_) => { let sess = self.r.tcx.sess; let mut err = rustc_errors::struct_span_err!( sess, @@ -2898,7 +2925,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { match &item.kind { AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => { debug!("resolve_implementation AssocItemKind::Const"); - self.with_generic_param_rib( &generics.params, RibKind::AssocItem, @@ -2908,28 +2934,33 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { kind: LifetimeBinderKind::ConstItem, }, |this| { - // If this is a trait impl, ensure the const - // exists in trait - this.check_trait_item( - item.id, - item.ident, - &item.kind, - ValueNS, - item.span, - seen_trait_items, - |i, s, c| ConstNotMemberOfTrait(i, s, c), - ); + this.with_lifetime_rib( + LifetimeRibKind::AnonymousWarnToStatic(item.id), + |this| { + // If this is a trait impl, ensure the const + // exists in trait + this.check_trait_item( + item.id, + item.ident, + &item.kind, + ValueNS, + item.span, + seen_trait_items, + |i, s, c| ConstNotMemberOfTrait(i, s, c), + ); - this.visit_generics(generics); - this.visit_ty(ty); - if let Some(expr) = expr { - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_body(expr, None); - } + this.visit_generics(generics); + this.visit_ty(ty); + if let Some(expr) = expr { + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_body(expr, None); + } + }, + ); }, ); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 76e54e60d14..6d3a1d69ef0 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -18,7 +18,7 @@ #![recursion_limit = "256"] #![allow(rustdoc::private_intra_doc_links)] #![allow(rustc::potential_query_instability)] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![allow(internal_features)] #[macro_use] extern crate tracing; @@ -39,13 +39,15 @@ use rustc_errors::{ Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, SubdiagnosticMessage, }; use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; +use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_fluent_macro::fluent_messages; use rustc_hir::def::Namespace::{self, *}; +use rustc_hir::def::NonMacroAttrKind; use rustc_hir::def::{self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, PartialRes, PerNS}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap, LocalDefIdSet}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::DefPathData; -use rustc_hir::TraitCandidate; +use rustc_hir::{PrimTy, TraitCandidate}; use rustc_index::IndexVec; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_middle::metadata::ModChild; @@ -517,7 +519,7 @@ struct ModuleData<'a> { /// All modules are unique and allocated on a same arena, /// so we can use referential equality to compare them. -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] #[rustc_pass_by_value] struct Module<'a>(Interned<'a, ModuleData<'a>>); @@ -883,10 +885,16 @@ impl<'a> NameBindingData<'a> { #[derive(Default, Clone)] struct ExternPreludeEntry<'a> { - extern_crate_item: Option<NameBinding<'a>>, + binding: Option<NameBinding<'a>>, introduced_by_item: bool, } +impl ExternPreludeEntry<'_> { + fn is_import(&self) -> bool { + self.binding.is_some_and(|binding| binding.is_import()) + } +} + /// Used for better errors for E0773 enum BuiltinMacroState { NotYetSeen(SyntaxExtensionKind), @@ -996,6 +1004,12 @@ pub struct Resolver<'a, 'tcx> { arenas: &'a ResolverArenas<'a>, dummy_binding: NameBinding<'a>, + builtin_types_bindings: FxHashMap<Symbol, NameBinding<'a>>, + builtin_attrs_bindings: FxHashMap<Symbol, NameBinding<'a>>, + registered_tool_bindings: FxHashMap<Ident, NameBinding<'a>>, + /// Binding for implicitly declared names that come with a module, + /// like `self` (not yet used), or `crate`/`$crate` (for root modules). + module_self_bindings: FxHashMap<Module<'a>, NameBinding<'a>>, used_extern_options: FxHashSet<Symbol>, macro_names: FxHashSet<Ident>, @@ -1033,7 +1047,7 @@ pub struct Resolver<'a, 'tcx> { /// `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>>, + helper_attrs: FxHashMap<LocalExpnId, Vec<(Ident, NameBinding<'a>)>>, /// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute /// with the given `ExpnId`. derive_data: FxHashMap<LocalExpnId, DeriveData>, @@ -1111,6 +1125,7 @@ impl<'a> ResolverArenas<'a> { span: Span, no_implicit_prelude: bool, module_map: &mut FxHashMap<DefId, Module<'a>>, + module_self_bindings: &mut FxHashMap<Module<'a>, NameBinding<'a>>, ) -> Module<'a> { let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new( parent, @@ -1125,6 +1140,9 @@ impl<'a> ResolverArenas<'a> { } if let Some(def_id) = def_id { module_map.insert(def_id, module); + let vis = ty::Visibility::<DefId>::Public; + let binding = (module, vis, module.span, LocalExpnId::ROOT).to_name_binding(self); + module_self_bindings.insert(module, binding); } module } @@ -1236,6 +1254,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) -> Resolver<'a, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); let mut module_map = FxHashMap::default(); + let mut module_self_bindings = FxHashMap::default(); let graph_root = arenas.new_module( None, ModuleKind::Def(DefKind::Mod, root_def_id, kw::Empty), @@ -1243,6 +1262,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { crate_span, attr::contains_name(attrs, sym::no_implicit_prelude), &mut module_map, + &mut module_self_bindings, ); let empty_module = arenas.new_module( None, @@ -1251,6 +1271,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { DUMMY_SP, true, &mut FxHashMap::default(), + &mut FxHashMap::default(), ); let mut visibilities = FxHashMap::default(); @@ -1283,6 +1304,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let registered_tools = tcx.registered_tools(()); let features = tcx.features(); + let pub_vis = ty::Visibility::<DefId>::Public; let mut resolver = Resolver { tcx, @@ -1330,14 +1352,33 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { macro_expanded_macro_export_errors: BTreeSet::new(), arenas, - dummy_binding: arenas.alloc_name_binding(NameBindingData { - kind: NameBindingKind::Res(Res::Err), - ambiguity: None, - warn_ambiguity: false, - expansion: LocalExpnId::ROOT, - span: DUMMY_SP, - vis: ty::Visibility::Public, - }), + dummy_binding: (Res::Err, pub_vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(arenas), + builtin_types_bindings: PrimTy::ALL + .iter() + .map(|prim_ty| { + let binding = (Res::PrimTy(*prim_ty), pub_vis, DUMMY_SP, LocalExpnId::ROOT) + .to_name_binding(arenas); + (prim_ty.name(), binding) + }) + .collect(), + builtin_attrs_bindings: BUILTIN_ATTRIBUTES + .iter() + .map(|builtin_attr| { + let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(builtin_attr.name)); + let binding = + (res, pub_vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(arenas); + (builtin_attr.name, binding) + }) + .collect(), + registered_tool_bindings: registered_tools + .iter() + .map(|ident| { + let binding = (Res::ToolMod, pub_vis, ident.span, LocalExpnId::ROOT) + .to_name_binding(arenas); + (*ident, binding) + }) + .collect(), + module_self_bindings, used_extern_options: Default::default(), macro_names: FxHashSet::default(), @@ -1407,7 +1448,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { no_implicit_prelude: bool, ) -> Module<'a> { let module_map = &mut self.module_map; - self.arenas.new_module(parent, kind, expn_id, span, no_implicit_prelude, module_map) + let module_self_bindings = &mut self.module_self_bindings; + self.arenas.new_module( + parent, + kind, + expn_id, + span, + no_implicit_prelude, + module_map, + module_self_bindings, + ) } fn next_node_id(&mut self) -> NodeId { @@ -1727,7 +1777,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // but not introduce it, as used if they are accessed from lexical scope. if is_lexical_scope { if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) { - if !entry.introduced_by_item && entry.extern_crate_item == Some(used_binding) { + if !entry.introduced_by_item && entry.binding == Some(used_binding) { return; } } @@ -1885,12 +1935,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Make sure `self`, `super` etc produce an error when passed to here. return None; } - self.extern_prelude.get(&ident.normalize_to_macros_2_0()).cloned().and_then(|entry| { - if let Some(binding) = entry.extern_crate_item { - if finalize && entry.introduced_by_item { - self.record_use(ident, binding, false); + + let norm_ident = ident.normalize_to_macros_2_0(); + let binding = self.extern_prelude.get(&norm_ident).cloned().and_then(|entry| { + Some(if let Some(binding) = entry.binding { + if finalize { + if !entry.is_import() { + self.crate_loader(|c| c.process_path_extern(ident.name, ident.span)); + } else if entry.introduced_by_item { + self.record_use(ident, binding, false); + } } - Some(binding) + binding } else { let crate_id = if finalize { let Some(crate_id) = @@ -1903,10 +1959,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.crate_loader(|c| c.maybe_process_path_extern(ident.name))? }; let crate_root = self.expect_module(crate_id.as_def_id()); - let vis = ty::Visibility::<LocalDefId>::Public; - Some((crate_root, vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(self.arenas)) - } - }) + let vis = ty::Visibility::<DefId>::Public; + (crate_root, vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(self.arenas) + }) + }); + + if let Some(entry) = self.extern_prelude.get_mut(&norm_ident) { + entry.binding = binding; + } + + binding } /// Rustdoc uses this to resolve doc link paths in a recoverable way. `PathResult<'a>` diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 6a5b675b4bb..1199290a4d1 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -7,7 +7,7 @@ use crate::errors::{ use crate::Namespace::*; use crate::{BuiltinMacroState, Determinacy}; use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, ScopeSet}; -use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment}; +use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; use rustc_ast::expand::StrippedCfgItem; use rustc_ast::{self as ast, attr, Crate, Inline, ItemKind, ModKind, NodeId}; use rustc_ast_pretty::pprust; @@ -20,10 +20,10 @@ use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion}; use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; -use rustc_hir::def_id::{CrateNum, LocalDefId}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_middle::middle::stability; use rustc_middle::ty::RegisteredTools; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{TyCtxt, Visibility}; use rustc_session::lint::builtin::{ LEGACY_DERIVE_HELPERS, SOFT_UNSTABLE, UNKNOWN_DIAGNOSTIC_ATTRIBUTES, }; @@ -401,8 +401,17 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { } // Sort helpers in a stable way independent from the derive resolution order. entry.helper_attrs.sort_by_key(|(i, _)| *i); - self.helper_attrs - .insert(expn_id, entry.helper_attrs.iter().map(|(_, ident)| *ident).collect()); + let helper_attrs = entry + .helper_attrs + .iter() + .map(|(_, ident)| { + let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper); + let binding = (res, Visibility::<DefId>::Public, ident.span, expn_id) + .to_name_binding(self.arenas); + (*ident, binding) + }) + .collect(); + self.helper_attrs.insert(expn_id, helper_attrs); // Mark this derive as having `Copy` either if it has `Copy` itself or if its parent derive // has `Copy`, to support cases like `#[derive(Clone, Copy)] #[derive(Debug)]`. if entry.has_derive_copy || self.has_derive_copy(parent_scope.expansion) { diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index d433391f272..ba7417b6dda 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -1,4 +1,4 @@ -use pulldown_cmark::{BrokenLink, Event, LinkType, Options, Parser, Tag}; +use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, Options, Parser, Tag}; use rustc_ast as ast; use rustc_ast::util::comments::beautify_doc_string; use rustc_data_structures::fx::FxHashMap; @@ -392,16 +392,73 @@ pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<s let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true); let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap(); - Parser::new_with_broken_link_callback( + parse_links(&doc) +} + +/// Similiar version of `markdown_links` from rustdoc. +/// This will collect destination links and display text if exists. +fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> { + let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into())); + let mut event_iter = Parser::new_with_broken_link_callback( &doc, main_body_opts(), - Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))), + Some(&mut broken_link_callback), ) - .filter_map(|event| match event { - Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => { - Some(preprocess_link(&dest)) + .into_iter(); + let mut links = Vec::new(); + + while let Some(event) = event_iter.next() { + match event { + Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => { + if matches!( + link_type, + LinkType::Inline + | LinkType::ReferenceUnknown + | LinkType::Reference + | LinkType::Shortcut + | LinkType::ShortcutUnknown + ) { + if let Some(display_text) = collect_link_data(&mut event_iter) { + links.push(display_text); + } + } + + links.push(preprocess_link(&dest)); + } + _ => {} + } + } + + links +} + +/// Collects additional data of link. +fn collect_link_data<'input, 'callback>( + event_iter: &mut Parser<'input, 'callback>, +) -> Option<Box<str>> { + let mut display_text: Option<String> = None; + let mut append_text = |text: CowStr<'_>| { + if let Some(display_text) = &mut display_text { + display_text.push_str(&text); + } else { + display_text = Some(text.to_string()); + } + }; + + while let Some(event) = event_iter.next() { + match event { + Event::Text(text) => { + append_text(text); + } + Event::Code(code) => { + append_text(code); + } + Event::End(_) => { + break; + } + _ => {} } - _ => None, - }) - .collect() + } + + display_text.map(String::into_boxed_str) } |
