Remember names of cfg
-ed out items to mention them in diagnostics
`#[cfg]`s are frequently used to gate crate content behind cargo features. This can lead to very confusing errors when features are missing. For example, `serde` doesn't have the `derive` feature by default. Therefore, `serde::Serialize` fails to resolve with a generic error, even though the macro is present in the docs. This commit adds a list of all stripped item names to metadata. This is filled during macro expansion and then, through a fed query, persisted in metadata. The downstream resolver can then access the metadata to look at possible candidates for mentioning in the errors. This slightly increases metadata (800k->809k for the feature-heavy windows crate), but not enough to really matter.
This commit is contained in:
parent
642c92e630
commit
a647ba250a
30 changed files with 599 additions and 84 deletions
|
@ -25,6 +25,7 @@ use errors::{
|
|||
ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst, ParamKindInTyOfConstParam,
|
||||
};
|
||||
use rustc_arena::{DroplessArena, TypedArena};
|
||||
use rustc_ast::expand::StrippedCfgItem;
|
||||
use rustc_ast::node_id::NodeMap;
|
||||
use rustc_ast::{self as ast, attr, NodeId, CRATE_NODE_ID};
|
||||
use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
|
||||
|
@ -171,6 +172,7 @@ enum ImplTraitContext {
|
|||
Universal(LocalDefId),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BindingError {
|
||||
name: Symbol,
|
||||
origin: BTreeSet<Span>,
|
||||
|
@ -178,6 +180,7 @@ struct BindingError {
|
|||
could_be_path: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ResolutionError<'a> {
|
||||
/// Error E0401: can't use type or const parameters from outer function.
|
||||
GenericParamsFromOuterFunction(Res, HasGenericParams),
|
||||
|
@ -207,7 +210,12 @@ enum ResolutionError<'a> {
|
|||
/// Error E0431: `self` import can only appear in an import list with a non-empty prefix.
|
||||
SelfImportOnlyInImportListWithNonEmptyPrefix,
|
||||
/// Error E0433: failed to resolve.
|
||||
FailedToResolve { label: String, suggestion: Option<Suggestion> },
|
||||
FailedToResolve {
|
||||
last_segment: Option<Symbol>,
|
||||
label: String,
|
||||
suggestion: Option<Suggestion>,
|
||||
module: Option<ModuleOrUniformRoot<'a>>,
|
||||
},
|
||||
/// Error E0434: can't capture dynamic environment in a fn item.
|
||||
CannotCaptureDynamicEnvironmentInFnItem,
|
||||
/// Error E0435: attempt to use a non-constant value in a constant.
|
||||
|
@ -402,6 +410,7 @@ enum PathResult<'a> {
|
|||
label: String,
|
||||
suggestion: Option<Suggestion>,
|
||||
is_error_from_last_segment: bool,
|
||||
module: Option<ModuleOrUniformRoot<'a>>,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -410,11 +419,12 @@ impl<'a> PathResult<'a> {
|
|||
span: Span,
|
||||
is_error_from_last_segment: bool,
|
||||
finalize: bool,
|
||||
module: Option<ModuleOrUniformRoot<'a>>,
|
||||
label_and_suggestion: impl FnOnce() -> (String, Option<Suggestion>),
|
||||
) -> PathResult<'a> {
|
||||
let (label, suggestion) =
|
||||
if finalize { label_and_suggestion() } else { (String::new(), None) };
|
||||
PathResult::Failed { span, label, suggestion, is_error_from_last_segment }
|
||||
PathResult::Failed { span, label, suggestion, is_error_from_last_segment, module }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -685,6 +695,7 @@ struct PrivacyError<'a> {
|
|||
dedup_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct UseError<'a> {
|
||||
err: DiagnosticBuilder<'a, ErrorGuaranteed>,
|
||||
/// Candidates which user could `use` to access the missing type.
|
||||
|
@ -1059,6 +1070,9 @@ pub struct Resolver<'a, 'tcx> {
|
|||
/// Whether lifetime elision was successful.
|
||||
lifetime_elision_allowed: FxHashSet<NodeId>,
|
||||
|
||||
/// Names of items that were stripped out via cfg with their corresponding cfg meta item.
|
||||
stripped_cfg_items: Vec<StrippedCfgItem<NodeId>>,
|
||||
|
||||
effective_visibilities: EffectiveVisibilities,
|
||||
doc_link_resolutions: FxHashMap<LocalDefId, DocLinkResMap>,
|
||||
doc_link_traits_in_scope: FxHashMap<LocalDefId, Vec<DefId>>,
|
||||
|
@ -1353,6 +1367,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
proc_macros: Default::default(),
|
||||
confused_type_with_std_module: Default::default(),
|
||||
lifetime_elision_allowed: Default::default(),
|
||||
stripped_cfg_items: Default::default(),
|
||||
effective_visibilities: Default::default(),
|
||||
doc_link_resolutions: Default::default(),
|
||||
doc_link_traits_in_scope: Default::default(),
|
||||
|
@ -1410,6 +1425,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
|||
let main_def = self.main_def;
|
||||
let confused_type_with_std_module = self.confused_type_with_std_module;
|
||||
let effective_visibilities = self.effective_visibilities;
|
||||
|
||||
self.tcx.feed_local_crate().stripped_cfg_items(self.tcx.arena.alloc_from_iter(
|
||||
self.stripped_cfg_items.into_iter().filter_map(|item| {
|
||||
let parent_module = self.node_id_to_def_id.get(&item.parent_module)?.to_def_id();
|
||||
Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg })
|
||||
}),
|
||||
));
|
||||
|
||||
let global_ctxt = ResolverGlobalCtxt {
|
||||
expn_that_defined,
|
||||
visibilities,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue