Don't run everybody_loops for rustdoc

Instead, ignore resolution errors that occur in item bodies.

The reason this can't ignore item bodies altogether is because
`const fn` could be used in generic types, for example `[T; f()]`
This commit is contained in:
Joshua Nelson 2020-06-20 15:57:23 -04:00
parent f6764c42ab
commit a5275ff415
4 changed files with 50 additions and 29 deletions

View File

@ -354,24 +354,13 @@ fn configure_and_expand_inner<'a>(
)
});
// 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
@ -417,7 +406,19 @@ fn configure_and_expand_inner<'a>(
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", || {

View File

@ -394,6 +394,11 @@ struct LateResolutionVisitor<'a, 'b, 'ast> {
/// 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.
@ -627,7 +632,10 @@ fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
}
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;
@ -644,6 +652,7 @@ fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b, 'ast> {
label_ribs: Vec::new(),
current_trait_ref: None,
diagnostic_metadata: DiagnosticMetadata::default(),
ignore_bodies,
}
}
@ -757,7 +766,7 @@ fn resolve_label(&self, mut label: Ident) -> Option<NodeId> {
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,
@ -775,7 +784,7 @@ fn resolve_label(&self, mut label: Ident) -> Option<NodeId> {
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 },
);
@ -1008,7 +1017,7 @@ fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: Rib
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);
@ -1274,7 +1283,7 @@ fn check_trait_item<F>(&mut self, ident: Ident, ns: Namespace, span: Span, err:
.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)));
}
}
}
@ -1390,7 +1399,7 @@ fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) -> Vec<BindingMap> {
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),
);
@ -1400,7 +1409,7 @@ fn check_consistent_bindings(&mut self, pats: &[P<Pat>]) -> Vec<BindingMap> {
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.
@ -1550,7 +1559,7 @@ fn fresh_binding(
// `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:
@ -1624,7 +1633,7 @@ fn try_resolve_as_non_binding(
// 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(),
@ -1809,7 +1818,7 @@ fn smart_resolve_path_fragment(
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)
@ -1843,6 +1852,15 @@ fn self_value_is_available(&mut self, self_span: Span, path_span: Span) -> bool
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,
@ -2339,8 +2357,8 @@ fn find_transitive_imports(
}
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");

View File

@ -1441,13 +1441,13 @@ fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
}
/// Entry point to crate resolution.
pub fn resolve_crate(&mut self, krate: &Crate) {
pub fn resolve_crate(&mut self, krate: &Crate, ignore_bodies: bool) {
let _prof_timer = self.session.prof.generic_activity("resolve_crate");
ImportResolver { r: self }.finalize_imports();
self.finalize_macro_resolutions();
self.late_resolve_crate(krate);
self.late_resolve_crate(krate, ignore_bodies);
self.check_unused(krate);
self.report_errors(krate);

View File

@ -57,5 +57,7 @@ pub unsafe fn uses_target_feature() {
// 'This is supported with target feature avx only.'
#[doc(cfg(target_feature = "avx"))]
pub fn uses_cfg_target_feature() {
uses_target_feature();
unsafe {
uses_target_feature();
}
}