)
});
- // If we're actually rustdoc then there's no need to actually compile
- // anything, so switch everything to just looping
- let mut should_loop = sess.opts.actually_rustdoc;
- if let Some(PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops)) = sess.opts.pretty {
- should_loop |= true;
- }
- if should_loop {
- log::debug!("replacing bodies with loop {{}}");
- util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
- }
+ let crate_types = sess.crate_types();
+ let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
let has_proc_macro_decls = sess.time("AST_validation", || {
rustc_ast_passes::ast_validation::check_crate(sess, &krate, &mut resolver.lint_buffer())
});
- let crate_types = sess.crate_types();
- let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
-
// For backwards compatibility, we don't try to run proc macro injection
// if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being
// specified. This should only affect users who manually invoke 'rustdoc', as
println!("{}", json::as_json(&krate));
}
- resolver.resolve_crate(&krate);
+ // If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items.
+ // anything, so switch everything to just looping
+ resolver.resolve_crate(&krate, sess.opts.actually_rustdoc);
+
+ //let mut should_loop = sess.opts.actually_rustdoc;
+ let mut should_loop = false;
+ if let Some(PpMode::PpmSource(PpSourceMode::PpmEveryBodyLoops)) = sess.opts.pretty {
+ should_loop |= true;
+ }
+ if should_loop {
+ log::debug!("replacing bodies with loop {{}}");
+ util::ReplaceBodyWithLoop::new(&mut resolver).visit_crate(&mut krate);
+ }
// Needs to go *after* expansion to be able to check the results of macro expansion.
sess.time("complete_gated_feature_checking", || {
/// Fields used to add information to diagnostic errors.
diagnostic_metadata: DiagnosticMetadata<'ast>,
+
+ /// Whether to report resolution errors for item bodies.
+ ///
+ /// In particular, rustdoc uses this to avoid giving errors for `cfg()` items.
+ ignore_bodies: bool,
}
/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
}
impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
- fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b, 'ast> {
+ fn new(
+ resolver: &'b mut Resolver<'a>,
+ ignore_bodies: bool,
+ ) -> LateResolutionVisitor<'a, 'b, 'ast> {
// During late resolution we only track the module component of the parent scope,
// although it may be useful to track other components as well for diagnostics.
let graph_root = resolver.graph_root;
label_ribs: Vec::new(),
current_trait_ref: None,
diagnostic_metadata: DiagnosticMetadata::default(),
+ ignore_bodies,
}
}
return if self.is_label_valid_from_rib(i) {
Some(*id)
} else {
- self.r.report_error(
+ self.report_error(
original_span,
ResolutionError::UnreachableLabel {
name: label.name,
suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label));
}
- self.r.report_error(
+ self.report_error(
original_span,
ResolutionError::UndeclaredLabel { name: label.name, suggestion },
);
if seen_bindings.contains_key(&ident) {
let span = seen_bindings.get(&ident).unwrap();
let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, *span);
- self.r.report_error(param.ident.span, err);
+ self.report_error(param.ident.span, err);
}
seen_bindings.entry(ident).or_insert(param.ident.span);
.is_err()
{
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
- self.r.report_error(span, err(ident.name, &path_names_to_string(path)));
+ self.report_error(span, err(ident.name, &path_names_to_string(path)));
}
}
}
if inconsistent_vars.contains_key(name) {
v.could_be_path = false;
}
- self.r.report_error(
+ self.report_error(
*v.origin.iter().next().unwrap(),
ResolutionError::VariableNotBoundInPattern(v),
);
let mut inconsistent_vars = inconsistent_vars.iter().collect::<Vec<_>>();
inconsistent_vars.sort();
for (name, v) in inconsistent_vars {
- self.r.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
+ self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(*name, v.1));
}
// 5) Finally bubble up all the binding maps.
// `Variant(a, a)`:
_ => IdentifierBoundMoreThanOnceInSamePattern,
};
- self.r.report_error(ident.span, error(ident.name));
+ self.report_error(ident.span, error(ident.name));
}
// Record as bound if it's valid:
// to something unusable as a pattern (e.g., constructor function),
// but we still conservatively report an error, see
// issues/33118#issuecomment-233962221 for one reason why.
- self.r.report_error(
+ self.report_error(
ident.span,
ResolutionError::BindingShadowsSomethingUnacceptable(
pat_src.descr(),
Err(err) => {
if let Some(err) = report_errors_for_call(self, err) {
- self.r.report_error(err.span, err.node);
+ self.report_error(err.span, err.node);
}
PartialRes::new(Res::Err)
if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
}
+ /// A wrapper around [`Resolver::report_error`].
+ ///
+ /// This doesn't emit errors for function bodies if `ignore_bodies` is set.
+ fn report_error(&self, span: Span, resolution_error: ResolutionError<'_>) {
+ if !self.ignore_bodies || self.diagnostic_metadata.current_function.is_none() {
+ self.r.report_error(span, resolution_error);
+ }
+ }
+
// Resolve in alternative namespaces if resolution in the primary namespace fails.
fn resolve_qpath_anywhere(
&mut self,
}
impl<'a> Resolver<'a> {
- pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
- let mut late_resolution_visitor = LateResolutionVisitor::new(self);
+ pub(crate) fn late_resolve_crate(&mut self, krate: &Crate, ignore_bodies: bool) {
+ let mut late_resolution_visitor = LateResolutionVisitor::new(self, ignore_bodies);
visit::walk_crate(&mut late_resolution_visitor, krate);
for (id, span) in late_resolution_visitor.diagnostic_metadata.unused_labels.iter() {
self.lint_buffer.buffer_lint(lint::builtin::UNUSED_LABELS, *id, *span, "unused label");