diff --git a/RELEASES.md b/RELEASES.md index 37aed7735455b..64fe2df3c496c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -51,7 +51,7 @@ Compatibility Notes ------------------- - [The target configuration option `abi_blacklist` has been renamed to `unsupported_abis`.][74150] The old name will still continue to work. -- [Rustc will now warn if you have a C-like enum that implements `Drop`.][72331] +- [Rustc will now warn if you cast a C-like enum that implements `Drop`.][72331] This was previously accepted but will become a hard error in a future release. - [Rustc will fail to compile if you have a struct with `#[repr(i128)]` or `#[repr(u128)]`.][74109] This representation is currently only diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index d9b91acc3ad7b..e9a99ddb6b1bd 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -23,7 +23,7 @@ use crate::task::{Context, Poll}; /// When using a future, you generally won't call `poll` directly, but instead /// `.await` the value. /// -/// [`Waker`]: ../task/struct.Waker.html +/// [`Waker`]: crate::task::Waker #[doc(spotlight)] #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] @@ -91,11 +91,9 @@ pub trait Future { /// (memory corruption, incorrect use of `unsafe` functions, or the like), /// regardless of the future's state. /// - /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending - /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready - /// [`Context`]: ../task/struct.Context.html - /// [`Waker`]: ../task/struct.Waker.html - /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake + /// [`Poll::Ready(val)`]: Poll::Ready + /// [`Waker`]: crate::task::Waker + /// [`Waker::wake`]: crate::task::Waker::wake #[lang = "poll"] #[stable(feature = "futures_api", since = "1.36.0")] fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll; diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 461b4c79a1d1c..d40a380286762 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -101,7 +101,7 @@ pub fn spin_loop() { /// [`std::convert::identity`]: https://doc.rust-lang.org/core/convert/fn.identity.html /// /// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can -/// use `x` in any possible valid way that Rust code is allowed to without introducing undefined +/// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined /// behavior in the calling code. This property makes `black_box` useful for writing code in which /// certain optimizations are not desired, such as benchmarks. /// diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index d26f2124f15fd..4e0da1fc4a6a3 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -333,16 +333,16 @@ macro_rules! r#try { /// This macro accepts a format string, a list of arguments, and a 'writer'. Arguments will be /// formatted according to the specified format string and the result will be passed to the writer. /// The writer may be any value with a `write_fmt` method; generally this comes from an -/// implementation of either the [`std::fmt::Write`] or the [`std::io::Write`] trait. The macro -/// returns whatever the `write_fmt` method returns; commonly a [`std::fmt::Result`], or an +/// implementation of either the [`fmt::Write`] or the [`io::Write`] trait. The macro +/// returns whatever the `write_fmt` method returns; commonly a [`fmt::Result`], or an /// [`io::Result`]. /// /// See [`std::fmt`] for more information on the format string syntax. /// /// [`std::fmt`]: crate::fmt -/// [`std::fmt::Write`]: crate::fmt::Write -/// [`std::io::Write`]: ../std/io/trait.Write.html -/// [`std::fmt::Result`]: crate::fmt::Result +/// [`fmt::Write`]: crate::fmt::Write +/// [`io::Write`]: ../std/io/trait.Write.html +/// [`fmt::Result`]: crate::fmt::Result /// [`io::Result`]: ../std/io/type.Result.html /// /// # Examples diff --git a/library/core/src/macros/panic.md b/library/core/src/macros/panic.md index 3ecfc43be049b..a02e74d5e5a4d 100644 --- a/library/core/src/macros/panic.md +++ b/library/core/src/macros/panic.md @@ -5,12 +5,12 @@ to the caller of the program. `panic!` should be used when a program reaches an unrecoverable state. This macro is the perfect way to assert conditions in example code and in -tests. `panic!` is closely tied with the `unwrap` method of both [`Option`] -and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set -to None or Err variants. +tests. `panic!` is closely tied with the `unwrap` method of both +[`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call +`panic!` when they are set to [`None`] or [`Err`] variants. This macro is used to inject panic into a Rust thread, causing the thread to -panic entirely. Each thread's panic can be reaped as the `Box` type, +panic entirely. Each thread's panic can be reaped as the [`Box`]`<`[`Any`]`>` type, and the single-argument form of the `panic!` macro will be the value which is transmitted. @@ -24,11 +24,11 @@ The multi-argument form of this macro panics with a string and has the See also the macro [`compile_error!`], for raising errors during compilation. -[runwrap]: ../std/result/enum.Result.html#method.unwrap -[`Option`]: ../std/option/enum.Option.html#method.unwrap -[`Result`]: ../std/result/enum.Result.html +[ounwrap]: Option::unwrap +[runwrap]: Result::unwrap +[`Box`]: ../std/boxed/struct.Box.html +[`Any`]: crate::any::Any [`format!`]: ../std/macro.format.html -[`compile_error!`]: ../std/macro.compile_error.html [book]: ../book/ch09-00-error-handling.html # Current implementation diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs index c83c6b0eccbc7..ed6202bb82f0f 100644 --- a/library/core/src/num/dec2flt/mod.rs +++ b/library/core/src/num/dec2flt/mod.rs @@ -166,10 +166,6 @@ from_str_float_impl!(f64); /// /// This error is used as the error type for the [`FromStr`] implementation /// for [`f32`] and [`f64`]. -/// -/// [`FromStr`]: ../str/trait.FromStr.html -/// [`f32`]: ../../std/primitive.f32.html -/// [`f64`]: ../../std/primitive.f64.html #[derive(Debug, Clone, PartialEq, Eq)] #[stable(feature = "rust1", since = "1.0.0")] pub struct ParseFloatError { diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index fc70dec16f618..d09cdb44e0837 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -836,7 +836,7 @@ impl *const T { /// # use std::mem::align_of; /// # unsafe { /// let x = [5u8, 6u8, 7u8, 8u8, 9u8]; - /// let ptr = &x[n] as *const u8; + /// let ptr = x.as_ptr().add(n) as *const u8; /// let offset = ptr.align_offset(align_of::()); /// if offset < x.len() - n - 1 { /// let u16_ptr = ptr.add(offset) as *const u16; diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 2d25f21e55c76..537aa20bf1dbc 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1094,7 +1094,7 @@ impl *mut T { /// # use std::mem::align_of; /// # unsafe { /// let x = [5u8, 6u8, 7u8, 8u8, 9u8]; - /// let ptr = &x[n] as *const u8; + /// let ptr = x.as_ptr().add(n) as *const u8; /// let offset = ptr.align_offset(align_of::()); /// if offset < x.len() - n - 1 { /// let u16_ptr = ptr.add(offset) as *const u16; diff --git a/library/profiler_builtins/build.rs b/library/profiler_builtins/build.rs index b674f73ebf390..2a5d5853fec64 100644 --- a/library/profiler_builtins/build.rs +++ b/library/profiler_builtins/build.rs @@ -20,6 +20,7 @@ fn main() { "InstrProfilingMergeFile.c", "InstrProfilingNameVar.c", "InstrProfilingPlatformDarwin.c", + "InstrProfilingPlatformFuchsia.c", "InstrProfilingPlatformLinux.c", "InstrProfilingPlatformOther.c", "InstrProfilingPlatformWindows.c", diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 84e686c2fef81..d3b0f8ceb68a6 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -33,15 +33,14 @@ use crate::string; /// themselves through the [`Display`] and [`Debug`] traits, and may provide /// cause chain information: /// -/// The [`source`] method is generally used when errors cross "abstraction -/// boundaries". If one module must report an error that is caused by an error -/// from a lower-level module, it can allow access to that error via the -/// [`source`] method. This makes it possible for the high-level module to -/// provide its own errors while also revealing some of the implementation for -/// debugging via [`source`] chains. +/// [`Error::source()`] is generally used when errors cross +/// "abstraction boundaries". If one module must report an error that is caused +/// by an error from a lower-level module, it can allow accessing that error +/// via [`Error::source()`]. This makes it possible for the high-level +/// module to provide its own errors while also revealing some of the +/// implementation for debugging via `source` chains. /// /// [`Result`]: Result -/// [`source`]: Error::source #[stable(feature = "rust1", since = "1.0.0")] pub trait Error: Debug + Display { /// The lower-level source of this error, if any. @@ -636,7 +635,7 @@ impl dyn Error { } /// Returns an iterator starting with the current error and continuing with - /// recursively calling [`source`]. + /// recursively calling [`Error::source`]. /// /// If you want to omit the current error and only use its sources, /// use `skip(1)`. @@ -686,8 +685,6 @@ impl dyn Error { /// assert!(iter.next().is_none()); /// assert!(iter.next().is_none()); /// ``` - /// - /// [`source`]: Error::source #[unstable(feature = "error_iter", issue = "58520")] #[inline] pub fn chain(&self) -> Chain<'_> { diff --git a/src/librustc_error_codes/error_codes/E0761.md b/src/librustc_error_codes/error_codes/E0761.md index c01574e413cfa..e112674fbcc49 100644 --- a/src/librustc_error_codes/error_codes/E0761.md +++ b/src/librustc_error_codes/error_codes/E0761.md @@ -2,24 +2,20 @@ Multiple candidate files were found for an out-of-line module. Erroneous code example: -```rust +```ignore (multiple source files required for compile_fail) // file: ambiguous_module/mod.rs fn foo() {} -``` -```rust // file: ambiguous_module.rs fn foo() {} -``` -```ignore (multiple source files required for compile_fail) +// file: lib.rs + mod ambiguous_module; // error: file for module `ambiguous_module` // found at both ambiguous_module.rs and // ambiguous_module.rs/mod.rs - -fn main() {} ``` Please remove this ambiguity by deleting/renaming one of the candidate files. diff --git a/src/librustc_parse_format/lib.rs b/src/librustc_parse_format/lib.rs index ebb3aa3866e43..e07b8b86aef8e 100644 --- a/src/librustc_parse_format/lib.rs +++ b/src/librustc_parse_format/lib.rs @@ -760,7 +760,7 @@ fn find_skips_from_snippet( (' ' | '\n' | '\t', _) if eat_ws => { skips.push(pos); } - ('\\', Some((next_pos, 'n' | 't' | '0' | '\\' | '\'' | '\"'))) => { + ('\\', Some((next_pos, 'n' | 't' | 'r' | '0' | '\\' | '\'' | '\"'))) => { skips.push(*next_pos); let _ = s.next(); } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index ab0b332ee1936..c039b181178a4 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -135,7 +135,7 @@ impl Cfg { /// Renders the configuration for human display, as a short HTML description. pub(crate) fn render_short_html(&self) -> String { - let mut msg = Html(self, true).to_string(); + let mut msg = Display(self, Format::ShortHtml).to_string(); if self.should_capitalize_first_letter() { if let Some(i) = msg.find(|c: char| c.is_ascii_alphanumeric()) { msg[i..i + 1].make_ascii_uppercase(); @@ -148,7 +148,11 @@ impl Cfg { pub(crate) fn render_long_html(&self) -> String { let on = if self.should_use_with_in_description() { "with" } else { "on" }; - let mut msg = format!("This is supported {} {}", on, Html(self, false)); + let mut msg = format!( + "This is supported {} {}", + on, + Display(self, Format::LongHtml) + ); if self.should_append_only_to_description() { msg.push_str(" only"); } @@ -156,6 +160,17 @@ impl Cfg { msg } + /// Renders the configuration for long display, as a long plain text description. + pub(crate) fn render_long_plain(&self) -> String { + let on = if self.should_use_with_in_description() { "with" } else { "on" }; + + let mut msg = format!("This is supported {} {}", on, Display(self, Format::LongPlain)); + if self.should_append_only_to_description() { + msg.push_str(" only"); + } + msg + } + fn should_capitalize_first_letter(&self) -> bool { match *self { Cfg::False | Cfg::True | Cfg::Not(..) => true, @@ -286,9 +301,31 @@ impl ops::BitOr for Cfg { } } -/// Pretty-print wrapper for a `Cfg`. Also indicates whether the "short-form" rendering should be -/// used. -struct Html<'a>(&'a Cfg, bool); +#[derive(Clone, Copy)] +enum Format { + LongHtml, + LongPlain, + ShortHtml, +} + +impl Format { + fn is_long(self) -> bool { + match self { + Format::LongHtml | Format::LongPlain => true, + Format::ShortHtml => false, + } + } + + fn is_html(self) -> bool { + match self { + Format::LongHtml | Format::ShortHtml => true, + Format::LongPlain => false, + } + } +} + +/// Pretty-print wrapper for a `Cfg`. Also indicates what form of rendering should be used. +struct Display<'a>(&'a Cfg, Format); fn write_with_opt_paren( fmt: &mut fmt::Formatter<'_>, @@ -305,7 +342,7 @@ fn write_with_opt_paren( Ok(()) } -impl<'a> fmt::Display for Html<'a> { +impl<'a> fmt::Display for Display<'a> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match *self.0 { Cfg::Not(ref child) => match **child { @@ -314,31 +351,86 @@ impl<'a> fmt::Display for Html<'a> { if sub_cfgs.iter().all(Cfg::is_simple) { " nor " } else { ", nor " }; for (i, sub_cfg) in sub_cfgs.iter().enumerate() { fmt.write_str(if i == 0 { "neither " } else { separator })?; - write_with_opt_paren(fmt, !sub_cfg.is_all(), Html(sub_cfg, self.1))?; + write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; } Ok(()) } - ref simple @ Cfg::Cfg(..) => write!(fmt, "non-{}", Html(simple, self.1)), - ref c => write!(fmt, "not ({})", Html(c, self.1)), + ref simple @ Cfg::Cfg(..) => write!(fmt, "non-{}", Display(simple, self.1)), + ref c => write!(fmt, "not ({})", Display(c, self.1)), }, Cfg::Any(ref sub_cfgs) => { let separator = if sub_cfgs.iter().all(Cfg::is_simple) { " or " } else { ", or " }; + + let short_longhand = self.1.is_long() && { + let all_crate_features = sub_cfgs + .iter() + .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_)))); + let all_target_features = sub_cfgs + .iter() + .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::target_feature, Some(_)))); + + if all_crate_features { + fmt.write_str("crate features ")?; + true + } else if all_target_features { + fmt.write_str("target features ")?; + true + } else { + false + } + }; + for (i, sub_cfg) in sub_cfgs.iter().enumerate() { if i != 0 { fmt.write_str(separator)?; } - write_with_opt_paren(fmt, !sub_cfg.is_all(), Html(sub_cfg, self.1))?; + if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) { + if self.1.is_html() { + write!(fmt, "{}", feat)?; + } else { + write!(fmt, "`{}`", feat)?; + } + } else { + write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?; + } } Ok(()) } Cfg::All(ref sub_cfgs) => { + let short_longhand = self.1.is_long() && { + let all_crate_features = sub_cfgs + .iter() + .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::feature, Some(_)))); + let all_target_features = sub_cfgs + .iter() + .all(|sub_cfg| matches!(sub_cfg, Cfg::Cfg(sym::target_feature, Some(_)))); + + if all_crate_features { + fmt.write_str("crate features ")?; + true + } else if all_target_features { + fmt.write_str("target features ")?; + true + } else { + false + } + }; + for (i, sub_cfg) in sub_cfgs.iter().enumerate() { if i != 0 { fmt.write_str(" and ")?; } - write_with_opt_paren(fmt, !sub_cfg.is_simple(), Html(sub_cfg, self.1))?; + if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) { + if self.1.is_html() { + write!(fmt, "{}", feat)?; + } else { + write!(fmt, "`{}`", feat)?; + } + } else { + write_with_opt_paren(fmt, !sub_cfg.is_simple(), Display(sub_cfg, self.1))?; + } } Ok(()) } @@ -406,26 +498,39 @@ impl<'a> fmt::Display for Html<'a> { }, (sym::target_endian, Some(endian)) => return write!(fmt, "{}-endian", endian), (sym::target_pointer_width, Some(bits)) => return write!(fmt, "{}-bit", bits), - (sym::target_feature, Some(feat)) => { - if self.1 { - return write!(fmt, "{}", feat); - } else { + (sym::target_feature, Some(feat)) => match self.1 { + Format::LongHtml => { return write!(fmt, "target feature {}", feat); } - } + Format::LongPlain => return write!(fmt, "target feature `{}`", feat), + Format::ShortHtml => return write!(fmt, "{}", feat), + }, + (sym::feature, Some(feat)) => match self.1 { + Format::LongHtml => { + return write!(fmt, "crate feature {}", feat); + } + Format::LongPlain => return write!(fmt, "crate feature `{}`", feat), + Format::ShortHtml => return write!(fmt, "{}", feat), + }, _ => "", }; if !human_readable.is_empty() { fmt.write_str(human_readable) } else if let Some(v) = value { - write!( - fmt, - "{}=\"{}\"", - Escape(&name.as_str()), - Escape(&v.as_str()) - ) - } else { + if self.1.is_html() { + write!( + fmt, + r#"{}="{}""#, + Escape(&name.as_str()), + Escape(&v.as_str()) + ) + } else { + write!(fmt, r#"`{}="{}"`"#, name, v) + } + } else if self.1.is_html() { write!(fmt, "{}", Escape(&name.as_str())) + } else { + write!(fmt, "`{}`", name) } } } diff --git a/src/librustdoc/test.rs b/src/librustdoc/doctest.rs similarity index 100% rename from src/librustdoc/test.rs rename to src/librustdoc/doctest.rs diff --git a/src/librustdoc/test/tests.rs b/src/librustdoc/doctest/tests.rs similarity index 100% rename from src/librustdoc/test/tests.rs rename to src/librustdoc/doctest/tests.rs diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index b2589e5b806e8..56499f736e163 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -34,9 +34,9 @@ use std::fmt::Write; use std::ops::Range; use std::str; +use crate::doctest; use crate::html::highlight; use crate::html::toc::TocBuilder; -use crate::test; use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, Options, Parser, Tag}; @@ -243,7 +243,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { .collect::>>() .join("\n"); let krate = krate.as_ref().map(|s| &**s); - let (test, _) = test::make_test(&test, krate, false, &Default::default(), edition); + let (test, _) = doctest::make_test(&test, krate, false, &Default::default(), edition); let channel = if test.contains("#![feature(") { "&version=nightly" } else { "" }; let edition_string = format!("&edition={}", edition); @@ -568,7 +568,7 @@ impl<'a, I: Iterator>> Iterator for Footnotes<'a, I> { } } -pub fn find_testable_code( +pub fn find_testable_code( doc: &str, tests: &mut T, error_codes: ErrorCodes, diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 2aadb2357f97b..15afe9257d187 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2130,8 +2130,8 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean: fn stability_tags(item: &clean::Item) -> String { let mut tags = String::new(); - fn tag_html(class: &str, contents: &str) -> String { - format!(r#"{}"#, class, contents) + fn tag_html(class: &str, title: &str, contents: &str) -> String { + format!(r#"{}"#, class, Escape(title), contents) } // The trailing space after each tag is to space it properly against the rest of the docs. @@ -2140,7 +2140,7 @@ fn stability_tags(item: &clean::Item) -> String { if !stability::deprecation_in_effect(depr.is_since_rustc_version, depr.since.as_deref()) { message = "Deprecation planned"; } - tags += &tag_html("deprecated", message); + tags += &tag_html("deprecated", "", message); } // The "rustc_private" crates are permanently unstable so it makes no sense @@ -2151,11 +2151,11 @@ fn stability_tags(item: &clean::Item) -> String { .map(|s| s.level == stability::Unstable && s.feature != "rustc_private") == Some(true) { - tags += &tag_html("unstable", "Experimental"); + tags += &tag_html("unstable", "", "Experimental"); } if let Some(ref cfg) = item.attrs.cfg { - tags += &tag_html("portability", &cfg.render_short_html()); + tags += &tag_html("portability", &cfg.render_long_plain(), &cfg.render_short_html()); } tags diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b5e246b5d17a5..8658b39b45578 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -64,13 +64,13 @@ mod docfs; mod doctree; #[macro_use] mod error; +mod doctest; mod fold; crate mod formats; pub mod html; mod json; mod markdown; mod passes; -mod test; mod theme; mod visit_ast; mod visit_lib; @@ -476,7 +476,7 @@ fn main_options(options: config::Options) -> MainResult { match (options.should_test, options.markdown_input()) { (true, true) => return wrap_return(&diag, markdown::test(options)), - (true, false) => return test::run(options), + (true, false) => return doctest::run(options), (false, true) => { return wrap_return( &diag, diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 89d184e35cb06..3a87e1c46a615 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -7,10 +7,10 @@ use rustc_span::edition::Edition; use rustc_span::source_map::DUMMY_SP; use crate::config::{Options, RenderOptions}; +use crate::doctest::{Collector, TestOptions}; use crate::html::escape::Escape; use crate::html::markdown; use crate::html::markdown::{find_testable_code, ErrorCodes, IdMap, Markdown, MarkdownWithToc}; -use crate::test::{Collector, TestOptions}; /// Separate any lines at the start of the file that begin with `# ` or `%`. fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) { diff --git a/src/librustdoc/passes/doc_test_lints.rs b/src/librustdoc/passes/doc_test_lints.rs index 367f93cfd3893..cbbe86dc433f3 100644 --- a/src/librustdoc/passes/doc_test_lints.rs +++ b/src/librustdoc/passes/doc_test_lints.rs @@ -54,7 +54,7 @@ impl Tests { } } -impl crate::test::Tester for Tests { +impl crate::doctest::Tester for Tests { fn add_test(&mut self, _: String, _: LangString, _: usize) { self.found_tests += 1; } diff --git a/src/test/rustdoc/duplicate-cfg.rs b/src/test/rustdoc/duplicate-cfg.rs index 9ccc5d7882eb8..47ba362c97789 100644 --- a/src/test/rustdoc/duplicate-cfg.rs +++ b/src/test/rustdoc/duplicate-cfg.rs @@ -3,22 +3,34 @@ #![crate_name = "foo"] #![feature(doc_cfg)] +// @has 'foo/index.html' +// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync$' +// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only' + // @has 'foo/struct.Foo.html' -// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" only.' +// @has '-' '//*[@class="stab portability"]' 'sync' #[doc(cfg(feature = "sync"))] #[doc(cfg(feature = "sync"))] pub struct Foo; +// @has 'foo/bar/index.html' +// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync$' +// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` only' + // @has 'foo/bar/struct.Bar.html' -// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" only.' +// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync only.' #[doc(cfg(feature = "sync"))] pub mod bar { #[doc(cfg(feature = "sync"))] pub struct Bar; } +// @has 'foo/baz/index.html' +// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync and send$' +// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate features `sync` and `send` only' + // @has 'foo/baz/struct.Baz.html' -// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" only.' +// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.' #[doc(cfg(all(feature = "sync", feature = "send")))] pub mod baz { #[doc(cfg(feature = "sync"))] @@ -26,15 +38,19 @@ pub mod baz { } // @has 'foo/qux/struct.Qux.html' -// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" only.' +// @has '-' '//*[@class="stab portability"]' 'This is supported on crate features sync and send only.' #[doc(cfg(feature = "sync"))] pub mod qux { #[doc(cfg(all(feature = "sync", feature = "send")))] pub struct Qux; } +// @has 'foo/quux/index.html' +// @matches '-' '//*[@class="module-item"]//*[@class="stab portability"]' '^sync and send and foo and bar$' +// @has '-' '//*[@class="module-item"]//*[@class="stab portability"]/@title' 'This is supported on crate feature `sync` and crate feature `send` and `foo` and `bar` only' + // @has 'foo/quux/struct.Quux.html' -// @has '-' '//*[@class="stab portability"]' 'This is supported on feature="sync" and feature="send" and foo and bar only.' +// @has '-' '//*[@class="stab portability"]' 'This is supported on crate feature sync and crate feature send and foo and bar only.' #[doc(cfg(all(feature = "sync", feature = "send", foo)))] pub mod quux { #[doc(cfg(all(feature = "send", feature = "sync", bar)))] diff --git a/src/test/ui/issues/issue-70381.rs b/src/test/ui/issues/issue-70381.rs new file mode 100644 index 0000000000000..3df8277b87372 --- /dev/null +++ b/src/test/ui/issues/issue-70381.rs @@ -0,0 +1,6 @@ +// Test that multi-byte unicode characters with missing parameters do not ICE. + +fn main() { + println!("\r¡{}") + //~^ ERROR 1 positional argument in format string +} diff --git a/src/test/ui/issues/issue-70381.stderr b/src/test/ui/issues/issue-70381.stderr new file mode 100644 index 0000000000000..96b8e656991c2 --- /dev/null +++ b/src/test/ui/issues/issue-70381.stderr @@ -0,0 +1,8 @@ +error: 1 positional argument in format string, but no arguments were given + --> $DIR/issue-70381.rs:4:16 + | +LL | println!("\r¡{}") + | ^^ + +error: aborting due to previous error + diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 124a9adcab91a..965b20f5202e0 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2782,6 +2782,18 @@ impl<'test> TestCx<'test> { cmd.env("RUSTFLAGS", "-Ctarget-feature=-crt-static").env("IS_MUSL_HOST", "1"); } + if self.config.bless { + cmd.env("RUSTC_BLESS_TEST", "--bless"); + // Assume this option is active if the environment variable is "defined", with _any_ value. + // As an example, a `Makefile` can use this option by: + // + // ifdef RUSTC_BLESS_TEST + // cp "$(TMPDIR)"/actual_something.ext expected_something.ext + // else + // $(DIFF) expected_something.ext "$(TMPDIR)"/actual_something.ext + // endif + } + if self.config.target.contains("msvc") && self.config.cc != "" { // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe` // and that `lib.exe` lives next to it.