When cross-compiling, also build target-arch tarballs for libstd. (Closes: #42320)
Half of the logic is actually in there already in install.rs:install_std but it fails with an error like:
sh: 0: Can't open /<<BUILDDIR>>/rustc-1.21.0+dfsg1/build/tmp/dist/rust-std-1.21.0-powerpc64le-unknown-linux-gnu/install.sh
because the target-arch dist tarball wasn't built as well. This commit fixes that so the overall install works.
There is one minor bug in the existing code which this commit doesn't fix - the install.log from multiple runs of the installer gets clobbered, which seems like it might interfere with the uninstall process (I didn't look very deeply into this, because it doesn't affect what I need to do.) The actual installed files under DESTDIR seem fine though - either they are installed under an arch-specific path, or the multiple runs will clobber the same path with the same arch-independent file.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorOutputType {
HumanReadable(ColorConfig),
- Json,
+ Json(bool),
Short(ColorConfig),
}
let error_format = if matches.opts_present(&["error-format".to_owned()]) {
match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
Some("human") => ErrorOutputType::HumanReadable(color),
- Some("json") => ErrorOutputType::Json,
+ Some("json") => ErrorOutputType::Json(false),
+ Some("pretty-json") => ErrorOutputType::Json(true),
Some("short") => ErrorOutputType::Short(color),
None => ErrorOutputType::HumanReadable(color),
let debugging_opts = build_debugging_options(matches, error_format);
+ if !debugging_opts.unstable_options && error_format == ErrorOutputType::Json(true) {
+ early_error(ErrorOutputType::Json(false),
+ "--error-format=pretty-json is unstable");
+ }
+
let mut output_types = BTreeMap::new();
if !debugging_opts.parse_only {
for list in matches.opt_strs("emit") {
let mut v5 = super::basic_options();
// Reference
- v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
- v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
- v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
- v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
- v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+ v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+ v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+ v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+ v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+ v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
// Native changed
- v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json);
- v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
- v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
- v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
- v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+ v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
// Crate changed
- v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
- v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json);
- v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
- v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
- v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+ v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
// Dependency changed
- v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
- v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
- v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json);
- v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
- v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+ v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+ v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+ v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json(false));
+ v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+ v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
// Framework changed
- v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
- v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
- v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
- v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json);
- v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
+ v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+ v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+ v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+ v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json(false));
+ v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
// All changed
- v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
- v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
- v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
- v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
- v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json);
+ v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+ v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+ v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+ v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+ v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json(false));
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
let mut v4 = super::basic_options();
// Reference
- v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
- v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
- v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
- v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
- v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-
- v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
- v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
- v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
- v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
- v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-
- v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
- v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
- v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
- v3.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
- v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
-
- v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json);
- v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json);
- v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json);
- v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json);
- v4.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json);
+ v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+ v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+ v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+ v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+ v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+
+ v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+ v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+
+ v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+ v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
+ v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+ v3.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+ v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+
+ v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
+ v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
+ v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
+ v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
+ v4.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
match self.opts.error_format {
// when outputting JSON for tool consumption, the tool might want
// the duplicates
- config::ErrorOutputType::Json => {
+ config::ErrorOutputType::Json(_) => {
do_method()
},
_ => {
(config::ErrorOutputType::HumanReadable(_), Some(dst)) => {
Box::new(EmitterWriter::new(dst, Some(codemap.clone()), false))
}
- (config::ErrorOutputType::Json, None) => {
- Box::new(JsonEmitter::stderr(Some(registry), codemap.clone()))
+ (config::ErrorOutputType::Json(pretty), None) => {
+ Box::new(JsonEmitter::stderr(Some(registry), codemap.clone(), pretty))
}
- (config::ErrorOutputType::Json, Some(dst)) => {
- Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone()))
+ (config::ErrorOutputType::Json(pretty), Some(dst)) => {
+ Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone(), pretty))
}
(config::ErrorOutputType::Short(color_config), None) => {
Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), true))
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(EmitterWriter::stderr(color_config, None, false))
}
- config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
+ config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
config::ErrorOutputType::Short(color_config) => {
Box::new(EmitterWriter::stderr(color_config, None, true))
}
config::ErrorOutputType::HumanReadable(color_config) => {
Box::new(EmitterWriter::stderr(color_config, None, false))
}
- config::ErrorOutputType::Json => Box::new(JsonEmitter::basic()),
+ config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
config::ErrorOutputType::Short(color_config) => {
Box::new(EmitterWriter::stderr(color_config, None, true))
}
item: &'l ast::Item,
def: &'l ast::VariantData,
ty_params: &'l ast::Generics) {
+ debug!("process_struct {:?} {:?}", item, item.span);
let name = item.ident.to_string();
let qualname = format!("::{}", self.tcx.node_path_str(item.id));
- let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct);
- let (value, fields) =
- if let ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) = item.node
- {
- let include_priv_fields = !self.save_ctxt.config.pub_only;
- let fields_str = fields
- .iter()
- .enumerate()
- .filter_map(|(i, f)| {
- if include_priv_fields || f.vis == ast::Visibility::Public {
- f.ident.map(|i| i.to_string()).or_else(|| Some(i.to_string()))
- } else {
- None
- }
- })
- .collect::<Vec<_>>()
- .join(", ");
- let value = format!("{} {{ {} }}", name, fields_str);
- (value, fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect())
- } else {
- (String::new(), vec![])
+ let (kind, keyword) = match item.node {
+ ast::ItemKind::Struct(_, _) => (DefKind::Struct, keywords::Struct),
+ ast::ItemKind::Union(_, _) => (DefKind::Union, keywords::Union),
+ _ => unreachable!(),
+ };
+
+ let sub_span = self.span.sub_span_after_keyword(item.span, keyword);
+ let (value, fields) = match item.node {
+ ast::ItemKind::Struct(ast::VariantData::Struct(ref fields, _), _) |
+ ast::ItemKind::Union(ast::VariantData::Struct(ref fields, _), _) => {
+ let include_priv_fields = !self.save_ctxt.config.pub_only;
+ let fields_str = fields
+ .iter()
+ .enumerate()
+ .filter_map(|(i, f)| {
+ if include_priv_fields || f.vis == ast::Visibility::Public {
+ f.ident.map(|i| i.to_string()).or_else(|| Some(i.to_string()))
+ } else {
+ None
+ }
+ })
+ .collect::<Vec<_>>()
+ .join(", ");
+ let value = format!("{} {{ {} }}", name, fields_str);
+ (value, fields.iter().map(|f| ::id_from_node_id(f.id, &self.save_ctxt)).collect())
+ }
+ _ => (String::new(), vec![])
};
if !self.span.filter_generated(sub_span, item.span) {
let span = self.span_from_span(sub_span.expect("No span found for struct"));
- let kind = match item.node {
- ast::ItemKind::Struct(_, _) => DefKind::Struct,
- ast::ItemKind::Union(_, _) => DefKind::Union,
- _ => unreachable!(),
- };
self.dumper.dump_def(item.vis == ast::Visibility::Public, Def {
kind,
id: ::id_from_node_id(item.id, &self.save_ctxt),
ex: &'l ast::Expr,
seg: &'l ast::PathSegment,
args: &'l [P<ast::Expr>]) {
+ debug!("process_method_call {:?} {:?}", ex, ex.span);
if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
down_cast_data!(mcd, RefData, ex.span);
if !generated_code(ex.span) {
}
}
}
- ast::ExprKind::MethodCall(..) => {
+ ast::ExprKind::MethodCall(ref seg, ..) => {
let expr_hir_id = self.tcx.hir.definitions().node_to_hir_id(expr.id);
let method_id = self.tables.type_dependent_defs()[expr_hir_id].def_id();
let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
ty::ImplContainer(_) => (Some(method_id), None),
ty::TraitContainer(_) => (None, Some(method_id)),
};
- let sub_span = self.span_utils.sub_span_for_meth_name(expr.span);
- filter!(self.span_utils, sub_span, expr.span, None);
- let span = self.span_from_span(sub_span.unwrap());
+ let sub_span = seg.span;
+ filter!(self.span_utils, Some(sub_span), expr.span, None);
+ let span = self.span_from_span(sub_span);
Some(Data::RefData(Ref {
kind: RefKind::Function,
span,
false
}
+ if path.segments.is_empty() {
+ return None;
+ }
+
let def = self.get_path_def(id);
- let sub_span = self.span_utils.span_for_last_ident(path.span);
- filter!(self.span_utils, sub_span, path.span, None);
+ let last_seg = &path.segments[path.segments.len() - 1];
+ let sub_span = last_seg.span;
+ filter!(self.span_utils, Some(sub_span), path.span, None);
match def {
HirDef::Upvar(id, ..) |
HirDef::Local(id) => {
- let span = self.span_from_span(sub_span.unwrap());
+ let span = self.span_from_span(sub_span);
Some(Ref {
kind: RefKind::Variable,
span,
HirDef::Const(..) |
HirDef::AssociatedConst(..) |
HirDef::VariantCtor(..) => {
- let span = self.span_from_span(sub_span.unwrap());
+ let span = self.span_from_span(sub_span);
Some(Ref {
kind: RefKind::Variable,
span,
HirDef::AssociatedTy(def_id) |
HirDef::Trait(def_id) |
HirDef::TyParam(def_id) => {
- let span = self.span_from_span(sub_span.unwrap());
+ let span = self.span_from_span(sub_span);
Some(Ref {
kind: RefKind::Type,
span,
// This is a reference to a tuple struct where the def_id points
// to an invisible constructor function. That is not a very useful
// def, so adjust to point to the tuple struct itself.
- let span = self.span_from_span(sub_span.unwrap());
+ let span = self.span_from_span(sub_span);
let parent_def_id = self.tcx.parent_def_id(def_id).unwrap();
Some(Ref {
kind: RefKind::Type,
})
}
HirDef::Method(decl_id) => {
- let sub_span = self.span_utils.sub_span_for_meth_name(path.span);
- filter!(self.span_utils, sub_span, path.span, None);
let def_id = if decl_id.is_local() {
let ti = self.tcx.associated_item(decl_id);
self.tcx.associated_items(ti.container.id())
} else {
None
};
- let span = self.span_from_span(sub_span.unwrap());
+ let span = self.span_from_span(sub_span);
Some(Ref {
kind: RefKind::Function,
span,
})
}
HirDef::Fn(def_id) => {
- let span = self.span_from_span(sub_span.unwrap());
+ let span = self.span_from_span(sub_span);
Some(Ref {
kind: RefKind::Function,
span,
})
}
HirDef::Mod(def_id) => {
- let span = self.span_from_span(sub_span.unwrap());
+ let span = self.span_from_span(sub_span);
Some(Ref {
kind: RefKind::Mod,
span,
}
}
- // Return the span for the last ident before a `(` or `<` or '::<' and outside any
- // any brackets, or the last span.
- pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
- let mut toks = self.retokenise_span(span);
- let mut prev = toks.real_token();
- let mut result = None;
- let mut bracket_count = 0;
- let mut prev_span = None;
- while prev.tok != token::Eof {
- prev_span = None;
- let mut next = toks.real_token();
-
- if (next.tok == token::OpenDelim(token::Paren) || next.tok == token::Lt) &&
- bracket_count == 0 && prev.tok.is_ident() {
- result = Some(prev.sp);
- }
-
- if bracket_count == 0 && next.tok == token::ModSep {
- let old = prev;
- prev = next;
- next = toks.real_token();
- if next.tok == token::Lt && old.tok.is_ident() {
- result = Some(old.sp);
- }
- }
-
- bracket_count += match prev.tok {
- token::OpenDelim(token::Paren) | token::Lt => 1,
- token::CloseDelim(token::Paren) | token::Gt => -1,
- token::BinOp(token::Shr) => -2,
- _ => 0,
- };
-
- if prev.tok.is_ident() && bracket_count == 0 {
- prev_span = Some(prev.sp);
- }
- prev = next;
- }
- result.or(prev_span)
- }
-
// Return the span for the last ident before a `<` and outside any
// angle brackets, or the last span.
pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
}
macro_rules! filter {
- ($util: expr, $span: ident, $parent: expr, None) => {
+ ($util: expr, $span: expr, $parent: expr, None) => {
if $util.filter_generated($span, $parent) {
return None;
}
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self) -> &mut R { &mut self.inner }
+ /// Returns `true` if there are no bytes in the internal buffer.
+ ///
+ /// # Examples
+ /// ```
+ /// # #![feature(bufreader_is_empty)]
+ /// use std::io::BufReader;
+ /// use std::io::BufRead;
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let f1 = File::open("log.txt")?;
+ /// let mut reader = BufReader::new(f1);
+ /// assert!(reader.is_empty());
+ ///
+ /// if reader.fill_buf()?.len() > 0 {
+ /// assert!(!reader.is_empty());
+ /// }
+ /// # Ok(())
+ /// # }
+ /// ```
+ #[unstable(feature = "bufreader_is_empty", issue = "45323", reason = "recently added")]
+ pub fn is_empty(&self) -> bool {
+ self.pos == self.cap
+ }
+
/// Unwraps this `BufReader`, returning the underlying reader.
///
/// Note that any leftover data in the internal buffer is lost.
use std::io::{self, Write};
use std::vec;
-use rustc_serialize::json::as_json;
+use rustc_serialize::json::{as_json, as_pretty_json};
pub struct JsonEmitter {
dst: Box<Write + Send>,
registry: Option<Registry>,
cm: Rc<CodeMapper + 'static>,
+ pretty: bool,
}
impl JsonEmitter {
pub fn stderr(registry: Option<Registry>,
- code_map: Rc<CodeMap>) -> JsonEmitter {
+ code_map: Rc<CodeMap>,
+ pretty: bool) -> JsonEmitter {
JsonEmitter {
dst: Box::new(io::stderr()),
registry,
cm: code_map,
+ pretty,
}
}
- pub fn basic() -> JsonEmitter {
+ pub fn basic(pretty: bool) -> JsonEmitter {
let file_path_mapping = FilePathMapping::empty();
- JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)))
+ JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)), pretty)
}
pub fn new(dst: Box<Write + Send>,
registry: Option<Registry>,
- code_map: Rc<CodeMap>) -> JsonEmitter {
+ code_map: Rc<CodeMap>,
+ pretty: bool) -> JsonEmitter {
JsonEmitter {
dst,
registry,
cm: code_map,
+ pretty,
}
}
}
impl Emitter for JsonEmitter {
fn emit(&mut self, db: &DiagnosticBuilder) {
let data = Diagnostic::from_diagnostic_builder(db, self);
- if let Err(e) = writeln!(&mut self.dst, "{}", as_json(&data)) {
+ let result = if self.pretty {
+ writeln!(&mut self.dst, "{}", as_pretty_json(&data))
+ } else {
+ writeln!(&mut self.dst, "{}", as_json(&data))
+ };
+ if let Err(e) = result {
panic!("failed to print diagnostics: {:?}", e);
}
}
spans: Vec<DiagnosticSpan>,
/// Associated diagnostic messages.
children: Vec<Diagnostic>,
- /// The message as rustc would render it. Currently this is only
- /// `Some` for "suggestions", but eventually it will include all
- /// snippets.
+ /// The message as rustc would render it. Currently this is always `None`
rendered: Option<String>,
}
/// Label that should be placed at this location (if any)
label: Option<String>,
/// If we are suggesting a replacement, this will contain text
- /// that should be sliced in atop this span. You may prefer to
- /// load the fully rendered version from the parent `Diagnostic`,
- /// however.
+ /// that should be sliced in atop this span.
suggested_replacement: Option<String>,
/// Macro invocations that created the code at this span, if any.
expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// compile-flags: --error-format json
+// compile-flags: --error-format pretty-json -Zunstable-options
// The output for humans should just highlight the whole span without showing
// the suggested replacement, but we also want to test that suggested
-{"message":"unnecessary parentheses around assigned value","code":{"code":"unused_parens","explanation":null},"level":"warning","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1001,"byte_end":1014,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[{"message":"lint level defined here","code":null,"level":"note","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":847,"byte_end":860,"line_start":19,"line_end":19,"column_start":9,"column_end":22,"is_primary":true,"text":[{"text":"#![warn(unused_parens)]","highlight_start":9,"highlight_end":22}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[],"rendered":null},{"message":"remove these parentheses","code":null,"level":"help","spans":[{"file_name":"$DIR/unused_parens_json_suggestion.rs","byte_start":1001,"byte_end":1014,"line_start":24,"line_end":24,"column_start":14,"column_end":27,"is_primary":true,"text":[{"text":" let _a = (1 / (2 + 3));","highlight_start":14,"highlight_end":27}],"label":null,"suggested_replacement":"1 / (2 + 3)","expansion":null}],"children":[],"rendered":null}],"rendered":null}
+{
+ "message": "unnecessary parentheses around assigned value",
+ "code": {
+ "code": "unused_parens",
+ "explanation": null
+ },
+ "level": "warning",
+ "spans": [
+ {
+ "file_name": "$DIR/unused_parens_json_suggestion.rs",
+ "byte_start": 1027,
+ "byte_end": 1040,
+ "line_start": 24,
+ "line_end": 24,
+ "column_start": 14,
+ "column_end": 27,
+ "is_primary": true,
+ "text": [
+ {
+ "text": " let _a = (1 / (2 + 3));",
+ "highlight_start": 14,
+ "highlight_end": 27
+ }
+ ],
+ "label": null,
+ "suggested_replacement": null,
+ "expansion": null
+ }
+ ],
+ "children": [
+ {
+ "message": "lint level defined here",
+ "code": null,
+ "level": "note",
+ "spans": [
+ {
+ "file_name": "$DIR/unused_parens_json_suggestion.rs",
+ "byte_start": 873,
+ "byte_end": 886,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 9,
+ "column_end": 22,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "#![warn(unused_parens)]",
+ "highlight_start": 9,
+ "highlight_end": 22
+ }
+ ],
+ "label": null,
+ "suggested_replacement": null,
+ "expansion": null
+ }
+ ],
+ "children": [],
+ "rendered": null
+ },
+ {
+ "message": "remove these parentheses",
+ "code": null,
+ "level": "help",
+ "spans": [
+ {
+ "file_name": "$DIR/unused_parens_json_suggestion.rs",
+ "byte_start": 1027,
+ "byte_end": 1040,
+ "line_start": 24,
+ "line_end": 24,
+ "column_start": 14,
+ "column_end": 27,
+ "is_primary": true,
+ "text": [
+ {
+ "text": " let _a = (1 / (2 + 3));",
+ "highlight_start": 14,
+ "highlight_end": 27
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "1 / (2 + 3)",
+ "expansion": null
+ }
+ ],
+ "children": [],
+ "rendered": null
+ }
+ ],
+ "rendered": null
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// compile-flags: --error-format json
+// compile-flags: --error-format pretty-json -Zunstable-options
// The output for humans should just highlight the whole span without showing
// the suggested replacement, but we also want to test that suggested
-{"message":"cannot find type `Iter` in this scope","code":{"code":"E0412","explanation":"/nThe type name used is not in scope./n/nErroneous code examples:/n/n```compile_fail,E0412/nimpl Something {} // error: type name `Something` is not in scope/n/n// or:/n/ntrait Foo {/n fn bar(N); // error: type name `N` is not in scope/n}/n/n// or:/n/nfn foo(x: T) {} // type name `T` is not in scope/n```/n/nTo fix this error, please verify you didn't misspell the type name, you did/ndeclare it or imported it into the scope. Examples:/n/n```/nstruct Something;/n/nimpl Something {} // ok!/n/n// or:/n/ntrait Foo {/n type N;/n/n fn bar(_: Self::N); // ok!/n}/n/n// or:/n/nfn foo<T>(x: T) {} // ok!/n```/n/nAnother case that causes this error is when a type is imported into a parent/nmodule. To fix this, you can follow the suggestion and use File directly or/n`use super::File;` which will import the types from the parent namespace. An/nexample that causes this error is below:/n/n```compile_fail,E0412/nuse std::fs::File;/n/nmod foo {/n fn some_function(f: File) {}/n}/n```/n/n```/nuse std::fs::File;/n/nmod foo {/n // either/n use super::File;/n // or/n // use std::fs::File;/n fn foo(f: File) {}/n}/n# fn main() {} // don't insert it for us; that'll break imports/n```/n"},"level":"error","spans":[{"file_name":"$DIR/use_suggestion_json.rs","byte_start":862,"byte_end":866,"line_start":20,"line_end":20,"column_start":12,"column_end":16,"is_primary":true,"text":[{"text":" let x: Iter;","highlight_start":12,"highlight_end":16}],"label":"not found in this scope","suggested_replacement":null,"expansion":null}],"children":[{"message":"possible candidates are found in other modules, you can import them into scope","code":null,"level":"help","spans":[{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::binary_heap::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::btree_map::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::btree_set::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::hash_map::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::hash_set::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::linked_list::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::collections::vec_deque::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::option::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::path::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::result::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::slice::Iter;/n/n","expansion":null},{"file_name":"$DIR/use_suggestion_json.rs","byte_start":839,"byte_end":839,"line_start":19,"line_end":19,"column_start":1,"column_end":1,"is_primary":true,"text":[{"text":"fn main() {","highlight_start":1,"highlight_end":1}],"label":null,"suggested_replacement":"use std::sync::mpsc::Iter;/n/n","expansion":null}],"children":[],"rendered":null}],"rendered":null}
-{"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":null}
+{
+ "message": "cannot find type `Iter` in this scope",
+ "code": {
+ "code": "E0412",
+ "explanation": "/nThe type name used is not in scope./n/nErroneous code examples:/n/n```compile_fail,E0412/nimpl Something {} // error: type name `Something` is not in scope/n/n// or:/n/ntrait Foo {/n fn bar(N); // error: type name `N` is not in scope/n}/n/n// or:/n/nfn foo(x: T) {} // type name `T` is not in scope/n```/n/nTo fix this error, please verify you didn't misspell the type name, you did/ndeclare it or imported it into the scope. Examples:/n/n```/nstruct Something;/n/nimpl Something {} // ok!/n/n// or:/n/ntrait Foo {/n type N;/n/n fn bar(_: Self::N); // ok!/n}/n/n// or:/n/nfn foo<T>(x: T) {} // ok!/n```/n/nAnother case that causes this error is when a type is imported into a parent/nmodule. To fix this, you can follow the suggestion and use File directly or/n`use super::File;` which will import the types from the parent namespace. An/nexample that causes this error is below:/n/n```compile_fail,E0412/nuse std::fs::File;/n/nmod foo {/n fn some_function(f: File) {}/n}/n```/n/n```/nuse std::fs::File;/n/nmod foo {/n // either/n use super::File;/n // or/n // use std::fs::File;/n fn foo(f: File) {}/n}/n# fn main() {} // don't insert it for us; that'll break imports/n```/n"
+ },
+ "level": "error",
+ "spans": [
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 888,
+ "byte_end": 892,
+ "line_start": 20,
+ "line_end": 20,
+ "column_start": 12,
+ "column_end": 16,
+ "is_primary": true,
+ "text": [
+ {
+ "text": " let x: Iter;",
+ "highlight_start": 12,
+ "highlight_end": 16
+ }
+ ],
+ "label": "not found in this scope",
+ "suggested_replacement": null,
+ "expansion": null
+ }
+ ],
+ "children": [
+ {
+ "message": "possible candidates are found in other modules, you can import them into scope",
+ "code": null,
+ "level": "help",
+ "spans": [
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::collections::binary_heap::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::collections::btree_map::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::collections::btree_set::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::collections::hash_map::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::collections::hash_set::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::collections::linked_list::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::collections::vec_deque::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::option::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::path::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::result::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::slice::Iter;/n/n",
+ "expansion": null
+ },
+ {
+ "file_name": "$DIR/use_suggestion_json.rs",
+ "byte_start": 865,
+ "byte_end": 865,
+ "line_start": 19,
+ "line_end": 19,
+ "column_start": 1,
+ "column_end": 1,
+ "is_primary": true,
+ "text": [
+ {
+ "text": "fn main() {",
+ "highlight_start": 1,
+ "highlight_end": 1
+ }
+ ],
+ "label": null,
+ "suggested_replacement": "use std::sync::mpsc::Iter;/n/n",
+ "expansion": null
+ }
+ ],
+ "children": [],
+ "rendered": null
+ }
+ ],
+ "rendered": null
+}
+{
+ "message": "aborting due to previous error",
+ "code": null,
+ "level": "error",
+ "spans": [],
+ "children": [],
+ "rendered": null
+}
fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String {
let parent_dir = self.testpaths.file.parent().unwrap();
let cflags = self.props.compile_flags.join(" ");
- let parent_dir_str = if cflags.contains("--error-format json") {
+ let parent_dir_str = if cflags.contains("--error-format json")
+ || cflags.contains("--error-format pretty-json") {
parent_dir.display().to_string().replace("\\", "\\\\")
} else {
parent_dir.display().to_string()