Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add warning if a resolution failed #49542

Merged
merged 6 commits into from
Apr 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ impl<'a> Builder<'a> {
test::TheBook, test::UnstableBook,
test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme,
// Run run-make last, since these won't pass without make on Windows
test::RunMake),
test::RunMake, test::RustdocUi),
Kind::Bench => describe!(test::Crate, test::CrateLibrustc),
Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc,
Expand Down
59 changes: 52 additions & 7 deletions src/bootstrap/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,41 @@ impl Step for RustdocJS {
}
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RustdocUi {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a lot of code for very few tests. I was hoping we could somehow express this in the regular ui tests by inserting some flags via comments in the test?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As would i, but (as far as i know) there's no facility in compiletest to swap out which binary is called for a specific test - only which arguments are passed. In addition, we would have to tell bootstrap to have rustdoc ready for the UI tests, even if someone is trying to run a specific non-rustdoc test.

Plus, we wanted to introduce UI tests for rustdoc at some point anyway. >_> Having them in a separate test directory will help us when we add more over time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to have a struct directly to bind the test folder path.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This struct should be replaceable with a host_test! macro invocation I believe.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to at first to avoid writing code by hand, but failed... I can't only rely on UI or rustdoc test suite, I need a mix of the two.

pub host: Interned<String>,
pub target: Interned<String>,
pub compiler: Compiler,
}

impl Step for RustdocUi {
type Output = ();
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;

fn should_run(run: ShouldRun) -> ShouldRun {
run.path("src/test/rustdoc-ui")
}

fn make_run(run: RunConfig) {
let compiler = run.builder.compiler(run.builder.top_stage, run.host);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to make this depend on rustdoc. Otherwise rustdoc might not be available when running the tests. A call to ensure should suffice

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently it's done correctly (or at least that's what I understood from @Mark-Simulacrum's comment).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is fine as is, we depend on rustdoc below when we pass it's path.

run.builder.ensure(RustdocUi {
host: run.host,
target: run.target,
compiler,
});
}

fn run(self, builder: &Builder) {
builder.ensure(Compiletest {
compiler: self.compiler,
target: self.target,
mode: "ui",
suite: "rustdoc-ui",
})
}
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Tidy;

Expand Down Expand Up @@ -851,8 +886,12 @@ impl Step for Compiletest {
cmd.arg("--run-lib-path").arg(builder.sysroot_libdir(compiler, target));
cmd.arg("--rustc-path").arg(builder.rustc(compiler));

let is_rustdoc_ui = suite.ends_with("rustdoc-ui");

// Avoid depending on rustdoc when we don't need it.
if mode == "rustdoc" || (mode == "run-make" && suite.ends_with("fulldeps")) {
if mode == "rustdoc" ||
(mode == "run-make" && suite.ends_with("fulldeps")) ||
(mode == "ui" && is_rustdoc_ui) {
cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler.host));
}

Expand All @@ -868,12 +907,18 @@ impl Step for Compiletest {
cmd.arg("--nodejs").arg(nodejs);
}

let mut flags = vec!["-Crpath".to_string()];
if build.config.rust_optimize_tests {
flags.push("-O".to_string());
}
if build.config.rust_debuginfo_tests {
flags.push("-g".to_string());
let mut flags = if is_rustdoc_ui {
Vec::new()
} else {
vec!["-Crpath".to_string()]
};
if !is_rustdoc_ui {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge the if below into this one

if build.config.rust_optimize_tests {
flags.push("-O".to_string());
}
if build.config.rust_debuginfo_tests {
flags.push("-g".to_string());
}
}
flags.push("-Zunstable-options".to_string());
flags.push(build.config.cmd.rustc_args().join(" "));
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/iter/iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -998,7 +998,7 @@ pub trait Iterator {
/// an extra layer of indirection. `flat_map()` will remove this extra layer
/// on its own.
///
/// You can think of [`flat_map(f)`][flat_map] as the semantic equivalent
/// You can think of `flat_map(f)` as the semantic equivalent
/// of [`map`]ping, and then [`flatten`]ing as in `map(f).flatten()`.
///
/// Another way of thinking about `flat_map()`: [`map`]'s closure returns
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/str/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ pub struct CharSearcher<'a> {

/// `finger` is the current byte index of the forward search.
/// Imagine that it exists before the byte at its index, i.e.
/// haystack[finger] is the first byte of the slice we must inspect during
/// `haystack[finger]` is the first byte of the slice we must inspect during
/// forward searching
finger: usize,
/// `finger_back` is the current byte index of the reverse search.
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1550,7 +1550,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
}
}

/// Returns the type of ty[i]
/// Returns the type of `ty[i]`.
pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
match self.sty {
TyArray(ty, _) | TySlice(ty) => Some(ty),
Expand Down
8 changes: 8 additions & 0 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1178,6 +1178,10 @@ enum PathKind {
Type,
}

fn resolution_failure(cx: &DocContext, path_str: &str) {
cx.sess().warn(&format!("[{}] cannot be resolved, ignoring it...", path_str));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there spans available that we can use to report the warnings?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'll be part of another pr. I think this one is already big enough.

}

impl Clean<Attributes> for [ast::Attribute] {
fn clean(&self, cx: &DocContext) -> Attributes {
let mut attrs = Attributes::from_ast(cx.sess().diagnostic(), self);
Expand Down Expand Up @@ -1228,6 +1232,7 @@ impl Clean<Attributes> for [ast::Attribute] {
if let Ok(def) = resolve(cx, path_str, true) {
def
} else {
resolution_failure(cx, path_str);
// this could just be a normal link or a broken link
// we could potentially check if something is
// "intra-doc-link-like" and warn in that case
Expand All @@ -1238,6 +1243,7 @@ impl Clean<Attributes> for [ast::Attribute] {
if let Ok(def) = resolve(cx, path_str, false) {
def
} else {
resolution_failure(cx, path_str);
// this could just be a normal link
continue;
}
Expand Down Expand Up @@ -1282,6 +1288,7 @@ impl Clean<Attributes> for [ast::Attribute] {
} else if let Ok(value_def) = resolve(cx, path_str, true) {
value_def
} else {
resolution_failure(cx, path_str);
// this could just be a normal link
continue;
}
Expand All @@ -1290,6 +1297,7 @@ impl Clean<Attributes> for [ast::Attribute] {
if let Some(def) = macro_resolve(cx, path_str) {
(def, None)
} else {
resolution_failure(cx, path_str);
continue
}
}
Expand Down
45 changes: 38 additions & 7 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt, AllArenas};
use rustc::hir::map as hir_map;
use rustc::lint;
use rustc::session::config::ErrorOutputType;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_resolve as resolve;
use rustc_metadata::creader::CrateLoader;
Expand All @@ -28,8 +29,9 @@ use syntax::ast::NodeId;
use syntax::codemap;
use syntax::edition::Edition;
use syntax::feature_gate::UnstableFeatures;
use syntax::json::JsonEmitter;
use errors;
use errors::emitter::ColorConfig;
use errors::emitter::{Emitter, EmitterWriter};

use std::cell::{RefCell, Cell};
use std::mem;
Expand Down Expand Up @@ -115,7 +117,6 @@ impl DocAccessLevels for AccessLevels<DefId> {
}
}


pub fn run_core(search_paths: SearchPaths,
cfgs: Vec<String>,
externs: config::Externs,
Expand All @@ -126,7 +127,8 @@ pub fn run_core(search_paths: SearchPaths,
crate_name: Option<String>,
force_unstable_if_unmarked: bool,
edition: Edition,
cg: CodegenOptions) -> (clean::Crate, RenderInfo)
cg: CodegenOptions,
error_format: ErrorOutputType) -> (clean::Crate, RenderInfo)
{
// Parse, resolve, and typecheck the given crate.

Expand All @@ -138,6 +140,7 @@ pub fn run_core(search_paths: SearchPaths,
let warning_lint = lint::builtin::WARNINGS.name_lower();

let host_triple = TargetTriple::from_triple(config::host_triple());
// plays with error output here!
let sessopts = config::Options {
maybe_sysroot,
search_paths,
Expand All @@ -155,14 +158,42 @@ pub fn run_core(search_paths: SearchPaths,
edition,
..config::basic_debugging_options()
},
error_format,
..config::basic_options().clone()
};

let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()));
let diagnostic_handler = errors::Handler::with_tty_emitter(ColorConfig::Auto,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of these changes?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Allow rustdoc output to be checked through UI test suite.

true,
false,
Some(codemap.clone()));
let emitter: Box<dyn Emitter> = match error_format {
ErrorOutputType::HumanReadable(color_config) => Box::new(
EmitterWriter::stderr(
color_config,
Some(codemap.clone()),
false,
sessopts.debugging_opts.teach,
).ui_testing(sessopts.debugging_opts.ui_testing)
),
ErrorOutputType::Json(pretty) => Box::new(
JsonEmitter::stderr(
None,
codemap.clone(),
pretty,
sessopts.debugging_opts.approximate_suggestions,
).ui_testing(sessopts.debugging_opts.ui_testing)
),
ErrorOutputType::Short(color_config) => Box::new(
EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false)
),
};

let diagnostic_handler = errors::Handler::with_emitter_and_flags(
emitter,
errors::HandlerFlags {
can_emit_warnings: true,
treat_err_as_bug: false,
external_macro_backtrace: false,
..Default::default()
},
);

let mut sess = session::build_session_(
sessopts, cpath, diagnostic_handler, codemap,
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/html/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub struct SharedContext {
/// This describes the layout of each page, and is not modified after
/// creation of the context (contains info like the favicon and added html).
pub layout: layout::Layout,
/// This flag indicates whether [src] links should be generated or not. If
/// This flag indicates whether `[src]` links should be generated or not. If
/// the source files are present in the html rendering, then this will be
/// `true`.
pub include_sources: bool,
Expand Down
56 changes: 51 additions & 5 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#![feature(test)]
#![feature(vec_remove_item)]
#![feature(entry_and_modify)]
#![feature(dyn_trait)]

extern crate arena;
extern crate getopts;
Expand All @@ -48,6 +49,8 @@ extern crate tempdir;

extern crate serialize as rustc_serialize; // used by deriving

use errors::ColorConfig;

use std::collections::{BTreeMap, BTreeSet};
use std::default::Default;
use std::env;
Expand Down Expand Up @@ -278,6 +281,21 @@ pub fn opts() -> Vec<RustcOptGroup> {
"edition to use when compiling rust code (default: 2015)",
"EDITION")
}),
unstable("color", |o| {
o.optopt("",
"color",
"Configure coloring of output:
auto = colorize, if output goes to a tty (default);
always = always colorize output;
never = never colorize output",
"auto|always|never")
}),
unstable("error-format", |o| {
o.optopt("",
"error-format",
"How errors and other messages are produced",
"human|json|short")
}),
]
}

Expand Down Expand Up @@ -362,9 +380,33 @@ pub fn main_args(args: &[String]) -> isize {
}
let input = &matches.free[0];

let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
Some("auto") => ColorConfig::Auto,
Some("always") => ColorConfig::Always,
Some("never") => ColorConfig::Never,
None => ColorConfig::Auto,
Some(arg) => {
print_error(&format!("argument for --color must be `auto`, `always` or `never` \
(instead was `{}`)", arg));
return 1;
}
};
let error_format = match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
Some("human") => ErrorOutputType::HumanReadable(color),
Some("json") => ErrorOutputType::Json(false),
Some("pretty-json") => ErrorOutputType::Json(true),
Some("short") => ErrorOutputType::Short(color),
None => ErrorOutputType::HumanReadable(color),
Some(arg) => {
print_error(&format!("argument for --error-format must be `human`, `json` or \
`short` (instead was `{}`)", arg));
return 1;
}
};

let mut libs = SearchPaths::new();
for s in &matches.opt_strs("L") {
libs.add_path(s, ErrorOutputType::default());
libs.add_path(s, error_format);
}
let externs = match parse_externs(&matches) {
Ok(ex) => ex,
Expand Down Expand Up @@ -464,7 +506,9 @@ pub fn main_args(args: &[String]) -> isize {
}

let output_format = matches.opt_str("w");
let res = acquire_input(PathBuf::from(input), externs, edition, cg, &matches, move |out| {

let res = acquire_input(PathBuf::from(input), externs, edition, cg, &matches, error_format,
move |out| {
let Output { krate, passes, renderinfo } = out;
info!("going to format");
match output_format.as_ref().map(|s| &**s) {
Expand Down Expand Up @@ -508,13 +552,14 @@ fn acquire_input<R, F>(input: PathBuf,
edition: Edition,
cg: CodegenOptions,
matches: &getopts::Matches,
error_format: ErrorOutputType,
f: F)
-> Result<R, String>
where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
match matches.opt_str("r").as_ref().map(|s| &**s) {
Some("rust") => Ok(rust_input(input, externs, edition, cg, matches, f)),
Some("rust") => Ok(rust_input(input, externs, edition, cg, matches, error_format, f)),
Some(s) => Err(format!("unknown input format: {}", s)),
None => Ok(rust_input(input, externs, edition, cg, matches, f))
None => Ok(rust_input(input, externs, edition, cg, matches, error_format, f))
}
}

Expand Down Expand Up @@ -545,6 +590,7 @@ fn rust_input<R, F>(cratefile: PathBuf,
edition: Edition,
cg: CodegenOptions,
matches: &getopts::Matches,
error_format: ErrorOutputType,
f: F) -> R
where R: 'static + Send,
F: 'static + Send + FnOnce(Output) -> R
Expand Down Expand Up @@ -597,7 +643,7 @@ where R: 'static + Send,
let (mut krate, renderinfo) =
core::run_core(paths, cfgs, externs, Input::File(cratefile), triple, maybe_sysroot,
display_warnings, crate_name.clone(),
force_unstable_if_unmarked, edition, cg);
force_unstable_if_unmarked, edition, cg, error_format);

info!("finished with rustc");

Expand Down
Loading