diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index fde40b0d1b407..96aed7293450c 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -156,8 +156,10 @@ impl Step for Llvm { .define("LLVM_DEFAULT_TARGET_TRIPLE", target); if builder.config.llvm_thin_lto && !emscripten { - cfg.define("LLVM_ENABLE_LTO", "Thin") - .define("LLVM_ENABLE_LLD", "ON"); + cfg.define("LLVM_ENABLE_LTO", "Thin"); + if !target.contains("apple") { + cfg.define("LLVM_ENABLE_LLD", "ON"); + } } // By default, LLVM will automatically find OCaml and, if it finds it, diff --git a/src/liballoc/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs index 0930f8dacd494..0685fa943c0b8 100644 --- a/src/liballoc/tests/binary_heap.rs +++ b/src/liballoc/tests/binary_heap.rs @@ -282,7 +282,7 @@ fn assert_covariance() { // // Destructors must be called exactly once per element. #[test] -#[cfg(not(miri))] // Miri does not support panics nor entropy +#[cfg(not(miri))] // Miri does not support catching panics fn panic_safe() { static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index b54c128a0249a..ad2cd7c95eb8f 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -389,7 +389,7 @@ fn test_reverse() { } #[test] -#[cfg(not(miri))] // Miri does not support entropy +#[cfg(not(miri))] // Miri is too slow fn test_sort() { let mut rng = thread_rng(); @@ -466,10 +466,19 @@ fn test_sort() { } #[test] -#[cfg(not(miri))] // Miri does not support entropy fn test_sort_stability() { - for len in (2..25).chain(500..510) { - for _ in 0..10 { + #[cfg(not(miri))] // Miri is too slow + let large_range = 500..510; + #[cfg(not(miri))] // Miri is too slow + let rounds = 10; + + #[cfg(miri)] + let large_range = 0..0; // empty range + #[cfg(miri)] + let rounds = 1; + + for len in (2..25).chain(large_range) { + for _ in 0..rounds { let mut counts = [0; 10]; // create a vector like [(6, 1), (5, 1), (6, 2), ...], @@ -1397,7 +1406,7 @@ fn test_box_slice_clone() { #[test] #[allow(unused_must_use)] // here, we care about the side effects of `.clone()` #[cfg_attr(target_os = "emscripten", ignore)] -#[cfg(not(miri))] // Miri does not support threads nor entropy +#[cfg(not(miri))] // Miri does not support threads fn test_box_slice_clone_panics() { use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -1589,7 +1598,7 @@ thread_local!(static SILENCE_PANIC: Cell = Cell::new(false)); #[test] #[cfg_attr(target_os = "emscripten", ignore)] // no threads -#[cfg(not(miri))] // Miri does not support threads nor entropy +#[cfg(not(miri))] // Miri does not support threads fn panic_safe() { let prev = panic::take_hook(); panic::set_hook(Box::new(move |info| { diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 007283b5f69c8..acf6b03791f01 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -1024,22 +1024,31 @@ fn test_rotate_right() { #[test] #[cfg(not(target_arch = "wasm32"))] -#[cfg(not(miri))] // Miri does not support entropy fn sort_unstable() { use core::cmp::Ordering::{Equal, Greater, Less}; use core::slice::heapsort; use rand::{FromEntropy, Rng, rngs::SmallRng, seq::SliceRandom}; + #[cfg(not(miri))] // Miri is too slow + let large_range = 500..510; + #[cfg(not(miri))] // Miri is too slow + let rounds = 100; + + #[cfg(miri)] + let large_range = 0..0; // empty range + #[cfg(miri)] + let rounds = 1; + let mut v = [0; 600]; let mut tmp = [0; 600]; let mut rng = SmallRng::from_entropy(); - for len in (2..25).chain(500..510) { + for len in (2..25).chain(large_range) { let v = &mut v[0..len]; let tmp = &mut tmp[0..len]; for &modulus in &[5, 10, 100, 1000] { - for _ in 0..100 { + for _ in 0..rounds { for i in 0..len { v[i] = rng.gen::() % modulus; } @@ -1095,7 +1104,7 @@ fn sort_unstable() { #[test] #[cfg(not(target_arch = "wasm32"))] -#[cfg(not(miri))] // Miri does not support entropy +#[cfg(not(miri))] // Miri is too slow fn partition_at_index() { use core::cmp::Ordering::{Equal, Greater, Less}; use rand::rngs::SmallRng; diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 80fef910cc718..ca5feaee12ee4 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -45,12 +45,10 @@ pub struct Allocation { } -pub trait AllocationExtra: ::std::fmt::Debug + Clone { - /// Hook to initialize the extra data when an allocation gets created. - fn memory_allocated( - _size: Size, - _memory_extra: &MemoryExtra - ) -> Self; +pub trait AllocationExtra: ::std::fmt::Debug + Clone { + // There is no constructor in here because the constructor's type depends + // on `MemoryKind`, and making things sufficiently generic leads to painful + // inference failure. /// Hook for performing extra checks on a memory read access. /// @@ -88,15 +86,8 @@ pub trait AllocationExtra: ::std::fmt::Debug + Clone { } } -impl AllocationExtra<(), ()> for () { - #[inline(always)] - fn memory_allocated( - _size: Size, - _memory_extra: &() - ) -> Self { - () - } -} +// For Tag=() and no extra state, we have is a trivial implementation. +impl AllocationExtra<()> for () { } impl Allocation { /// Creates a read-only allocation initialized by the given bytes @@ -159,7 +150,7 @@ impl<'tcx, Tag, Extra> Allocation { } /// Byte accessors -impl<'tcx, Tag: Copy, Extra> Allocation { +impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// The last argument controls whether we error out when there are undefined /// or pointer bytes. You should never call this, call `get_bytes` or /// `get_bytes_with_undef_and_ptr` instead, @@ -167,15 +158,13 @@ impl<'tcx, Tag: Copy, Extra> Allocation { /// This function also guarantees that the resulting pointer will remain stable /// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies /// on that. - fn get_bytes_internal( + fn get_bytes_internal( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, check_defined_and_ptr: bool, ) -> EvalResult<'tcx, &[u8]> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { self.check_bounds(cx, ptr, size)?; @@ -196,14 +185,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation { } #[inline] - pub fn get_bytes( + pub fn get_bytes( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, ) -> EvalResult<'tcx, &[u8]> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { self.get_bytes_internal(cx, ptr, size, true) } @@ -211,28 +198,24 @@ impl<'tcx, Tag: Copy, Extra> Allocation { /// It is the caller's responsibility to handle undefined and pointer bytes. /// However, this still checks that there are no relocations on the *edges*. #[inline] - pub fn get_bytes_with_undef_and_ptr( + pub fn get_bytes_with_undef_and_ptr( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, ) -> EvalResult<'tcx, &[u8]> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { self.get_bytes_internal(cx, ptr, size, false) } /// Just calling this already marks everything as defined and removes relocations, /// so be sure to actually put data there! - pub fn get_bytes_mut( + pub fn get_bytes_mut( &mut self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, ) -> EvalResult<'tcx, &mut [u8]> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { assert_ne!(size.bytes(), 0, "0-sized accesses should never even get a `Pointer`"); self.check_bounds(cx, ptr, size)?; @@ -250,16 +233,14 @@ impl<'tcx, Tag: Copy, Extra> Allocation { } /// Reading and writing -impl<'tcx, Tag: Copy, Extra> Allocation { +impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { /// Reads bytes until a `0` is encountered. Will error if the end of the allocation is reached /// before a `0` is found. - pub fn read_c_str( + pub fn read_c_str( &self, cx: &impl HasDataLayout, ptr: Pointer, ) -> EvalResult<'tcx, &[u8]> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes()); let offset = ptr.offset.bytes() as usize; @@ -278,15 +259,13 @@ impl<'tcx, Tag: Copy, Extra> Allocation { /// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a /// relocation. If `allow_ptr_and_undef` is `false`, also enforces that the memory in the /// given range contains neither relocations nor undef bytes. - pub fn check_bytes( + pub fn check_bytes( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size, allow_ptr_and_undef: bool, ) -> EvalResult<'tcx> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { // Check bounds and relocations on the edges self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; @@ -301,14 +280,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation { /// Writes `src` to the memory starting at `ptr.offset`. /// /// Will do bounds checks on the allocation. - pub fn write_bytes( + pub fn write_bytes( &mut self, cx: &impl HasDataLayout, ptr: Pointer, src: &[u8], ) -> EvalResult<'tcx> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { let bytes = self.get_bytes_mut(cx, ptr, Size::from_bytes(src.len() as u64))?; bytes.clone_from_slice(src); @@ -316,15 +293,13 @@ impl<'tcx, Tag: Copy, Extra> Allocation { } /// Sets `count` bytes starting at `ptr.offset` with `val`. Basically `memset`. - pub fn write_repeat( + pub fn write_repeat( &mut self, cx: &impl HasDataLayout, ptr: Pointer, val: u8, count: Size ) -> EvalResult<'tcx> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { let bytes = self.get_bytes_mut(cx, ptr, count)?; for b in bytes { @@ -341,14 +316,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation { /// being valid for ZSTs /// /// Note: This function does not do *any* alignment checks, you need to do these before calling - pub fn read_scalar( + pub fn read_scalar( &self, cx: &impl HasDataLayout, ptr: Pointer, size: Size ) -> EvalResult<'tcx, ScalarMaybeUndef> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { // get_bytes_unchecked tests relocation edges let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?; @@ -379,13 +352,11 @@ impl<'tcx, Tag: Copy, Extra> Allocation { } /// Note: This function does not do *any* alignment checks, you need to do these before calling - pub fn read_ptr_sized( + pub fn read_ptr_sized( &self, cx: &impl HasDataLayout, ptr: Pointer, ) -> EvalResult<'tcx, ScalarMaybeUndef> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { self.read_scalar(cx, ptr, cx.data_layout().pointer_size) } @@ -398,15 +369,13 @@ impl<'tcx, Tag: Copy, Extra> Allocation { /// being valid for ZSTs /// /// Note: This function does not do *any* alignment checks, you need to do these before calling - pub fn write_scalar( + pub fn write_scalar( &mut self, cx: &impl HasDataLayout, ptr: Pointer, val: ScalarMaybeUndef, type_size: Size, ) -> EvalResult<'tcx> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { let val = match val { ScalarMaybeUndef::Scalar(scalar) => scalar, @@ -446,14 +415,12 @@ impl<'tcx, Tag: Copy, Extra> Allocation { } /// Note: This function does not do *any* alignment checks, you need to do these before calling - pub fn write_ptr_sized( + pub fn write_ptr_sized( &mut self, cx: &impl HasDataLayout, ptr: Pointer, val: ScalarMaybeUndef ) -> EvalResult<'tcx> - // FIXME: Working around https://github.com/rust-lang/rust/issues/56209 - where Extra: AllocationExtra { let ptr_size = cx.data_layout().pointer_size; self.write_scalar(cx, ptr.into(), val, ptr_size) diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index 9216cb494cef9..75e0f704a5854 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -94,11 +94,17 @@ impl<'tcx> Pointer<()> { Pointer { alloc_id, offset, tag: () } } + #[inline(always)] + pub fn with_tag(self, tag: Tag) -> Pointer + { + Pointer::new_with_tag(self.alloc_id, self.offset, tag) + } + #[inline(always)] pub fn with_default_tag(self) -> Pointer where Tag: Default { - Pointer::new_with_tag(self.alloc_id, self.offset, Default::default()) + self.with_tag(Tag::default()) } } diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 7b47c02de1b54..18c82ecd38edc 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -119,14 +119,19 @@ impl fmt::Display for Scalar { impl<'tcx> Scalar<()> { #[inline] - pub fn with_default_tag(self) -> Scalar - where Tag: Default - { + pub fn with_tag(self, new_tag: Tag) -> Scalar { match self { - Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_default_tag()), + Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_tag(new_tag)), Scalar::Bits { bits, size } => Scalar::Bits { bits, size }, } } + + #[inline(always)] + pub fn with_default_tag(self) -> Scalar + where Tag: Default + { + self.with_tag(Tag::default()) + } } impl<'tcx, Tag> Scalar { @@ -138,14 +143,6 @@ impl<'tcx, Tag> Scalar { } } - #[inline] - pub fn with_tag(self, new_tag: Tag) -> Self { - match self { - Scalar::Ptr(ptr) => Scalar::Ptr(Pointer { tag: new_tag, ..ptr }), - Scalar::Bits { bits, size } => Scalar::Bits { bits, size }, - } - } - #[inline] pub fn ptr_null(cx: &impl HasDataLayout) -> Self { Scalar::Bits { @@ -434,14 +431,19 @@ impl fmt::Display for ScalarMaybeUndef { impl<'tcx> ScalarMaybeUndef<()> { #[inline] - pub fn with_default_tag(self) -> ScalarMaybeUndef - where Tag: Default - { + pub fn with_tag(self, new_tag: Tag) -> ScalarMaybeUndef { match self { - ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.with_default_tag()), + ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.with_tag(new_tag)), ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef, } } + + #[inline(always)] + pub fn with_default_tag(self) -> ScalarMaybeUndef + where Tag: Default + { + self.with_tag(Tag::default()) + } } impl<'tcx, Tag> ScalarMaybeUndef { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index d3a734cbc6ead..dc1ceaf69f013 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -19,6 +19,7 @@ use syntax::parse::token; use syntax::parse; use syntax::symbol::Symbol; use syntax::feature_gate::UnstableFeatures; +use errors::emitter::HumanReadableErrorType; use errors::{ColorConfig, FatalError, Handler}; @@ -219,14 +220,18 @@ impl OutputType { #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum ErrorOutputType { - HumanReadable(ColorConfig), - Json(bool), - Short(ColorConfig), + HumanReadable(HumanReadableErrorType), + Json { + /// Render the json in a human readable way (with indents and newlines) + pretty: bool, + /// The way the `rendered` field is created + json_rendered: HumanReadableErrorType, + }, } impl Default for ErrorOutputType { fn default() -> ErrorOutputType { - ErrorOutputType::HumanReadable(ColorConfig::Auto) + ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto)) } } @@ -1372,6 +1377,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "print some statistics about AST and HIR"), always_encode_mir: bool = (false, parse_bool, [TRACKED], "encode MIR of all functions into the crate metadata"), + json_rendered: Option = (None, parse_opt_string, [UNTRACKED], + "describes how to render the `rendered` field of json diagnostics"), unleash_the_miri_inside_of_you: bool = (false, parse_bool, [TRACKED], "take the breaks off const evaluation. NOTE: this is unsound"), osx_rpath_install_name: bool = (false, parse_bool, [TRACKED], @@ -1825,6 +1832,12 @@ pub fn rustc_optgroups() -> Vec { "How errors and other messages are produced", "human|json|short", ), + opt::opt( + "", + "json-rendered", + "Choose `rendered` field of json diagnostics render scheme", + "plain|termcolor", + ), opt::opt_s( "", "color", @@ -1965,6 +1978,17 @@ pub fn build_session_options_and_crate_config( ) } + let json_rendered = matches.opt_str("json-rendered").and_then(|s| match s.as_str() { + "plain" => None, + "termcolor" => Some(HumanReadableErrorType::Default(ColorConfig::Always)), + _ => early_error( + ErrorOutputType::default(), + &format!( + "argument for --json-rendered must be `plain` or `termcolor` (instead was `{}`)", + s, + ), + ), + }).unwrap_or(HumanReadableErrorType::Default(ColorConfig::Never)); // We need the opts_present check because the driver will send us Matches // with only stable options if no unstable options are used. Since error-format @@ -1972,14 +1996,14 @@ pub fn build_session_options_and_crate_config( // opt_present because the latter will panic. 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(false), - Some("pretty-json") => ErrorOutputType::Json(true), - Some("short") => ErrorOutputType::Short(color), - None => ErrorOutputType::HumanReadable(color), + None | + Some("human") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), + Some("json") => ErrorOutputType::Json { pretty: false, json_rendered }, + Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered }, + Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)), Some(arg) => early_error( - ErrorOutputType::HumanReadable(color), + ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), &format!( "argument for --error-format must be `human`, `json` or \ `short` (instead was `{}`)", @@ -1988,7 +2012,7 @@ pub fn build_session_options_and_crate_config( ), } } else { - ErrorOutputType::HumanReadable(color) + ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) }; let unparsed_crate_types = matches.opt_strs("crate-type"); @@ -2000,11 +2024,16 @@ pub fn build_session_options_and_crate_config( let mut 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", - ); + if !debugging_opts.unstable_options { + if matches.opt_str("json-rendered").is_some() { + early_error(error_format, "`--json-rendered=x` is unstable"); + } + if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format { + early_error( + ErrorOutputType::Json { pretty: false, json_rendered }, + "--error-format=pretty-json is unstable", + ); + } } if debugging_opts.pgo_gen.enabled() && !debugging_opts.pgo_use.is_empty() { @@ -2928,50 +2957,55 @@ mod tests { let mut v3 = Options::default(); let mut v4 = Options::default(); + const JSON: super::ErrorOutputType = super::ErrorOutputType::Json { + pretty: false, + json_rendered: super::HumanReadableErrorType::Default(super::ColorConfig::Never), + }; + // Reference v1.search_paths - .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("native=abc", JSON)); v1.search_paths - .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("crate=def", JSON)); v1.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); v1.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); v1.search_paths - .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("all=mno", JSON)); v2.search_paths - .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("native=abc", JSON)); v2.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); v2.search_paths - .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("crate=def", JSON)); v2.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); v2.search_paths - .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("all=mno", JSON)); v3.search_paths - .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("crate=def", JSON)); v3.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); v3.search_paths - .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("native=abc", JSON)); v3.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); v3.search_paths - .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("all=mno", JSON)); v4.search_paths - .push(SearchPath::from_cli_opt("all=mno", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("all=mno", JSON)); v4.search_paths - .push(SearchPath::from_cli_opt("native=abc", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("native=abc", JSON)); v4.search_paths - .push(SearchPath::from_cli_opt("crate=def", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("crate=def", JSON)); v4.search_paths - .push(SearchPath::from_cli_opt("dependency=ghi", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("dependency=ghi", JSON)); v4.search_paths - .push(SearchPath::from_cli_opt("framework=jkl", super::ErrorOutputType::Json(false))); + .push(SearchPath::from_cli_opt("framework=jkl", JSON)); assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash()); assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash()); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index a1966c02683e9..eed516a438175 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -1033,39 +1033,42 @@ fn default_emitter( emitter_dest: Option>, ) -> Box { match (sopts.error_format, emitter_dest) { - (config::ErrorOutputType::HumanReadable(color_config), None) => Box::new( - EmitterWriter::stderr( - color_config, - Some(source_map.clone()), - false, - sopts.debugging_opts.teach, - ).ui_testing(sopts.debugging_opts.ui_testing), - ), - (config::ErrorOutputType::HumanReadable(_), Some(dst)) => Box::new( - EmitterWriter::new(dst, Some(source_map.clone()), false, false) - .ui_testing(sopts.debugging_opts.ui_testing), - ), - (config::ErrorOutputType::Json(pretty), None) => Box::new( + (config::ErrorOutputType::HumanReadable(kind), dst) => { + let (short, color_config) = kind.unzip(); + let emitter = match dst { + None => EmitterWriter::stderr( + color_config, + Some(source_map.clone()), + short, + sopts.debugging_opts.teach, + ), + Some(dst) => EmitterWriter::new( + dst, + Some(source_map.clone()), + short, + false, // no teach messages when writing to a buffer + false, // no colors when writing to a buffer + ), + }; + Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing)) + }, + (config::ErrorOutputType::Json { pretty, json_rendered }, None) => Box::new( JsonEmitter::stderr( Some(registry), source_map.clone(), pretty, + json_rendered, ).ui_testing(sopts.debugging_opts.ui_testing), ), - (config::ErrorOutputType::Json(pretty), Some(dst)) => Box::new( + (config::ErrorOutputType::Json { pretty, json_rendered }, Some(dst)) => Box::new( JsonEmitter::new( dst, Some(registry), source_map.clone(), pretty, + json_rendered, ).ui_testing(sopts.debugging_opts.ui_testing), ), - (config::ErrorOutputType::Short(color_config), None) => Box::new( - EmitterWriter::stderr(color_config, Some(source_map.clone()), true, false), - ), - (config::ErrorOutputType::Short(_), Some(dst)) => { - Box::new(EmitterWriter::new(dst, Some(source_map.clone()), true, false)) - } } } @@ -1322,13 +1325,12 @@ pub enum IncrCompSession { pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { let emitter: Box = match output { - config::ErrorOutputType::HumanReadable(color_config) => { - Box::new(EmitterWriter::stderr(color_config, None, false, false)) - } - config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)), - config::ErrorOutputType::Short(color_config) => { - Box::new(EmitterWriter::stderr(color_config, None, true, false)) + config::ErrorOutputType::HumanReadable(kind) => { + let (short, color_config) = kind.unzip(); + Box::new(EmitterWriter::stderr(color_config, None, short, false)) } + config::ErrorOutputType::Json { pretty, json_rendered } => + Box::new(JsonEmitter::basic(pretty, json_rendered)), }; let handler = errors::Handler::with_emitter(true, None, emitter); handler.emit(&MultiSpan::new(), msg, errors::Level::Fatal); @@ -1337,13 +1339,12 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { pub fn early_warn(output: config::ErrorOutputType, msg: &str) { let emitter: Box = match output { - config::ErrorOutputType::HumanReadable(color_config) => { - Box::new(EmitterWriter::stderr(color_config, None, false, false)) - } - config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)), - config::ErrorOutputType::Short(color_config) => { - Box::new(EmitterWriter::stderr(color_config, None, true, false)) + config::ErrorOutputType::HumanReadable(kind) => { + let (short, color_config) = kind.unzip(); + Box::new(EmitterWriter::stderr(color_config, None, short, false)) } + config::ErrorOutputType::Json { pretty, json_rendered } => + Box::new(JsonEmitter::basic(pretty, json_rendered)), }; let handler = errors::Handler::with_emitter(true, None, emitter); handler.emit(&MultiSpan::new(), msg, errors::Level::Warning); diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index ee2a1b69cbd01..a1472479afa89 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -16,9 +16,35 @@ use std::borrow::Cow; use std::io::prelude::*; use std::io; use std::cmp::{min, Reverse}; -use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter}; +use termcolor::{StandardStream, ColorChoice, ColorSpec, BufferWriter, Ansi}; use termcolor::{WriteColor, Color, Buffer}; +/// Describes the way the content of the `rendered` field of the json output is generated +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum HumanReadableErrorType { + Default(ColorConfig), + Short(ColorConfig), +} + +impl HumanReadableErrorType { + /// Returns a (`short`, `color`) tuple + pub fn unzip(self) -> (bool, ColorConfig) { + match self { + HumanReadableErrorType::Default(cc) => (false, cc), + HumanReadableErrorType::Short(cc) => (true, cc), + } + } + pub fn new_emitter( + self, + dst: Box, + source_map: Option>, + teach: bool, + ) -> EmitterWriter { + let (short, color_config) = self.unzip(); + EmitterWriter::new(dst, source_map, short, teach, color_config.suggests_using_colors()) + } +} + const ANONYMIZED_LINE_NUM: &str = "LL"; /// Emitter trait for emitting errors. @@ -104,8 +130,8 @@ pub enum ColorConfig { } impl ColorConfig { - fn to_color_choice(&self) -> ColorChoice { - match *self { + fn to_color_choice(self) -> ColorChoice { + match self { ColorConfig::Always => { if atty::is(atty::Stream::Stderr) { ColorChoice::Always @@ -120,6 +146,14 @@ impl ColorConfig { ColorConfig::Auto => ColorChoice::Never, } } + fn suggests_using_colors(self) -> bool { + match self { + | ColorConfig::Always + | ColorConfig::Auto + => true, + ColorConfig::Never => false, + } + } } pub struct EmitterWriter { @@ -152,13 +186,15 @@ impl EmitterWriter { } } - pub fn new(dst: Box, - source_map: Option>, - short_message: bool, - teach: bool) - -> EmitterWriter { + pub fn new( + dst: Box, + source_map: Option>, + short_message: bool, + teach: bool, + colored: bool, + ) -> EmitterWriter { EmitterWriter { - dst: Raw(dst), + dst: Raw(dst, colored), sm: source_map, short_message, teach, @@ -1538,13 +1574,15 @@ fn emit_to_destination(rendered_buffer: &[Vec], pub enum Destination { Terminal(StandardStream), Buffered(BufferWriter), - Raw(Box), + // The bool denotes whether we should be emitting ansi color codes or not + Raw(Box<(dyn Write + Send)>, bool), } pub enum WritableDst<'a> { Terminal(&'a mut StandardStream), Buffered(&'a mut BufferWriter, Buffer), - Raw(&'a mut Box), + Raw(&'a mut (dyn Write + Send)), + ColoredRaw(Ansi<&'a mut (dyn Write + Send)>), } impl Destination { @@ -1570,7 +1608,8 @@ impl Destination { let buf = t.buffer(); WritableDst::Buffered(t, buf) } - Destination::Raw(ref mut t) => WritableDst::Raw(t), + Destination::Raw(ref mut t, false) => WritableDst::Raw(t), + Destination::Raw(ref mut t, true) => WritableDst::ColoredRaw(Ansi::new(t)), } } } @@ -1628,6 +1667,7 @@ impl<'a> WritableDst<'a> { match *self { WritableDst::Terminal(ref mut t) => t.set_color(color), WritableDst::Buffered(_, ref mut t) => t.set_color(color), + WritableDst::ColoredRaw(ref mut t) => t.set_color(color), WritableDst::Raw(_) => Ok(()) } } @@ -1636,6 +1676,7 @@ impl<'a> WritableDst<'a> { match *self { WritableDst::Terminal(ref mut t) => t.reset(), WritableDst::Buffered(_, ref mut t) => t.reset(), + WritableDst::ColoredRaw(ref mut t) => t.reset(), WritableDst::Raw(_) => Ok(()), } } @@ -1647,6 +1688,7 @@ impl<'a> Write for WritableDst<'a> { WritableDst::Terminal(ref mut t) => t.write(bytes), WritableDst::Buffered(_, ref mut buf) => buf.write(bytes), WritableDst::Raw(ref mut w) => w.write(bytes), + WritableDst::ColoredRaw(ref mut t) => t.write(bytes), } } @@ -1655,6 +1697,7 @@ impl<'a> Write for WritableDst<'a> { WritableDst::Terminal(ref mut t) => t.flush(), WritableDst::Buffered(_, ref mut buf) => buf.flush(), WritableDst::Raw(ref mut w) => w.flush(), + WritableDst::ColoredRaw(ref mut w) => w.flush(), } } } diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 4c8ab361e04ea..09c50d4f81f49 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -11,7 +11,7 @@ use rustc::hir::def::Def; use rustc::mir::interpret::{ConstEvalErr, ErrorHandled}; use rustc::mir; use rustc::ty::{self, TyCtxt, query::TyCtxtAt}; -use rustc::ty::layout::{self, LayoutOf, VariantIdx}; +use rustc::ty::layout::{self, LayoutOf, VariantIdx, Size}; use rustc::ty::subst::Subst; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; @@ -21,7 +21,7 @@ use syntax::ast::Mutability; use syntax::source_map::{Span, DUMMY_SP}; use crate::interpret::{self, - PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Immediate, Scalar, Pointer, + PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Immediate, Scalar, RawConst, ConstValue, EvalResult, EvalError, InterpError, GlobalId, InterpretCx, StackPopCleanup, Allocation, AllocId, MemoryKind, @@ -406,6 +406,15 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> Cow::Borrowed(alloc) } + #[inline(always)] + fn new_allocation( + _size: Size, + _extra: &Self::MemoryExtra, + _kind: MemoryKind, + ) -> (Self::AllocExtra, Self::PointerTag) { + ((), ()) + } + fn box_alloc( _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, _dest: PlaceTy<'tcx>, @@ -439,15 +448,6 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx> ) } - #[inline(always)] - fn tag_new_allocation( - _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, - ptr: Pointer, - _kind: MemoryKind, - ) -> Pointer { - ptr - } - #[inline(always)] fn stack_push( _ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 09d403ab243d6..288ffbf3cd616 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -7,11 +7,11 @@ use std::hash::Hash; use rustc::hir::{self, def_id::DefId}; use rustc::mir; -use rustc::ty::{self, query::TyCtxtAt}; +use rustc::ty::{self, query::TyCtxtAt, layout::Size}; use super::{ Allocation, AllocId, EvalResult, Scalar, AllocationExtra, - InterpretCx, PlaceTy, MPlaceTy, OpTy, ImmTy, Pointer, MemoryKind, + InterpretCx, PlaceTy, MPlaceTy, OpTy, ImmTy, MemoryKind, }; /// Whether this kind of memory is allowed to leak @@ -76,7 +76,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { type MemoryExtra: Default; /// Extra data stored in every allocation. - type AllocExtra: AllocationExtra + 'static; + type AllocExtra: AllocationExtra + 'static; /// Memory's allocation map type MemoryMap: @@ -139,18 +139,6 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { memory_extra: &Self::MemoryExtra, ) -> EvalResult<'tcx, Cow<'tcx, Allocation>>; - /// Called to turn an allocation obtained from the `tcx` into one that has - /// the right type for this machine. - /// - /// This should avoid copying if no work has to be done! If this returns an owned - /// allocation (because a copy had to be done to add tags or metadata), machine memory will - /// cache the result. (This relies on `AllocMap::get_or` being able to add the - /// owned allocation to the map even when the map is shared.) - fn adjust_static_allocation<'b>( - alloc: &'b Allocation, - memory_extra: &Self::MemoryExtra, - ) -> Cow<'b, Allocation>; - /// Called for all binary operations on integer(-like) types when one operand is a pointer /// value, and for the `Offset` operation that is inherently about pointers. /// @@ -168,12 +156,24 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized { dest: PlaceTy<'tcx, Self::PointerTag>, ) -> EvalResult<'tcx>; - /// Adds the tag for a newly allocated pointer. - fn tag_new_allocation( - ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>, - ptr: Pointer, + /// Called to turn an allocation obtained from the `tcx` into one that has + /// the right type for this machine. + /// + /// This should avoid copying if no work has to be done! If this returns an owned + /// allocation (because a copy had to be done to add tags or metadata), machine memory will + /// cache the result. (This relies on `AllocMap::get_or` being able to add the + /// owned allocation to the map even when the map is shared.) + fn adjust_static_allocation<'b>( + alloc: &'b Allocation, + memory_extra: &Self::MemoryExtra, + ) -> Cow<'b, Allocation>; + + /// Computes the extra state and the tag for a new allocation. + fn new_allocation( + size: Size, + extra: &Self::MemoryExtra, kind: MemoryKind, - ) -> Pointer; + ) -> (Self::AllocExtra, Self::PointerTag); /// Executed when evaluating the `*` operator: Following a reference. /// This has the chance to adjust the tag. It should not change anything else! diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index e5d8341dfcf6d..117bd15399cde 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -132,9 +132,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { size: Size, align: Align, kind: MemoryKind, - ) -> Pointer { - let extra = AllocationExtra::memory_allocated(size, &self.extra); - Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)) + ) -> Pointer { + let (extra, tag) = M::new_allocation(size, &self.extra, kind); + Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)).with_tag(tag) } pub fn reallocate( @@ -145,7 +145,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { new_size: Size, new_align: Align, kind: MemoryKind, - ) -> EvalResult<'tcx, Pointer> { + ) -> EvalResult<'tcx, Pointer> { if ptr.offset.bytes() != 0 { return err!(ReallocateNonBasePtr); } @@ -156,7 +156,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { self.copy( ptr.into(), old_align, - new_ptr.with_default_tag().into(), + new_ptr.into(), new_align, old_size.min(new_size), /*nonoverlapping*/ true, diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 1ce6d09d7a4e0..55c1bfb17dec3 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -31,19 +31,6 @@ pub enum Immediate { ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef), } -impl Immediate { - #[inline] - pub fn with_default_tag(self) -> Immediate - where Tag: Default - { - match self { - Immediate::Scalar(x) => Immediate::Scalar(x.with_default_tag()), - Immediate::ScalarPair(x, y) => - Immediate::ScalarPair(x.with_default_tag(), y.with_default_tag()), - } - } -} - impl<'tcx, Tag> Immediate { #[inline] pub fn from_scalar(val: Scalar) -> Self { @@ -142,18 +129,6 @@ pub enum Operand { Indirect(MemPlace), } -impl Operand { - #[inline] - pub fn with_default_tag(self) -> Operand - where Tag: Default - { - match self { - Operand::Immediate(x) => Operand::Immediate(x.with_default_tag()), - Operand::Indirect(x) => Operand::Indirect(x.with_default_tag()), - } - } -} - impl Operand { #[inline] pub fn erase_tag(self) -> Operand @@ -554,16 +529,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> // We rely on mutability being set correctly in that allocation to prevent writes // where none should happen -- and for `static mut`, we copy on demand anyway. Operand::Indirect( - MemPlace::from_ptr(ptr, alloc.align) - ).with_default_tag() + MemPlace::from_ptr(ptr.with_default_tag(), alloc.align) + ) }, ConstValue::Slice(a, b) => Operand::Immediate(Immediate::ScalarPair( - a.into(), - Scalar::from_uint(b, self.tcx.data_layout.pointer_size).into(), - )).with_default_tag(), + a.with_default_tag().into(), + Scalar::from_uint(b, self.tcx.data_layout.pointer_size) + .with_default_tag().into(), + )), ConstValue::Scalar(x) => - Operand::Immediate(Immediate::Scalar(x.into())).with_default_tag(), + Operand::Immediate(Immediate::Scalar(x.with_default_tag().into())), ConstValue::Unevaluated(def_id, substs) => { let instance = self.resolve(def_id, substs)?; return Ok(OpTy::from(self.const_eval_raw(GlobalId { diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 32ad52746896f..8239337796e9a 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -83,23 +83,19 @@ impl<'tcx, Tag> From> for PlaceTy<'tcx, Tag> { } } -impl MemPlace { +impl MemPlace { + /// Replace ptr tag, maintain vtable tag (if any) #[inline] - pub fn with_default_tag(self) -> MemPlace - where Tag: Default - { + pub fn replace_tag(self, new_tag: Tag) -> Self { MemPlace { - ptr: self.ptr.with_default_tag(), + ptr: self.ptr.erase_tag().with_tag(new_tag), align: self.align, - meta: self.meta.map(Scalar::with_default_tag), + meta: self.meta, } } -} -impl MemPlace { #[inline] - pub fn erase_tag(self) -> MemPlace - { + pub fn erase_tag(self) -> MemPlace { MemPlace { ptr: self.ptr.erase_tag(), align: self.align, @@ -107,16 +103,6 @@ impl MemPlace { } } - #[inline] - pub fn with_tag(self, new_tag: Tag) -> Self - { - MemPlace { - ptr: self.ptr.with_tag(new_tag), - align: self.align, - meta: self.meta, - } - } - #[inline(always)] pub fn from_scalar_ptr(ptr: Scalar, align: Align) -> Self { MemPlace { @@ -189,11 +175,11 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { } } + /// Replace ptr tag, maintain vtable tag (if any) #[inline] - pub fn with_tag(self, new_tag: Tag) -> Self - { + pub fn replace_tag(self, new_tag: Tag) -> Self { MPlaceTy { - mplace: self.mplace.with_tag(new_tag), + mplace: self.mplace.replace_tag(new_tag), layout: self.layout, } } @@ -312,7 +298,7 @@ where M: Machine<'a, 'mir, 'tcx, PointerTag=Tag>, // FIXME: Working around https://github.com/rust-lang/rust/issues/24159 M::MemoryMap: AllocMap, Allocation)>, - M::AllocExtra: AllocationExtra, + M::AllocExtra: AllocationExtra, { /// Take a value, which represents a (thin or fat) reference, and make it a place. /// Alignment is just based on the type. This is the inverse of `MemPlace::to_ref()`. @@ -943,7 +929,6 @@ where let (size, align) = self.size_and_align_of(meta, local_layout)? .expect("Cannot allocate for non-dyn-sized type"); let ptr = self.memory.allocate(size, align, MemoryKind::Stack); - let ptr = M::tag_new_allocation(self, ptr, MemoryKind::Stack); let mplace = MemPlace { ptr: ptr.into(), align, meta }; if let Some(value) = old_val { // Preserve old value. @@ -981,7 +966,6 @@ where kind: MemoryKind, ) -> MPlaceTy<'tcx, M::PointerTag> { let ptr = self.memory.allocate(layout.size, layout.align.abi, kind); - let ptr = M::tag_new_allocation(self, ptr, kind); MPlaceTy::from_aligned_ptr(ptr, layout) } diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index a451f2afb4663..0bed62ccf500a 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -52,7 +52,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> ptr_size * (3 + methods.len() as u64), ptr_align, MemoryKind::Vtable, - ).with_default_tag(); + ); let tcx = &*self.tcx; let drop = crate::monomorphize::resolve_drop_in_place(*tcx, ty); diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 87459571b529c..7826d3da4fed2 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -326,7 +326,12 @@ fn check_terminator( abi::Abi::Rust if tcx.is_min_const_fn(def_id) => {}, abi::Abi::Rust => return Err(( span, - "can only call other `min_const_fn` within a `min_const_fn`".into(), + format!( + "can only call other `const fn` within a `const fn`, \ + but `{:?}` is not stable as `const fn`", + func, + ) + .into(), )), abi => return Err(( span, diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index a4d2a3be86330..769ea3ff7bc74 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -3,7 +3,7 @@ use std::fmt; use std::path::PathBuf; use errors; -use errors::emitter::ColorConfig; +use errors::emitter::{ColorConfig, HumanReadableErrorType}; use getopts; use rustc::lint::Level; use rustc::session::early_error; @@ -254,12 +254,19 @@ impl Options { (instead was `{}`)", arg)); } }; + // FIXME: deduplicate this code from the identical code in librustc/session/config.rs 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), + None | + Some("human") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), + Some("json") => ErrorOutputType::Json { + pretty: false, + json_rendered: HumanReadableErrorType::Default(ColorConfig::Never), + }, + Some("pretty-json") => ErrorOutputType::Json { + pretty: true, + json_rendered: HumanReadableErrorType::Default(ColorConfig::Never), + }, + Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)), Some(arg) => { early_error(ErrorOutputType::default(), &format!("argument for --error-format must be `human`, `json` or \ diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 3cf6b32b07c4c..c141b47481531 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -299,15 +299,18 @@ pub fn new_handler(error_format: ErrorOutputType, // stick to the defaults let sessopts = Options::default(); let emitter: Box = match error_format { - ErrorOutputType::HumanReadable(color_config) => Box::new( - EmitterWriter::stderr( - color_config, - source_map.map(|cm| cm as _), - false, - sessopts.debugging_opts.teach, - ).ui_testing(ui_testing) - ), - ErrorOutputType::Json(pretty) => { + ErrorOutputType::HumanReadable(kind) => { + let (short, color_config) = kind.unzip(); + Box::new( + EmitterWriter::stderr( + color_config, + source_map.map(|cm| cm as _), + short, + sessopts.debugging_opts.teach, + ).ui_testing(ui_testing) + ) + }, + ErrorOutputType::Json { pretty, json_rendered } => { let source_map = source_map.unwrap_or_else( || Lrc::new(source_map::SourceMap::new(sessopts.file_path_mapping()))); Box::new( @@ -315,16 +318,10 @@ pub fn new_handler(error_format: ErrorOutputType, None, source_map, pretty, + json_rendered, ).ui_testing(ui_testing) ) }, - ErrorOutputType::Short(color_config) => Box::new( - EmitterWriter::stderr( - color_config, - source_map.map(|cm| cm as _), - true, - false) - ), }; errors::Handler::with_emitter_and_flags( diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 0bbc7c5c4b223..abf74158c938e 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -381,7 +381,7 @@ pub fn make_test(s: &str, // Any errors in parsing should also appear when the doctest is compiled for real, so just // send all the errors that libsyntax emits directly into a `Sink` instead of stderr. let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); - let emitter = EmitterWriter::new(box io::sink(), None, false, false); + let emitter = EmitterWriter::new(box io::sink(), None, false, false, false); let handler = Handler::with_emitter(false, None, box emitter); let sess = ParseSess::with_span_handler(handler, cm); diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 838dfc626468c..c19b408442ad1 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -14,7 +14,7 @@ use crate::source_map::{SourceMap, FilePathMapping}; use errors::registry::Registry; use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, SourceMapper}; use errors::{DiagnosticId, Applicability}; -use errors::emitter::{Emitter, EmitterWriter}; +use errors::emitter::{Emitter, HumanReadableErrorType}; use syntax_pos::{MacroBacktrace, Span, SpanLabel, MultiSpan}; use rustc_data_structures::sync::{self, Lrc}; @@ -30,37 +30,46 @@ pub struct JsonEmitter { sm: Lrc, pretty: bool, ui_testing: bool, + json_rendered: HumanReadableErrorType, } impl JsonEmitter { - pub fn stderr(registry: Option, - source_map: Lrc, - pretty: bool) -> JsonEmitter { + pub fn stderr( + registry: Option, + source_map: Lrc, + pretty: bool, + json_rendered: HumanReadableErrorType, + ) -> JsonEmitter { JsonEmitter { dst: Box::new(io::stderr()), registry, sm: source_map, pretty, ui_testing: false, + json_rendered, } } - pub fn basic(pretty: bool) -> JsonEmitter { + pub fn basic(pretty: bool, json_rendered: HumanReadableErrorType) -> JsonEmitter { let file_path_mapping = FilePathMapping::empty(); JsonEmitter::stderr(None, Lrc::new(SourceMap::new(file_path_mapping)), - pretty) + pretty, json_rendered) } - pub fn new(dst: Box, - registry: Option, - source_map: Lrc, - pretty: bool) -> JsonEmitter { + pub fn new( + dst: Box, + registry: Option, + source_map: Lrc, + pretty: bool, + json_rendered: HumanReadableErrorType, + ) -> JsonEmitter { JsonEmitter { dst, registry, sm: source_map, pretty, ui_testing: false, + json_rendered, } } @@ -190,7 +199,7 @@ impl Diagnostic { } let buf = BufWriter::default(); let output = buf.clone(); - EmitterWriter::new(Box::new(buf), Some(je.sm.clone()), false, false) + je.json_rendered.new_emitter(Box::new(buf), Some(je.sm.clone()), false) .ui_testing(je.ui_testing).emit(db); let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 5557e281a6639..3b980fafc2f1c 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1920,6 +1920,7 @@ mod tests { let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()), Some(sm.clone()), false, + false, false); ParseSess { span_diagnostic: errors::Handler::with_emitter(true, None, Box::new(emitter)), diff --git a/src/libsyntax/test_snippet.rs b/src/libsyntax/test_snippet.rs index 86910ffd894c4..cba429068fd5b 100644 --- a/src/libsyntax/test_snippet.rs +++ b/src/libsyntax/test_snippet.rs @@ -57,6 +57,7 @@ fn test_harness(file_text: &str, span_labels: Vec, expected_output: & let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }), Some(source_map.clone()), false, + false, false); let handler = Handler::with_emitter(true, None, Box::new(emitter)); handler.span_err(msp, "foo"); diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs index db416e7eb03ac..759d9ab6a4081 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.rs @@ -12,14 +12,14 @@ const fn foo() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] // can't call non-min_const_fn -const fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn` +const fn bar() -> u32 { foo() } //~ ERROR can only call other `const fn` #[unstable(feature = "rust1", issue="0")] const fn foo2() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] // can't call non-min_const_fn -const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn` +const fn bar2() -> u32 { foo2() } //~ ERROR can only call other `const fn` #[stable(feature = "rust1", since = "1.0.0")] // conformity is required, even with `const_fn` feature gate @@ -31,6 +31,6 @@ const fn foo2_gated() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] // can't call non-min_const_fn -const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn` +const fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `const fn` fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr index a8d0dc37e4031..c73eda9ab9fc1 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_libstd_stability.stderr @@ -1,4 +1,4 @@ -error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563) +error[E0723]: can only call other `const fn` within a `const fn`, but `const foo` is not stable as `const fn` (see issue #57563) --> $DIR/min_const_fn_libstd_stability.rs:15:25 | LL | const fn bar() -> u32 { foo() } @@ -6,7 +6,7 @@ LL | const fn bar() -> u32 { foo() } | = help: add #![feature(const_fn)] to the crate attributes to enable -error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563) +error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2` is not stable as `const fn` (see issue #57563) --> $DIR/min_const_fn_libstd_stability.rs:22:26 | LL | const fn bar2() -> u32 { foo2() } @@ -22,7 +22,7 @@ LL | const fn bar3() -> u32 { (5f32 + 6f32) as u32 } | = help: add #![feature(const_fn)] to the crate attributes to enable -error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563) +error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2_gated` is not stable as `const fn` (see issue #57563) --> $DIR/min_const_fn_libstd_stability.rs:34:32 | LL | const fn bar2_gated() -> u32 { foo2_gated() } diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs index 7faba480a233e..64057b012b8df 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.rs @@ -12,14 +12,14 @@ const unsafe fn foo() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] // can't call non-min_const_fn -const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `min_const_fn` +const unsafe fn bar() -> u32 { unsafe { foo() } } //~ ERROR can only call other `const fn` #[unstable(feature = "rust1", issue="0")] const unsafe fn foo2() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] // can't call non-min_const_fn -const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call other `min_const_fn` +const unsafe fn bar2() -> u32 { unsafe { foo2() } } //~ ERROR can only call other `const fn` #[stable(feature = "rust1", since = "1.0.0")] // conformity is required, even with `const_fn` feature gate @@ -31,6 +31,7 @@ const unsafe fn foo2_gated() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] // can't call non-min_const_fn -const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } //~ ERROR can only call other +const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } +//~^ ERROR can only call other `const fn` fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr index 5b2bee19acf90..87b572dcc46f3 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability.stderr @@ -1,4 +1,4 @@ -error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563) +error[E0723]: can only call other `const fn` within a `const fn`, but `const foo` is not stable as `const fn` (see issue #57563) --> $DIR/min_const_unsafe_fn_libstd_stability.rs:15:41 | LL | const unsafe fn bar() -> u32 { unsafe { foo() } } @@ -6,7 +6,7 @@ LL | const unsafe fn bar() -> u32 { unsafe { foo() } } | = help: add #![feature(const_fn)] to the crate attributes to enable -error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563) +error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2` is not stable as `const fn` (see issue #57563) --> $DIR/min_const_unsafe_fn_libstd_stability.rs:22:42 | LL | const unsafe fn bar2() -> u32 { unsafe { foo2() } } @@ -22,7 +22,7 @@ LL | const unsafe fn bar3() -> u32 { (5f32 + 6f32) as u32 } | = help: add #![feature(const_fn)] to the crate attributes to enable -error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563) +error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2_gated` is not stable as `const fn` (see issue #57563) --> $DIR/min_const_unsafe_fn_libstd_stability.rs:34:48 | LL | const unsafe fn bar2_gated() -> u32 { unsafe { foo2_gated() } } diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs index bc1d5091f38d3..deb2cb6b619bb 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.rs @@ -12,14 +12,14 @@ const fn foo() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] // can't call non-min_const_fn -const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `min_const_fn` +const unsafe fn bar() -> u32 { foo() } //~ ERROR can only call other `const fn` #[unstable(feature = "rust1", issue="0")] const fn foo2() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] // can't call non-min_const_fn -const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `min_const_fn` +const unsafe fn bar2() -> u32 { foo2() } //~ ERROR can only call other `const fn` // check whether this function cannot be called even with the feature gate active #[unstable(feature = "foo2", issue="0")] @@ -27,6 +27,6 @@ const fn foo2_gated() -> u32 { 42 } #[stable(feature = "rust1", since = "1.0.0")] // can't call non-min_const_fn -const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `min_const_fn` +const unsafe fn bar2_gated() -> u32 { foo2_gated() } //~ ERROR can only call other `const fn` fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr index f7f630c9ae3f5..5fddc11975884 100644 --- a/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_unsafe_fn_libstd_stability2.stderr @@ -1,4 +1,4 @@ -error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563) +error[E0723]: can only call other `const fn` within a `const fn`, but `const foo` is not stable as `const fn` (see issue #57563) --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:15:32 | LL | const unsafe fn bar() -> u32 { foo() } @@ -6,7 +6,7 @@ LL | const unsafe fn bar() -> u32 { foo() } | = help: add #![feature(const_fn)] to the crate attributes to enable -error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563) +error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2` is not stable as `const fn` (see issue #57563) --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:22:33 | LL | const unsafe fn bar2() -> u32 { foo2() } @@ -14,7 +14,7 @@ LL | const unsafe fn bar2() -> u32 { foo2() } | = help: add #![feature(const_fn)] to the crate attributes to enable -error[E0723]: can only call other `min_const_fn` within a `min_const_fn` (see issue #57563) +error[E0723]: can only call other `const fn` within a `const fn`, but `const foo2_gated` is not stable as `const fn` (see issue #57563) --> $DIR/min_const_unsafe_fn_libstd_stability2.rs:30:39 | LL | const unsafe fn bar2_gated() -> u32 { foo2_gated() } diff --git a/src/test/ui/lint/use_suggestion_json.rs b/src/test/ui/lint/use_suggestion_json.rs index 3bdbaa55f2df8..9679ce4a2ae1d 100644 --- a/src/test/ui/lint/use_suggestion_json.rs +++ b/src/test/ui/lint/use_suggestion_json.rs @@ -1,5 +1,6 @@ // ignore-cloudabi -// compile-flags: --error-format pretty-json -Zunstable-options +// ignore-windows +// compile-flags: --error-format pretty-json -Zunstable-options --json-rendered=termcolor // The output for humans should just highlight the whole span without showing // the suggested replacement, but we also want to test that suggested diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr index dee7f2f9b160b..632666db75b66 100644 --- a/src/test/ui/lint/use_suggestion_json.stderr +++ b/src/test/ui/lint/use_suggestion_json.stderr @@ -73,10 +73,10 @@ mod foo { "spans": [ { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 440, - "byte_end": 444, - "line_start": 11, - "line_end": 11, + "byte_start": 484, + "byte_end": 488, + "line_start": 12, + "line_end": 12, "column_start": 12, "column_end": 16, "is_primary": true, @@ -101,10 +101,10 @@ mod foo { "spans": [ { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -124,10 +124,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -147,10 +147,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -170,10 +170,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -193,10 +193,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -216,10 +216,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -239,10 +239,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -262,10 +262,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -285,10 +285,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -308,10 +308,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -331,10 +331,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -354,10 +354,10 @@ mod foo { }, { "file_name": "$DIR/use_suggestion_json.rs", - "byte_start": 417, - "byte_end": 417, - "line_start": 10, - "line_end": 10, + "byte_start": 461, + "byte_end": 461, + "line_start": 11, + "line_end": 11, "column_start": 1, "column_end": 1, "is_primary": true, @@ -380,22 +380,22 @@ mod foo { "rendered": null } ], - "rendered": "error[E0412]: cannot find type `Iter` in this scope - --> $DIR/use_suggestion_json.rs:11:12 - | -LL | let x: Iter; - | ^^^^ not found in this scope -help: possible candidates are found in other modules, you can import them into scope - | -LL | use std::collections::binary_heap::Iter; - | -LL | use std::collections::btree_map::Iter; - | -LL | use std::collections::btree_set::Iter; - | -LL | use std::collections::hash_map::Iter; - | -and 8 other candidates + "rendered": "\u001b[0m\u001b[1m\u001b[38;5;9merror[E0412]\u001b[0m\u001b[0m\u001b[1m: cannot find type `Iter` in this scope\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0m$DIR/use_suggestion_json.rs:12:12\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m let x: Iter;\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mnot found in this scope\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: possible candidates are found in other modules, you can import them into scope\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0muse std::collections::binary_heap::Iter;\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0muse std::collections::btree_map::Iter;\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0muse std::collections::btree_set::Iter;\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0muse std::collections::hash_map::Iter;\u001b[0m +\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m +\u001b[0mand 8 other candidates\u001b[0m " } @@ -405,7 +405,7 @@ and 8 other candidates "level": "error", "spans": [], "children": [], - "rendered": "error: aborting due to previous error + "rendered": "\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: aborting due to previous error\u001b[0m " } @@ -415,6 +415,6 @@ and 8 other candidates "level": "", "spans": [], "children": [], - "rendered": "For more information about this error, try `rustc --explain E0412`. + "rendered": "\u001b[0m\u001b[1mFor more information about this error, try `rustc --explain E0412`.\u001b[0m " } diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index ba919f4c4118a..a7615f5f423a3 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -62,7 +62,7 @@ struct DiagnosticCode { explanation: Option, } -pub fn extract_rendered(output: &str, proc_res: &ProcRes) -> String { +pub fn extract_rendered(output: &str) -> String { output .lines() .filter_map(|line| { @@ -70,11 +70,12 @@ pub fn extract_rendered(output: &str, proc_res: &ProcRes) -> String { match serde_json::from_str::(line) { Ok(diagnostic) => diagnostic.rendered, Err(error) => { - proc_res.fatal(Some(&format!( + print!( "failed to decode compiler output as json: \ `{}`\nline: {}\noutput: {}", error, line, output - ))); + ); + panic!() } } } else { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 369bb3fefe574..6df56168973bb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2090,50 +2090,10 @@ impl<'test> TestCx<'test> { } fn fatal_proc_rec(&self, err: &str, proc_res: &ProcRes) -> ! { - self.try_print_open_handles(); self.error(err); proc_res.fatal(None); } - // This function is a poor man's attempt to debug rust-lang/rust#38620, if - // that's closed then this should be deleted - // - // This is a very "opportunistic" debugging attempt, so we ignore all - // errors here. - fn try_print_open_handles(&self) { - if !cfg!(windows) { - return; - } - if self.config.mode != Incremental { - return; - } - - let filename = match self.testpaths.file.file_stem() { - Some(path) => path, - None => return, - }; - - let mut cmd = Command::new("handle.exe"); - cmd.arg("-a").arg("-u"); - cmd.arg(filename); - cmd.arg("-nobanner"); - cmd.stdout(Stdio::piped()); - cmd.stderr(Stdio::piped()); - let output = match cmd.spawn().and_then(read2_abbreviated) { - Ok(output) => output, - Err(_) => return, - }; - println!("---------------------------------------------------"); - println!("ran extra command to debug rust-lang/rust#38620: "); - println!("{:?}", cmd); - println!("result: {}", output.status); - println!("--- stdout ----------------------------------------"); - println!("{}", String::from_utf8_lossy(&output.stdout)); - println!("--- stderr ----------------------------------------"); - println!("{}", String::from_utf8_lossy(&output.stderr)); - println!("---------------------------------------------------"); - } - // codegen tests (using FileCheck) fn compile_test_and_save_ir(&self) -> ProcRes { @@ -2844,7 +2804,7 @@ impl<'test> TestCx<'test> { let stderr = if explicit { proc_res.stderr.clone() } else { - json::extract_rendered(&proc_res.stderr, &proc_res) + json::extract_rendered(&proc_res.stderr) }; let normalized_stderr = self.normalize_output(&stderr, &self.props.normalize_stderr); @@ -3464,7 +3424,9 @@ impl ProcRes { {}\n\ ------------------------------------------\n\ \n", - self.status, self.cmdline, self.stdout, self.stderr + self.status, self.cmdline, + json::extract_rendered(&self.stdout), + json::extract_rendered(&self.stderr), ); // Use resume_unwind instead of panic!() to prevent a panic message + backtrace from // compiletest, which is unnecessary noise.