diff options
Diffstat (limited to 'compiler/rustc_resolve')
| -rw-r--r-- | compiler/rustc_resolve/Cargo.toml | 2 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/build_reduced_graph.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/check_unused.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/def_collector.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/diagnostics.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/errors.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/ident.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/imports.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 45 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late/diagnostics.rs | 48 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/lib.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/macros.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/rustdoc.rs | 43 | 
13 files changed, 140 insertions, 67 deletions
| diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index b71853b871d..309227176d4 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -10,7 +10,7 @@ pulldown-cmark = { version = "0.11", features = ["html"], default-features = fal rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_attr = { path = "../rustc_attr" } +rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 924b8afa329..3fe1eed243f 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -12,7 +12,7 @@ use rustc_ast::{ self as ast, AssocItem, AssocItemKind, Block, ForeignItem, ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StmtKind, }; -use rustc_attr as attr; +use rustc_attr_parsing as attr; use rustc_data_structures::sync::Lrc; use rustc_expand::base::ResolverExpand; use rustc_expand::expand::AstFragment; @@ -22,9 +22,8 @@ use rustc_metadata::creader::LoadedMacro; use rustc_middle::metadata::ModChild; use rustc_middle::ty::Feed; use rustc_middle::{bug, ty}; -use rustc_span::Span; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; -use rustc_span::symbol::{Ident, Symbol, kw, sym}; +use rustc_span::{Ident, Span, Symbol, kw, sym}; use tracing::debug; use crate::Namespace::{MacroNS, TypeNS, ValueNS}; @@ -634,7 +633,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } ast::UseTreeKind::Glob => { let kind = ImportKind::Glob { - is_prelude: attr::contains_name(&item.attrs, sym::prelude_import), + is_prelude: ast::attr::contains_name(&item.attrs, sym::prelude_import), max_vis: Cell::new(None), id, }; @@ -777,7 +776,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { expansion.to_expn_id(), item.span, parent.no_implicit_prelude - || attr::contains_name(&item.attrs, sym::no_implicit_prelude), + || ast::attr::contains_name(&item.attrs, sym::no_implicit_prelude), ); self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion)); @@ -835,7 +834,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // If the structure is marked as non_exhaustive then lower the visibility // to within the crate. let mut ctor_vis = if vis.is_public() - && attr::contains_name(&item.attrs, sym::non_exhaustive) + && ast::attr::contains_name(&item.attrs, sym::non_exhaustive) { ty::Visibility::Restricted(CRATE_DEF_ID) } else { @@ -1176,11 +1175,11 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } fn proc_macro_stub(&self, item: &ast::Item) -> Option<(MacroKind, Ident, Span)> { - if attr::contains_name(&item.attrs, sym::proc_macro) { + if ast::attr::contains_name(&item.attrs, sym::proc_macro) { return Some((MacroKind::Bang, item.ident, item.span)); - } else if attr::contains_name(&item.attrs, sym::proc_macro_attribute) { + } else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) { return Some((MacroKind::Attr, item.ident, item.span)); - } else if let Some(attr) = attr::find_by_name(&item.attrs, sym::proc_macro_derive) { + } else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive) { if let Some(meta_item_inner) = attr.meta_item_list().and_then(|list| list.get(0).cloned()) { @@ -1233,7 +1232,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { if macro_rules { let ident = ident.normalize_to_macros_2_0(); self.r.macro_names.insert(ident); - let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export); + let is_macro_export = ast::attr::contains_name(&item.attrs, sym::macro_export); let vis = if is_macro_export { ty::Visibility::Public } else { @@ -1507,7 +1506,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // If the variant is marked as non_exhaustive then lower the visibility to within the crate. let ctor_vis = - if vis.is_public() && attr::contains_name(&variant.attrs, sym::non_exhaustive) { + if vis.is_public() && ast::attr::contains_name(&variant.attrs, sym::non_exhaustive) { ty::Visibility::Restricted(CRATE_DEF_ID) } else { vis diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index e36055e8575..5a605df88c2 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -33,8 +33,7 @@ use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::{ MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS, UNUSED_QUALIFICATIONS, }; -use rustc_span::symbol::{Ident, kw}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::{DUMMY_SP, Ident, Span, kw}; use crate::imports::{Import, ImportKind}; use crate::{LexicalScopeBinding, NameBindingKind, Resolver, module_to_string}; diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 66492842581..87024c487df 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -7,9 +7,8 @@ use rustc_expand::expand::AstFragment; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::def_id::LocalDefId; -use rustc_span::Span; use rustc_span::hygiene::LocalExpnId; -use rustc_span::symbol::{Symbol, kw, sym}; +use rustc_span::{Span, Symbol, kw, sym}; use tracing::debug; use crate::{ImplTraitContext, InvocationParent, Resolver}; @@ -356,6 +355,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { let kind = match self.impl_trait_context { ImplTraitContext::Universal => DefKind::TyParam, ImplTraitContext::Existential => DefKind::OpaqueTy, + ImplTraitContext::InBinding => return visit::walk_ty(self, ty), }; let id = self.create_def(*id, name, kind, ty.span); match self.impl_trait_context { @@ -365,6 +365,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { ImplTraitContext::Existential => { self.with_parent(id, |this| visit::walk_ty(this, ty)) } + ImplTraitContext::InBinding => unreachable!(), }; } _ => visit::walk_ty(self, ty), @@ -374,6 +375,13 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_stmt(&mut self, stmt: &'a Stmt) { match stmt.kind { StmtKind::MacCall(..) => self.visit_macro_invoc(stmt.id), + // FIXME(impl_trait_in_bindings): We don't really have a good way of + // introducing the right `ImplTraitContext` here for all the cases we + // care about, in case we want to introduce ITIB to other positions + // such as turbofishes (e.g. `foo::<impl Fn()>(|| {})`). + StmtKind::Let(ref local) => self.with_impl_trait(ImplTraitContext::InBinding, |this| { + visit::walk_local(this, local) + }), _ => visit::walk_stmt(self, stmt), } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 368eb3c26c7..9795299ed6d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -28,8 +28,7 @@ use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::SourceMap; -use rustc_span::symbol::{Ident, Symbol, kw, sym}; -use rustc_span::{BytePos, Span, SyntaxContext}; +use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym}; use thin_vec::{ThinVec, thin_vec}; use tracing::debug; @@ -2817,11 +2816,11 @@ fn show_candidates( path_strings.sort_by(|a, b| a.0.cmp(&b.0)); path_strings.dedup_by(|a, b| a.0 == b.0); let core_path_strings = - path_strings.extract_if(|p| p.0.starts_with("core::")).collect::<Vec<_>>(); + path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>(); let std_path_strings = - path_strings.extract_if(|p| p.0.starts_with("std::")).collect::<Vec<_>>(); + path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>(); let foreign_crate_path_strings = - path_strings.extract_if(|p| !p.0.starts_with("crate::")).collect::<Vec<_>>(); + path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>(); // We list the `crate` local paths first. // Then we list the `std`/`core` paths. diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 24f5a812a82..3bfe98f7091 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,8 +1,7 @@ use rustc_errors::codes::*; use rustc_errors::{Applicability, ElidedLifetimeInPathSubdiag, MultiSpan}; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_span::Span; -use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::{Ident, Span, Symbol}; use crate::Res; use crate::late::PatternSource; diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 5906a682f3e..45e87edc53e 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -9,8 +9,7 @@ use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK; use rustc_session::parse::feature_err; use rustc_span::def_id::LocalDefId; use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext}; -use rustc_span::symbol::{Ident, kw}; -use rustc_span::{Span, sym}; +use rustc_span::{Ident, Span, kw, sym}; use tracing::{debug, instrument}; use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 2ed3f4d2c4f..5b1d8d622bd 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -17,10 +17,9 @@ use rustc_session::lint::builtin::{ AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS, }; -use rustc_span::Span; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::LocalExpnId; -use rustc_span::symbol::{Ident, Symbol, kw}; +use rustc_span::{Ident, Span, Symbol, kw}; use smallvec::SmallVec; use tracing::debug; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index bde11428d40..7324d3fe786 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -19,7 +19,9 @@ use rustc_ast::visit::{ use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::codes::*; -use rustc_errors::{Applicability, DiagArgValue, IntoDiagArg, StashKey, Suggestions}; +use rustc_errors::{ + Applicability, DiagArgValue, ErrorGuaranteed, IntoDiagArg, StashKey, Suggestions, +}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId}; @@ -31,8 +33,7 @@ use rustc_session::config::{CrateType, ResolveDocLinks}; use rustc_session::lint::{self, BuiltinLintDiag}; use rustc_session::parse::feature_err; use rustc_span::source_map::{Spanned, respan}; -use rustc_span::symbol::{Ident, Symbol, kw, sym}; -use rustc_span::{BytePos, Span, SyntaxContext}; +use rustc_span::{BytePos, Ident, Span, Symbol, SyntaxContext, kw, sym}; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument, trace}; @@ -264,12 +265,17 @@ impl RibKind<'_> { #[derive(Debug)] pub(crate) struct Rib<'ra, R = Res> { pub bindings: IdentMap<R>, + pub patterns_with_skipped_bindings: FxHashMap<DefId, Vec<(Span, Result<(), ErrorGuaranteed>)>>, pub kind: RibKind<'ra>, } impl<'ra, R> Rib<'ra, R> { fn new(kind: RibKind<'ra>) -> Rib<'ra, R> { - Rib { bindings: Default::default(), kind } + Rib { + bindings: Default::default(), + patterns_with_skipped_bindings: Default::default(), + kind, + } } } @@ -3775,6 +3781,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { /// When a whole or-pattern has been dealt with, the thing happens. /// /// See the implementation and `fresh_binding` for more details. + #[tracing::instrument(skip(self, bindings), level = "debug")] fn resolve_pattern_inner( &mut self, pat: &Pat, @@ -3783,7 +3790,6 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ) { // Visit all direct subpatterns of this pattern. pat.walk(&mut |pat| { - debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind); match pat.kind { PatKind::Ident(bmode, ident, ref sub) => { // First try to resolve the identifier as some existing entity, @@ -3809,8 +3815,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { PatKind::Path(ref qself, ref path) => { self.smart_resolve_path(pat.id, qself, path, PathSource::Pat); } - PatKind::Struct(ref qself, ref path, ..) => { + PatKind::Struct(ref qself, ref path, ref _fields, ref rest) => { self.smart_resolve_path(pat.id, qself, path, PathSource::Struct); + self.record_patterns_with_skipped_bindings(pat, rest); } PatKind::Or(ref ps) => { // Add a new set of bindings to the stack. `Or` here records that when a @@ -3843,6 +3850,30 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }); } + fn record_patterns_with_skipped_bindings(&mut self, pat: &Pat, rest: &ast::PatFieldsRest) { + match rest { + ast::PatFieldsRest::Rest | ast::PatFieldsRest::Recovered(_) => { + // Record that the pattern doesn't introduce all the bindings it could. + if let Some(partial_res) = self.r.partial_res_map.get(&pat.id) + && let Some(res) = partial_res.full_res() + && let Some(def_id) = res.opt_def_id() + { + self.ribs[ValueNS] + .last_mut() + .unwrap() + .patterns_with_skipped_bindings + .entry(def_id) + .or_default() + .push((pat.span, match rest { + ast::PatFieldsRest::Recovered(guar) => Err(*guar), + _ => Ok(()), + })); + } + } + ast::PatFieldsRest::None => {} + } + } + fn fresh_binding( &mut self, ident: Ident, @@ -4294,7 +4325,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { #[inline] /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items or - // an invalid `use foo::*;` was found, which can cause unbounded ammounts of "item not found" + // an invalid `use foo::*;` was found, which can cause unbounded amounts of "item not found" // errors. We silence them all. fn should_report_errs(&self) -> bool { !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 09f3e848766..6ee02e9f47f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -27,8 +27,7 @@ use rustc_session::{Session, lint}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; -use rustc_span::symbol::{Ident, Symbol, kw, sym}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use thin_vec::ThinVec; use tracing::debug; @@ -430,6 +429,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut err = self.r.dcx().struct_span_err(base_error.span, base_error.msg.clone()); err.code(code); + self.detect_missing_binding_available_from_pattern(&mut err, path, following_seg); self.suggest_at_operator_in_slice_pat_with_range(&mut err, path); self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span); @@ -628,7 +628,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // Try to filter out intrinsics candidates, as long as we have // some other candidates to suggest. let intrinsic_candidates: Vec<_> = candidates - .extract_if(|sugg| { + .extract_if(.., |sugg| { let path = path_names_to_string(&sugg.path); path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::") }) @@ -1120,6 +1120,48 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { true } + fn detect_missing_binding_available_from_pattern( + &mut self, + err: &mut Diag<'_>, + path: &[Segment], + following_seg: Option<&Segment>, + ) { + let [segment] = path else { return }; + let None = following_seg else { return }; + for rib in self.ribs[ValueNS].iter().rev() { + for (def_id, spans) in &rib.patterns_with_skipped_bindings { + if let Some(fields) = self.r.field_idents(*def_id) { + for field in fields { + if field.name == segment.ident.name { + if spans.iter().all(|(_, had_error)| had_error.is_err()) { + // This resolution error will likely be fixed by fixing a + // syntax error in a pattern, so it is irrelevant to the user. + let multispan: MultiSpan = + spans.iter().map(|(s, _)| *s).collect::<Vec<_>>().into(); + err.span_note( + multispan, + "this pattern had a recovered parse error which likely lost \ + the expected fields", + ); + err.downgrade_to_delayed_bug(); + } + let ty = self.r.tcx.item_name(*def_id); + for (span, _) in spans { + err.span_label( + *span, + format!( + "this pattern doesn't include `{field}`, which is \ + available in `{ty}`", + ), + ); + } + } + } + } + } + } + } + fn suggest_at_operator_in_slice_pat_with_range( &mut self, err: &mut Diag<'_>, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 94adfcd3b91..7b950b97d30 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -70,8 +70,7 @@ use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_session::lint::{BuiltinLintDiag, LintBuffer}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; -use rustc_span::symbol::{Ident, Symbol, kw, sym}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use smallvec::{SmallVec, smallvec}; use tracing::debug; @@ -190,6 +189,7 @@ impl InvocationParent { enum ImplTraitContext { Existential, Universal, + InBinding, } /// Used for tracking import use types which will be used for redundant import checking. diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 669a9c2428f..b24e343c58d 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -4,10 +4,11 @@ use std::cell::Cell; use std::mem; +use rustc_ast::attr::AttributeExt; use rustc_ast::expand::StrippedCfgItem; use rustc_ast::{self as ast, Crate, Inline, ItemKind, ModKind, NodeId, attr}; use rustc_ast_pretty::pprust; -use rustc_attr::StabilityLevel; +use rustc_attr_parsing::StabilityLevel; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, StashKey}; @@ -32,8 +33,7 @@ use rustc_session::parse::feature_err; use rustc_span::edit_distance::edit_distance; use rustc_span::edition::Edition; use rustc_span::hygiene::{self, AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind}; -use rustc_span::symbol::{Ident, Symbol, kw, sym}; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use crate::Namespace::*; use crate::errors::{ @@ -689,8 +689,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && let [namespace, attribute, ..] = &*path.segments && namespace.ident.name == sym::diagnostic && !(attribute.ident.name == sym::on_unimplemented - || (attribute.ident.name == sym::do_not_recommend - && self.tcx.features().do_not_recommend())) + || attribute.ident.name == sym::do_not_recommend) { let distance = edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5); @@ -1126,7 +1125,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &mut self, macro_def: &ast::MacroDef, ident: Ident, - attrs: &[ast::Attribute], + attrs: &[impl AttributeExt], span: Span, node_id: NodeId, edition: Edition, diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index 65128ceb866..84e43d0e016 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -5,12 +5,13 @@ use pulldown_cmark::{ BrokenLink, BrokenLinkCallback, CowStr, Event, LinkType, Options, Parser, Tag, }; use rustc_ast as ast; +use rustc_ast::attr::AttributeExt; use rustc_ast::util::comments::beautify_doc_string; use rustc_data_structures::fx::FxIndexMap; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; -use rustc_span::symbol::{Symbol, kw, sym}; -use rustc_span::{DUMMY_SP, InnerSpan, Span}; +use rustc_span::{DUMMY_SP, InnerSpan, Span, Symbol, kw, sym}; +use thin_vec::ThinVec; use tracing::{debug, trace}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -192,19 +193,24 @@ pub fn add_doc_fragment(out: &mut String, frag: &DocFragment) { } } -pub fn attrs_to_doc_fragments<'a>( - attrs: impl Iterator<Item = (&'a ast::Attribute, Option<DefId>)>, +pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>( + attrs: impl Iterator<Item = (&'a A, Option<DefId>)>, doc_only: bool, -) -> (Vec<DocFragment>, ast::AttrVec) { +) -> (Vec<DocFragment>, ThinVec<A>) { let mut doc_fragments = Vec::new(); - let mut other_attrs = ast::AttrVec::new(); + let mut other_attrs = ThinVec::<A>::new(); for (attr, item_id) in attrs { if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() { let doc = beautify_doc_string(doc_str, comment_kind); let (span, kind) = if attr.is_doc_comment() { - (attr.span, DocFragmentKind::SugaredDoc) + (attr.span(), DocFragmentKind::SugaredDoc) } else { - (span_for_value(attr), DocFragmentKind::RawDoc) + ( + attr.value_span() + .map(|i| i.with_ctxt(attr.span().ctxt())) + .unwrap_or(attr.span()), + DocFragmentKind::RawDoc, + ) }; let fragment = DocFragment { span, doc, kind, item_id, indent: 0 }; doc_fragments.push(fragment); @@ -218,16 +224,6 @@ pub fn attrs_to_doc_fragments<'a>( (doc_fragments, other_attrs) } -fn span_for_value(attr: &ast::Attribute) -> Span { - if let ast::AttrKind::Normal(normal) = &attr.kind - && let ast::AttrArgs::Eq { value, .. } = &normal.item.args - { - value.span().with_ctxt(attr.span.ctxt()) - } else { - attr.span - } -} - /// Return the doc-comments on this item, grouped by the module they came from. /// The module can be different if this is a re-export with added documentation. /// @@ -353,12 +349,15 @@ pub fn strip_generics_from_path(path_str: &str) -> Result<Box<str>, MalformedGen /// //// If there are no doc-comments, return true. /// FIXME(#78591): Support both inner and outer attributes on the same item. -pub fn inner_docs(attrs: &[ast::Attribute]) -> bool { - attrs.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == ast::AttrStyle::Inner) +pub fn inner_docs(attrs: &[impl AttributeExt]) -> bool { + attrs + .iter() + .find(|a| a.doc_str().is_some()) + .map_or(true, |a| a.style() == ast::AttrStyle::Inner) } /// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]`. -pub fn has_primitive_or_keyword_docs(attrs: &[ast::Attribute]) -> bool { +pub fn has_primitive_or_keyword_docs(attrs: &[impl AttributeExt]) -> bool { for attr in attrs { if attr.has_name(sym::rustc_doc_primitive) { return true; @@ -408,7 +407,7 @@ pub fn may_be_doc_link(link_type: LinkType) -> bool { /// Simplified version of `preprocessed_markdown_links` from rustdoc. /// Must return at least the same links as it, but may add some more links on top of that. -pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<str>> { +pub(crate) fn attrs_to_preprocessed_links<A: AttributeExt + Clone>(attrs: &[A]) -> Vec<Box<str>> { 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(); | 
