diff options
| author | bors <bors@rust-lang.org> | 2019-09-08 13:02:54 +0000 | 
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-09-08 13:02:54 +0000 | 
| commit | 2c0931e168671d7536b58563dc3664c948a8dcd3 (patch) | |
| tree | fbbcf77cf17fbaf2dcbab14dcce6ccd1cf7658da | |
| parent | 50362372d68eae9b02a351f0fab42962cd0518de (diff) | |
| parent | 832b47aee6a5922bebd052e3261a6f839fba6aee (diff) | |
| download | rust-2c0931e168671d7536b58563dc3664c948a8dcd3.tar.gz rust-2c0931e168671d7536b58563dc3664c948a8dcd3.zip  | |
Auto merge of #64281 - Centril:rollup-inyqjf8, r=Centril
Rollup of 4 pull requests Successful merges: - #62205 (Add Iterator comparison methods that take a comparison function) - #64152 (Use backtrace formatting from the backtrace crate) - #64265 (resolve: Mark more erroneous imports as used) - #64267 (rustdoc: fix diagnostic with mixed code block styles) Failed merges: r? @ghost
| -rw-r--r-- | Cargo.lock | 4 | ||||
| -rw-r--r-- | src/libcore/iter/traits/iterator.rs | 109 | ||||
| -rw-r--r-- | src/libcore/tests/iter.rs | 56 | ||||
| -rw-r--r-- | src/libcore/tests/lib.rs | 1 | ||||
| -rw-r--r-- | src/librustc_resolve/resolve_imports.rs | 8 | ||||
| -rw-r--r-- | src/librustdoc/html/markdown.rs | 5 | ||||
| -rw-r--r-- | src/libstd/Cargo.toml | 2 | ||||
| -rw-r--r-- | src/libstd/panicking.rs | 8 | ||||
| -rw-r--r-- | src/libstd/sys_common/backtrace.rs | 235 | ||||
| -rw-r--r-- | src/test/rustdoc-ui/invalid-syntax.rs | 8 | ||||
| -rw-r--r-- | src/test/rustdoc-ui/invalid-syntax.stderr | 18 | ||||
| -rw-r--r-- | src/test/ui/imports/unresolved-imports-used.rs | 14 | ||||
| -rw-r--r-- | src/test/ui/imports/unresolved-imports-used.stderr | 26 | 
13 files changed, 323 insertions, 171 deletions
diff --git a/Cargo.lock b/Cargo.lock index 108c2fbd8f5..328d96023bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,9 +109,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.35" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1371048253fa3bac6704bfd6bbfc922ee9bdcee8881330d40f308b81cc5adc55" +checksum = "5180c5a20655b14a819b652fd2378fa5f1697b6c9ddad3e695c2f9cedf6df4e2" dependencies = [ "backtrace-sys", "cfg-if", diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 8fd5fe0653e..c09df3f7f22 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -2557,11 +2557,41 @@ pub trait Iterator { /// assert_eq!([1, 2].iter().cmp([1].iter()), Ordering::Greater); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] - fn cmp<I>(mut self, other: I) -> Ordering where + fn cmp<I>(self, other: I) -> Ordering + where I: IntoIterator<Item = Self::Item>, Self::Item: Ord, Self: Sized, { + self.cmp_by(other, |x, y| x.cmp(&y)) + } + + /// Lexicographically compares the elements of this `Iterator` with those + /// of another with respect to the specified comparison function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// use std::cmp::Ordering; + /// + /// let xs = [1, 2, 3, 4]; + /// let ys = [1, 4, 9, 16]; + /// + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| x.cmp(&y)), Ordering::Less); + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (x * x).cmp(&y)), Ordering::Equal); + /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); + /// ``` + #[unstable(feature = "iter_order_by", issue = "0")] + fn cmp_by<I, F>(mut self, other: I, mut cmp: F) -> Ordering + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> Ordering, + { let mut other = other.into_iter(); loop { @@ -2579,7 +2609,7 @@ pub trait Iterator { Some(val) => val, }; - match x.cmp(&y) { + match cmp(x, y) { Ordering::Equal => (), non_eq => return non_eq, } @@ -2601,11 +2631,50 @@ pub trait Iterator { /// assert_eq!([std::f64::NAN].iter().partial_cmp([1.].iter()), None); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] - fn partial_cmp<I>(mut self, other: I) -> Option<Ordering> where + fn partial_cmp<I>(self, other: I) -> Option<Ordering> + where I: IntoIterator, Self::Item: PartialOrd<I::Item>, Self: Sized, { + self.partial_cmp_by(other, |x, y| x.partial_cmp(&y)) + } + + /// Lexicographically compares the elements of this `Iterator` with those + /// of another with respect to the specified comparison function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// use std::cmp::Ordering; + /// + /// let xs = [1.0, 2.0, 3.0, 4.0]; + /// let ys = [1.0, 4.0, 9.0, 16.0]; + /// + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| x.partial_cmp(&y)), + /// Some(Ordering::Less) + /// ); + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| (x * x).partial_cmp(&y)), + /// Some(Ordering::Equal) + /// ); + /// assert_eq!( + /// xs.iter().partial_cmp_by(&ys, |&x, &y| (2.0 * x).partial_cmp(&y)), + /// Some(Ordering::Greater) + /// ); + /// ``` + #[unstable(feature = "iter_order_by", issue = "0")] + fn partial_cmp_by<I, F>(mut self, other: I, mut partial_cmp: F) -> Option<Ordering> + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> Option<Ordering>, + { let mut other = other.into_iter(); loop { @@ -2623,7 +2692,7 @@ pub trait Iterator { Some(val) => val, }; - match x.partial_cmp(&y) { + match partial_cmp(x, y) { Some(Ordering::Equal) => (), non_eq => return non_eq, } @@ -2640,11 +2709,37 @@ pub trait Iterator { /// assert_eq!([1].iter().eq([1, 2].iter()), false); /// ``` #[stable(feature = "iter_order", since = "1.5.0")] - fn eq<I>(mut self, other: I) -> bool where + fn eq<I>(self, other: I) -> bool + where I: IntoIterator, Self::Item: PartialEq<I::Item>, Self: Sized, { + self.eq_by(other, |x, y| x == y) + } + + /// Determines if the elements of this `Iterator` are equal to those of + /// another with respect to the specified equality function. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(iter_order_by)] + /// + /// let xs = [1, 2, 3, 4]; + /// let ys = [1, 4, 9, 16]; + /// + /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); + /// ``` + #[unstable(feature = "iter_order_by", issue = "0")] + fn eq_by<I, F>(mut self, other: I, mut eq: F) -> bool + where + Self: Sized, + I: IntoIterator, + F: FnMut(Self::Item, I::Item) -> bool, + { let mut other = other.into_iter(); loop { @@ -2658,7 +2753,9 @@ pub trait Iterator { Some(val) => val, }; - if x != y { return false } + if !eq(x, y) { + return false; + } } } diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 8e0658d87c1..d7088cf891f 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -58,6 +58,62 @@ fn test_multi_iter() { } #[test] +fn test_cmp_by() { + use core::cmp::Ordering; + + let f = |x: i32, y: i32| (x * x).cmp(&y); + let xs = || [1, 2, 3, 4].iter().copied(); + let ys = || [1, 4, 16].iter().copied(); + + assert_eq!(xs().cmp_by(ys(), f), Ordering::Less); + assert_eq!(ys().cmp_by(xs(), f), Ordering::Greater); + assert_eq!(xs().cmp_by(xs().map(|x| x * x), f), Ordering::Equal); + assert_eq!(xs().rev().cmp_by(ys().rev(), f), Ordering::Greater); + assert_eq!(xs().cmp_by(ys().rev(), f), Ordering::Less); + assert_eq!(xs().cmp_by(ys().take(2), f), Ordering::Greater); +} + +#[test] +fn test_partial_cmp_by() { + use core::cmp::Ordering; + use core::f64; + + let f = |x: i32, y: i32| (x * x).partial_cmp(&y); + let xs = || [1, 2, 3, 4].iter().copied(); + let ys = || [1, 4, 16].iter().copied(); + + assert_eq!(xs().partial_cmp_by(ys(), f), Some(Ordering::Less)); + assert_eq!(ys().partial_cmp_by(xs(), f), Some(Ordering::Greater)); + assert_eq!(xs().partial_cmp_by(xs().map(|x| x * x), f), Some(Ordering::Equal)); + assert_eq!(xs().rev().partial_cmp_by(ys().rev(), f), Some(Ordering::Greater)); + assert_eq!(xs().partial_cmp_by(xs().rev(), f), Some(Ordering::Less)); + assert_eq!(xs().partial_cmp_by(ys().take(2), f), Some(Ordering::Greater)); + + let f = |x: f64, y: f64| (x * x).partial_cmp(&y); + let xs = || [1.0, 2.0, 3.0, 4.0].iter().copied(); + let ys = || [1.0, 4.0, f64::NAN, 16.0].iter().copied(); + + assert_eq!(xs().partial_cmp_by(ys(), f), None); + assert_eq!(ys().partial_cmp_by(xs(), f), Some(Ordering::Greater)); +} + +#[test] +fn test_eq_by() { + let f = |x: i32, y: i32| x * x == y; + let xs = || [1, 2, 3, 4].iter().copied(); + let ys = || [1, 4, 9, 16].iter().copied(); + + assert!(xs().eq_by(ys(), f)); + assert!(!ys().eq_by(xs(), f)); + assert!(!xs().eq_by(xs(), f)); + assert!(!ys().eq_by(ys(), f)); + + assert!(!xs().take(3).eq_by(ys(), f)); + assert!(!xs().eq_by(ys().take(3), f)); + assert!(xs().take(3).eq_by(ys().take(3), f)); +} + +#[test] fn test_counter_from_iter() { let it = (0..).step_by(5).take(10); let xs: Vec<isize> = FromIterator::from_iter(it); diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index b2c29aa2692..050195cd2ef 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -33,6 +33,7 @@ #![feature(const_fn)] #![feature(iter_partition_in_place)] #![feature(iter_is_partitioned)] +#![feature(iter_order_by)] extern crate test; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index ca189e71800..132690dcd7d 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -673,6 +673,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> { self.throw_unresolved_import_error(errors.clone(), None); } + for import in &self.r.indeterminate_imports { + // Consider erroneous imports used to avoid duplicate diagnostics. + self.r.used_imports.insert((import.id, TypeNS)); + } // Report unresolved imports only if no hard error was already reported // to avoid generating multiple errors on the same import. if !has_errors { @@ -839,6 +843,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> { true, directive.span, directive.crate_lint()); let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len; directive.vis.set(orig_vis); + if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res { + // Consider erroneous imports used to avoid duplicate diagnostics. + self.r.used_imports.insert((directive.id, TypeNS)); + } let module = match path_res { PathResult::Module(module) => { // Consistency checks, analogous to `finalize_macro_resolutions`. diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 74413a7f905..8bf01d2cc1a 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -931,7 +931,10 @@ crate fn rust_code_blocks(md: &str) -> Vec<RustCodeBlock> { is_fenced = true; previous_offset + fence_idx } - None => offset, + None => { + is_fenced = false; + offset + } }; } } diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 18a46cf0b52..b5cbec7b0fa 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -26,7 +26,7 @@ unwind = { path = "../libunwind" } hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] } [dependencies.backtrace] -version = "0.3.35" +version = "0.3.37" default-features = false # don't use coresymbolication on OSX features = [ "rustc-dep-of-std", # enable build support for integrating into libstd diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 952fd9ebfdf..db4089c2948 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -158,7 +158,7 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> { fn default_hook(info: &PanicInfo<'_>) { #[cfg(feature = "backtrace")] - use crate::sys_common::backtrace; + use crate::sys_common::{backtrace as backtrace_mod}; // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. @@ -167,9 +167,9 @@ fn default_hook(info: &PanicInfo<'_>) { let panics = update_panic_count(0); if panics >= 2 { - Some(backtrace::PrintFormat::Full) + Some(backtrace::PrintFmt::Full) } else { - backtrace::log_enabled() + backtrace_mod::log_enabled() } }; @@ -197,7 +197,7 @@ fn default_hook(info: &PanicInfo<'_>) { static FIRST_PANIC: AtomicBool = AtomicBool::new(true); if let Some(format) = log_backtrace { - let _ = backtrace::print(err, format); + let _ = backtrace_mod::print(err, format); } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) { let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \ environment variable to display a backtrace."); diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index bf37ff7ddbd..f434b62aced 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -2,23 +2,20 @@ /// supported platforms. use crate::env; +use crate::fmt; use crate::io; use crate::io::prelude::*; -use crate::mem; use crate::path::{self, Path}; -use crate::ptr; use crate::sync::atomic::{self, Ordering}; use crate::sys::mutex::Mutex; -use backtrace::{BytesOrWideString, Frame, Symbol}; - -pub const HEX_WIDTH: usize = 2 + 2 * mem::size_of::<usize>(); +use backtrace::{BacktraceFmt, BytesOrWideString, PrintFmt}; /// Max number of frames to print. const MAX_NB_FRAMES: usize = 100; /// Prints the current backtrace. -pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { +pub fn print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> { static LOCK: Mutex = Mutex::new(); // There are issues currently linking libbacktrace into tests, and in @@ -39,26 +36,66 @@ pub fn print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { } } -fn _print(w: &mut dyn Write, format: PrintFormat) -> io::Result<()> { - writeln!(w, "stack backtrace:")?; +fn _print(w: &mut dyn Write, format: PrintFmt) -> io::Result<()> { + struct DisplayBacktrace { + format: PrintFmt, + } + impl fmt::Display for DisplayBacktrace { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + _print_fmt(fmt, self.format) + } + } + write!(w, "{}", DisplayBacktrace { format }) +} - let mut printer = Printer::new(format, w); +fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::Result { + let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| { + output_filename(fmt, bows, print_fmt) + }; + let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path); + bt_fmt.add_context()?; + let mut skipped = false; unsafe { + let mut idx = 0; + let mut res = Ok(()); backtrace::trace_unsynchronized(|frame| { + if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES { + skipped = true; + return false; + } + let mut hit = false; + let mut stop = false; backtrace::resolve_frame_unsynchronized(frame, |symbol| { hit = true; - printer.output(frame, Some(symbol)); + if print_fmt == PrintFmt::Short { + if let Some(sym) = symbol.name().and_then(|s| s.as_str()) { + if sym.contains("__rust_begin_short_backtrace") { + skipped = true; + stop = true; + return; + } + } + } + + res = bt_fmt.frame().symbol(frame, symbol); }); + if stop { + return false; + } if !hit { - printer.output(frame, None); + res = bt_fmt.frame().print_raw(frame.ip(), None, None, None); } - !printer.done + + idx += 1; + res.is_ok() }); + res?; } - if printer.skipped { + bt_fmt.finish()?; + if skipped { writeln!( - w, + fmt, "note: Some details are omitted, \ run with `RUST_BACKTRACE=full` for a verbose backtrace." )?; @@ -77,33 +114,24 @@ where f() } -/// Controls how the backtrace should be formatted. -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub enum PrintFormat { - /// Show only relevant data from the backtrace. - Short = 2, - /// Show all the frames with absolute path for files. - Full = 3, -} - // For now logging is turned off by default, and this function checks to see // whether the magical environment variable is present to see if it's turned on. -pub fn log_enabled() -> Option<PrintFormat> { +pub fn log_enabled() -> Option<PrintFmt> { static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0); match ENABLED.load(Ordering::SeqCst) { 0 => {} 1 => return None, - 2 => return Some(PrintFormat::Short), - _ => return Some(PrintFormat::Full), + 2 => return Some(PrintFmt::Short), + _ => return Some(PrintFmt::Full), } let val = env::var_os("RUST_BACKTRACE").and_then(|x| { if &x == "0" { None } else if &x == "full" { - Some(PrintFormat::Full) + Some(PrintFmt::Full) } else { - Some(PrintFormat::Short) + Some(PrintFmt::Short) } }); ENABLED.store( @@ -116,130 +144,45 @@ pub fn log_enabled() -> Option<PrintFormat> { val } -struct Printer<'a, 'b> { - format: PrintFormat, - done: bool, - skipped: bool, - idx: usize, - out: &'a mut (dyn Write + 'b), -} - -impl<'a, 'b> Printer<'a, 'b> { - fn new(format: PrintFormat, out: &'a mut (dyn Write + 'b)) -> Printer<'a, 'b> { - Printer { format, done: false, skipped: false, idx: 0, out } - } - - /// Prints the symbol of the backtrace frame. - /// - /// These output functions should now be used everywhere to ensure consistency. - /// You may want to also use `output_fileline`. - fn output(&mut self, frame: &Frame, symbol: Option<&Symbol>) { - if self.idx > MAX_NB_FRAMES { - self.done = true; - self.skipped = true; - return; - } - if self._output(frame, symbol).is_err() { - self.done = true; - } - self.idx += 1; - } - - fn _output(&mut self, frame: &Frame, symbol: Option<&Symbol>) -> io::Result<()> { - if self.format == PrintFormat::Short { - if let Some(sym) = symbol.and_then(|s| s.name()).and_then(|s| s.as_str()) { - if sym.contains("__rust_begin_short_backtrace") { - self.skipped = true; - self.done = true; - return Ok(()); - } - } - - // Remove the `17: 0x0 - <unknown>` line. - if self.format == PrintFormat::Short && frame.ip() == ptr::null_mut() { - self.skipped = true; - return Ok(()); - } - } - - match self.format { - PrintFormat::Full => { - write!(self.out, " {:2}: {:2$?} - ", self.idx, frame.ip(), HEX_WIDTH)? - } - PrintFormat::Short => write!(self.out, " {:2}: ", self.idx)?, - } - - match symbol.and_then(|s| s.name()) { - Some(symbol) => { - match self.format { - PrintFormat::Full => write!(self.out, "{}", symbol)?, - // Strip the trailing hash if short mode. - PrintFormat::Short => write!(self.out, "{:#}", symbol)?, - } - } - None => self.out.write_all(b"<unknown>")?, +/// Prints the filename of the backtrace frame. +/// +/// See also `output`. +fn output_filename( + fmt: &mut fmt::Formatter<'_>, + bows: BytesOrWideString<'_>, + print_fmt: PrintFmt, +) -> fmt::Result { + #[cfg(windows)] + let path_buf; + let file = match bows { + #[cfg(unix)] + BytesOrWideString::Bytes(bytes) => { + use crate::os::unix::prelude::*; + Path::new(crate::ffi::OsStr::from_bytes(bytes)) } - self.out.write_all(b"\n")?; - if let Some(sym) = symbol { - self.output_fileline(sym)?; + #[cfg(not(unix))] + BytesOrWideString::Bytes(bytes) => { + Path::new(crate::str::from_utf8(bytes).unwrap_or("<unknown>")) } - Ok(()) - } - - /// Prints the filename and line number of the backtrace frame. - /// - /// See also `output`. - fn output_fileline(&mut self, symbol: &Symbol) -> io::Result<()> { #[cfg(windows)] - let path_buf; - let file = match symbol.filename_raw() { - #[cfg(unix)] - Some(BytesOrWideString::Bytes(bytes)) => { - use crate::os::unix::prelude::*; - Path::new(crate::ffi::OsStr::from_bytes(bytes)) - } - #[cfg(not(unix))] - Some(BytesOrWideString::Bytes(bytes)) => { - Path::new(crate::str::from_utf8(bytes).unwrap_or("<unknown>")) - } - #[cfg(windows)] - Some(BytesOrWideString::Wide(wide)) => { - use crate::os::windows::prelude::*; - path_buf = crate::ffi::OsString::from_wide(wide); - Path::new(&path_buf) - } - #[cfg(not(windows))] - Some(BytesOrWideString::Wide(_wide)) => { - Path::new("<unknown>") - } - None => return Ok(()), - }; - let line = match symbol.lineno() { - Some(line) => line, - None => return Ok(()), - }; - // prior line: " ##: {:2$} - func" - self.out.write_all(b"")?; - match self.format { - PrintFormat::Full => write!(self.out, " {:1$}", "", HEX_WIDTH)?, - PrintFormat::Short => write!(self.out, " ")?, + BytesOrWideString::Wide(wide) => { + use crate::os::windows::prelude::*; + path_buf = crate::ffi::OsString::from_wide(wide); + Path::new(&path_buf) } - - let mut already_printed = false; - if self.format == PrintFormat::Short && file.is_absolute() { - if let Ok(cwd) = env::current_dir() { - if let Ok(stripped) = file.strip_prefix(&cwd) { - if let Some(s) = stripped.to_str() { - write!(self.out, " at .{}{}:{}", path::MAIN_SEPARATOR, s, line)?; - already_printed = true; - } + #[cfg(not(windows))] + BytesOrWideString::Wide(_wide) => { + Path::new("<unknown>") + } + }; + if print_fmt == PrintFmt::Short && file.is_absolute() { + if let Ok(cwd) = env::current_dir() { + if let Ok(stripped) = file.strip_prefix(&cwd) { + if let Some(s) = stripped.to_str() { + return write!(fmt, ".{}{}", path::MAIN_SEPARATOR, s); } } } - if !already_printed { - write!(self.out, " at {}:{}", file.display(), line)?; - } - - self.out.write_all(b"\n") } + fmt::Display::fmt(&file.display(), fmt) } diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs index 3ef66e273d0..97a0f4aaec1 100644 --- a/src/test/rustdoc-ui/invalid-syntax.rs +++ b/src/test/rustdoc-ui/invalid-syntax.rs @@ -74,3 +74,11 @@ pub fn empty_rust() {} /// /// ``` pub fn empty_rust_with_whitespace() {} + +/// ``` +/// let x = 1; +/// ``` +/// +/// \____/ +/// +pub fn indent_after_fenced() {} diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr index 36209e29277..6f50edae650 100644 --- a/src/test/rustdoc-ui/invalid-syntax.stderr +++ b/src/test/rustdoc-ui/invalid-syntax.stderr @@ -202,6 +202,24 @@ LL | /// ```text | ^^^^^^^ error: unknown start of token: \ + --> <doctest>:1:1 + | +1 | \____/ + | ^ + +warning: could not parse code block as Rust code + --> $DIR/invalid-syntax.rs:82:9 + | +LL | /// \____/ + | ^^^^^^ + +error: unknown start of token: \ + --> <rustdoc-highlighting>:1:1 + | +1 | \____/ + | ^ + +error: unknown start of token: \ --> <rustdoc-highlighting>:1:1 | 1 | \_ diff --git a/src/test/ui/imports/unresolved-imports-used.rs b/src/test/ui/imports/unresolved-imports-used.rs index d1461e7b041..5398dd63c89 100644 --- a/src/test/ui/imports/unresolved-imports-used.rs +++ b/src/test/ui/imports/unresolved-imports-used.rs @@ -1,12 +1,18 @@ -// There should be *no* unused import errors. +// There should be *one* unused import error. #![deny(unused_imports)] mod qux { fn quz() {} + pub fn quy() {} } -use qux::quz; //~ ERROR function `quz` is private -use qux::bar; //~ ERROR unresolved import `qux::bar` -use foo::bar; //~ ERROR unresolved import `foo` +use qux::quz; //~ ERROR function `quz` is private +use qux::bar; //~ ERROR unresolved import `qux::bar` +use foo::bar; +use baz::*; +use qux::bar2; //~ ERROR unresolved import `qux::bar2` +use foo2::bar2; +use baz2::*; +use qux::quy; //~ ERROR unused import fn main() {} diff --git a/src/test/ui/imports/unresolved-imports-used.stderr b/src/test/ui/imports/unresolved-imports-used.stderr index e8c827a6179..c9342d17a49 100644 --- a/src/test/ui/imports/unresolved-imports-used.stderr +++ b/src/test/ui/imports/unresolved-imports-used.stderr @@ -1,22 +1,34 @@ error[E0432]: unresolved import `qux::bar` - --> $DIR/unresolved-imports-used.rs:9:5 + --> $DIR/unresolved-imports-used.rs:10:5 | LL | use qux::bar; | ^^^^^^^^ no `bar` in `qux` -error[E0432]: unresolved import `foo` - --> $DIR/unresolved-imports-used.rs:10:5 +error[E0432]: unresolved import `qux::bar2` + --> $DIR/unresolved-imports-used.rs:13:5 | -LL | use foo::bar; - | ^^^ maybe a missing crate `foo`? +LL | use qux::bar2; + | ^^^^^^^^^ no `bar2` in `qux` error[E0603]: function `quz` is private - --> $DIR/unresolved-imports-used.rs:8:10 + --> $DIR/unresolved-imports-used.rs:9:10 | LL | use qux::quz; | ^^^ -error: aborting due to 3 previous errors +error: unused import: `qux::quy` + --> $DIR/unresolved-imports-used.rs:16:5 + | +LL | use qux::quy; + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/unresolved-imports-used.rs:2:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0432, E0603. For more information about an error, try `rustc --explain E0432`.  | 
