Skip to content
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -860,7 +860,7 @@ dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
@@ -2875,7 +2875,7 @@ dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
]

[[package]]
@@ -3428,7 +3428,7 @@ dependencies = [

[[package]]
name = "synstructure"
version = "0.10.1"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4367,7 +4367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7"
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
"checksum tar 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "a303ba60a099fcd2aaa646b14d2724591a96a75283e4b7ed3d1a1658909d9ae2"
"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
"checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
2 changes: 1 addition & 1 deletion src/bootstrap/doc.rs
Original file line number Diff line number Diff line change
@@ -728,7 +728,7 @@ impl Step for Rustc {

// Build cargo command.
let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "doc");
cargo.env("RUSTDOCFLAGS", "--document-private-items");
cargo.env("RUSTDOCFLAGS", "--document-private-items --passes strip-hidden");
compile::rustc_cargo(builder, &mut cargo);

// Only include compiler crates, no dependencies of those, such as `libc`.
1,406 changes: 0 additions & 1,406 deletions src/libcore/mem.rs

This file was deleted.

146 changes: 146 additions & 0 deletions src/libcore/mem/manually_drop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
use crate::ptr;
use crate::ops::{Deref, DerefMut};

/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
///
/// This wrapper is 0-cost.
///
/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
/// As a consequence, it has *no effect* on the assumptions that the compiler makes
/// about all values being initialized at their type. In particular, initializing
/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
///
/// # Examples
///
/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
/// the type:
///
/// ```rust
/// use std::mem::ManuallyDrop;
/// struct Peach;
/// struct Banana;
/// struct Melon;
/// struct FruitBox {
/// // Immediately clear there’s something non-trivial going on with these fields.
/// peach: ManuallyDrop<Peach>,
/// melon: Melon, // Field that’s independent of the other two.
/// banana: ManuallyDrop<Banana>,
/// }
///
/// impl Drop for FruitBox {
/// fn drop(&mut self) {
/// unsafe {
/// // Explicit ordering in which field destructors are run specified in the intuitive
/// // location – the destructor of the structure containing the fields.
/// // Moreover, one can now reorder fields within the struct however much they want.
/// ManuallyDrop::drop(&mut self.peach);
/// ManuallyDrop::drop(&mut self.banana);
/// }
/// // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
/// // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
/// }
/// }
/// ```
///
/// [`mem::zeroed`]: fn.zeroed.html
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
#[stable(feature = "manually_drop", since = "1.20.0")]
#[lang = "manually_drop"]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct ManuallyDrop<T: ?Sized> {
value: T,
}

impl<T> ManuallyDrop<T> {
/// Wrap a value to be manually dropped.
///
/// # Examples
///
/// ```rust
/// use std::mem::ManuallyDrop;
/// ManuallyDrop::new(Box::new(()));
/// ```
#[stable(feature = "manually_drop", since = "1.20.0")]
#[inline(always)]
pub const fn new(value: T) -> ManuallyDrop<T> {
ManuallyDrop { value }
}

/// Extracts the value from the `ManuallyDrop` container.
///
/// This allows the value to be dropped again.
///
/// # Examples
///
/// ```rust
/// use std::mem::ManuallyDrop;
/// let x = ManuallyDrop::new(Box::new(()));
/// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
/// ```
#[stable(feature = "manually_drop", since = "1.20.0")]
#[inline(always)]
pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
slot.value
}

/// Takes the contained value out.
///
/// This method is primarily intended for moving out values in drop.
/// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
/// you can use this method to take the value and use it however desired.
/// `Drop` will be invoked on the returned value following normal end-of-scope rules.
///
/// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead.
///
/// # Safety
///
/// This function semantically moves out the contained value without preventing further usage.
/// It is up to the user of this method to ensure that this container is not used again.
///
/// [`ManuallyDrop::drop`]: #method.drop
/// [`ManuallyDrop::into_inner`]: #method.into_inner
#[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
#[unstable(feature = "manually_drop_take", issue = "55422")]
#[inline]
pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
ManuallyDrop::into_inner(ptr::read(slot))
}
}

impl<T: ?Sized> ManuallyDrop<T> {
/// Manually drops the contained value.
///
/// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
///
/// # Safety
///
/// This function runs the destructor of the contained value and thus the wrapped value
/// now represents uninitialized data. It is up to the user of this method to ensure the
/// uninitialized data is not actually used.
///
/// [`ManuallyDrop::into_inner`]: #method.into_inner
#[stable(feature = "manually_drop", since = "1.20.0")]
#[inline]
pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
ptr::drop_in_place(&mut slot.value)
}
}

#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: ?Sized> Deref for ManuallyDrop<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
&self.value
}
}

#[stable(feature = "manually_drop", since = "1.20.0")]
impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut T {
&mut self.value
}
}
519 changes: 519 additions & 0 deletions src/libcore/mem/maybe_uninit.rs

Large diffs are not rendered by default.

752 changes: 752 additions & 0 deletions src/libcore/mem/mod.rs

Large diffs are not rendered by default.

15 changes: 5 additions & 10 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
@@ -170,16 +170,11 @@ pub enum Set1<T> {

impl<T: PartialEq> Set1<T> {
pub fn insert(&mut self, value: T) {
if let Set1::Empty = *self {
*self = Set1::One(value);
return;
}
if let Set1::One(ref old) = *self {
if *old == value {
return;
}
}
*self = Set1::Many;
*self = match self {
Set1::Empty => Set1::One(value),
Set1::One(old) if *old == value => return,
_ => Set1::Many,
};
}
}

2 changes: 1 addition & 1 deletion src/librustc_macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ edition = "2018"
proc-macro = true

[dependencies]
synstructure = "0.10.1"
synstructure = "0.10.2"
syn = { version = "0.15.22", features = ["full"] }
proc-macro2 = "0.4.24"
quote = "0.6.10"
51 changes: 24 additions & 27 deletions src/librustc_mir/borrow_check/conflict_errors.rs
Original file line number Diff line number Diff line change
@@ -595,12 +595,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
) -> (String, String, String, String) {
// Define a small closure that we can use to check if the type of a place
// is a union.
let is_union = |place: &Place<'tcx>| -> bool {
place.ty(self.mir, self.infcx.tcx).ty
.ty_adt_def()
.map(|adt| adt.is_union())
.unwrap_or(false)
let union_ty = |place: &Place<'tcx>| -> Option<Ty<'tcx>> {
let ty = place.ty(self.mir, self.infcx.tcx).ty;
ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty)
};
let describe_place = |place| self.describe_place(place).unwrap_or_else(|| "_".to_owned());

// Start with an empty tuple, so we can use the functions on `Option` to reduce some
// code duplication (particularly around returning an empty description in the failure
@@ -619,7 +618,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
let mut current = first_borrowed_place;
while let Place::Projection(box Projection { base, elem }) = current {
match elem {
ProjectionElem::Field(field, _) if is_union(base) => {
ProjectionElem::Field(field, _) if union_ty(base).is_some() => {
return Some((base, field));
},
_ => current = base,
@@ -632,34 +631,32 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// borrowed place and look for a access to a different field of the same union.
let mut current = second_borrowed_place;
while let Place::Projection(box Projection { base, elem }) = current {
match elem {
ProjectionElem::Field(field, _) if {
is_union(base) && field != target_field && base == target_base
} => {
let desc_base = self.describe_place(base)
.unwrap_or_else(|| "_".to_owned());
let desc_first = self.describe_place(first_borrowed_place)
.unwrap_or_else(|| "_".to_owned());
let desc_second = self.describe_place(second_borrowed_place)
.unwrap_or_else(|| "_".to_owned());

// Also compute the name of the union type, eg. `Foo` so we
// can add a helpful note with it.
let ty = base.ty(self.mir, self.infcx.tcx).ty;

return Some((desc_base, desc_first, desc_second, ty.to_string()));
},
_ => current = base,
if let ProjectionElem::Field(field, _) = elem {
if let Some(union_ty) = union_ty(base) {
if field != target_field && base == target_base {
return Some((
describe_place(base),
describe_place(first_borrowed_place),
describe_place(second_borrowed_place),
union_ty.to_string(),
));
}
}
}

current = base;
}
None
})
.unwrap_or_else(|| {
// If we didn't find a field access into a union, or both places match, then
// only return the description of the first place.
let desc_place = self.describe_place(first_borrowed_place)
.unwrap_or_else(|| "_".to_owned());
(desc_place, "".to_string(), "".to_string(), "".to_string())
(
describe_place(first_borrowed_place),
"".to_string(),
"".to_string(),
"".to_string(),
)
})
}

6 changes: 5 additions & 1 deletion src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
@@ -270,7 +270,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
None
}

fn is_hir_id_from_struct_pattern_shorthand_field(&self, hir_id: hir::HirId, sp: Span) -> bool {
crate fn is_hir_id_from_struct_pattern_shorthand_field(
&self,
hir_id: hir::HirId,
sp: Span,
) -> bool {
let cm = self.sess().source_map();
let parent_id = self.tcx.hir().get_parent_node_by_hir_id(hir_id);
if let Some(parent) = self.tcx.hir().find_by_hir_id(parent_id) {
20 changes: 14 additions & 6 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
@@ -5010,6 +5010,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Applicability::MachineApplicable,
);
} else if !self.check_for_cast(err, expr, found, expected) {
let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field(
expr.hir_id,
expr.span,
);
let methods = self.get_conversion_methods(expr.span, expected, found);
if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) {
let mut suggestions = iter::repeat(&expr_text).zip(methods.iter())
@@ -5019,14 +5023,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
None // do not suggest code that is already there (#53348)
} else {
let method_call_list = [".to_vec()", ".to_string()"];
if receiver.ends_with(".clone()")
let sugg = if receiver.ends_with(".clone()")
&& method_call_list.contains(&method_call.as_str()) {
let max_len = receiver.rfind(".").unwrap();
Some(format!("{}{}", &receiver[..max_len], method_call))
}
else {
Some(format!("{}{}", receiver, method_call))
}
format!("{}{}", &receiver[..max_len], method_call)
} else {
format!("{}{}", receiver, method_call)
};
Some(if is_struct_pat_shorthand_field {
format!("{}: {}", receiver, sugg)
} else {
sugg
})
}
}).peekable();
if suggestions.peek().is_some() {
5 changes: 1 addition & 4 deletions src/librustdoc/clean/mod.rs
Original file line number Diff line number Diff line change
@@ -3145,10 +3145,7 @@ impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
fn clean(&self, cx: &DocContext<'_>) -> Constant {
Constant {
type_: self.ty.clean(cx),
expr: match self.val {
ConstValue::Param(ty::ParamConst { name, .. }) => format!("{}", name),
e => format!("{:?}", e), // FIXME generic consts with expressions
},
expr: format!("{}", self),
}
}
}
139 changes: 114 additions & 25 deletions src/librustdoc/test.rs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ use std::io::prelude::*;
use std::io;
use std::panic::{self, AssertUnwindSafe};
use std::path::PathBuf;
use std::process::Command;
use std::process::{self, Command};
use std::str;
use std::sync::{Arc, Mutex};
use syntax::symbol::sym;
@@ -160,13 +160,45 @@ fn scrape_test_config(krate: &::rustc::hir::Crate) -> TestOptions {
opts
}

fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
cfgs: Vec<String>, libs: Vec<SearchPath>,
cg: CodegenOptions, externs: Externs,
should_panic: bool, no_run: bool, as_test_harness: bool,
compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
maybe_sysroot: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
persist_doctests: Option<PathBuf>) {
/// Documentation test failure modes.
enum TestFailure {
/// The test failed to compile.
CompileError,
/// The test is marked `compile_fail` but compiled successfully.
UnexpectedCompilePass,
/// The test failed to compile (as expected) but the compiler output did not contain all
/// expected error codes.
MissingErrorCodes(Vec<String>),
/// The test binary was unable to be executed.
ExecutionError(io::Error),
/// The test binary exited with a non-zero exit code.
///
/// This typically means an assertion in the test failed or another form of panic occurred.
ExecutionFailure(process::Output),
/// The test is marked `should_panic` but the test binary executed successfully.
UnexpectedRunPass,
}

fn run_test(
test: &str,
cratename: &str,
filename: &FileName,
line: usize,
cfgs: Vec<String>,
libs: Vec<SearchPath>,
cg: CodegenOptions,
externs: Externs,
should_panic: bool,
no_run: bool,
as_test_harness: bool,
compile_fail: bool,
mut error_codes: Vec<String>,
opts: &TestOptions,
maybe_sysroot: Option<PathBuf>,
linker: Option<PathBuf>,
edition: Edition,
persist_doctests: Option<PathBuf>,
) -> Result<(), TestFailure> {
let (test, line_offset) = match panic::catch_unwind(|| {
make_test(test, Some(cratename), as_test_harness, opts, edition)
}) {
@@ -307,44 +339,43 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,

match (compile_result, compile_fail) {
(Ok(()), true) => {
panic!("test compiled while it wasn't supposed to")
return Err(TestFailure::UnexpectedCompilePass);
}
(Ok(()), false) => {}
(Err(_), true) => {
if error_codes.len() > 0 {
if !error_codes.is_empty() {
let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap();
error_codes.retain(|err| !out.contains(err));

if !error_codes.is_empty() {
return Err(TestFailure::MissingErrorCodes(error_codes));
}
}
}
(Err(_), false) => {
panic!("couldn't compile the test")
return Err(TestFailure::CompileError);
}
}

if error_codes.len() > 0 {
panic!("Some expected error codes were not found: {:?}", error_codes);
if no_run {
return Ok(());
}

if no_run { return }

// Run the code!
let mut cmd = Command::new(output_file);

match cmd.output() {
Err(e) => panic!("couldn't run the test: {}{}", e,
if e.kind() == io::ErrorKind::PermissionDenied {
" - maybe your tempdir is mounted with noexec?"
} else { "" }),
Err(e) => return Err(TestFailure::ExecutionError(e)),
Ok(out) => {
if should_panic && out.status.success() {
panic!("test executable succeeded when it should have failed");
return Err(TestFailure::UnexpectedRunPass);
} else if !should_panic && !out.status.success() {
panic!("test executable failed:\n{}\n{}\n",
str::from_utf8(&out.stdout).unwrap_or(""),
str::from_utf8(&out.stderr).unwrap_or(""));
return Err(TestFailure::ExecutionFailure(out));
}
}
}

Ok(())
}

/// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
@@ -711,7 +742,7 @@ impl Tester for Collector {
allow_fail: config.allow_fail,
},
testfn: testing::DynTestFn(box move || {
run_test(
let res = run_test(
&test,
&cratename,
&filename,
@@ -730,7 +761,65 @@ impl Tester for Collector {
linker,
edition,
persist_doctests
)
);

if let Err(err) = res {
match err {
TestFailure::CompileError => {
eprint!("Couldn't compile the test.");
}
TestFailure::UnexpectedCompilePass => {
eprint!("Test compiled successfully, but it's marked `compile_fail`.");
}
TestFailure::UnexpectedRunPass => {
eprint!("Test executable succeeded, but it's marked `should_panic`.");
}
TestFailure::MissingErrorCodes(codes) => {
eprint!("Some expected error codes were not found: {:?}", codes);
}
TestFailure::ExecutionError(err) => {
eprint!("Couldn't run the test: {}", err);
if err.kind() == io::ErrorKind::PermissionDenied {
eprint!(" - maybe your tempdir is mounted with noexec?");
}
}
TestFailure::ExecutionFailure(out) => {
let reason = if let Some(code) = out.status.code() {
format!("exit code {}", code)
} else {
String::from("terminated by signal")
};

eprintln!("Test executable failed ({}).", reason);

// FIXME(#12309): An unfortunate side-effect of capturing the test
// executable's output is that the relative ordering between the test's
// stdout and stderr is lost. However, this is better than the
// alternative: if the test executable inherited the parent's I/O
// handles the output wouldn't be captured at all, even on success.
//
// The ordering could be preserved if the test process' stderr was
// redirected to stdout, but that functionality does not exist in the
// standard library, so it may not be portable enough.
let stdout = str::from_utf8(&out.stdout).unwrap_or_default();
let stderr = str::from_utf8(&out.stderr).unwrap_or_default();

if !stdout.is_empty() || !stderr.is_empty() {
eprintln!();

if !stdout.is_empty() {
eprintln!("stdout:\n{}", stdout);
}

if !stderr.is_empty() {
eprintln!("stderr:\n{}", stderr);
}
}
}
}

panic::resume_unwind(box ());
}
}),
});
}
11 changes: 11 additions & 0 deletions src/test/rustdoc-ui/failed-doctest-compile-fail.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// FIXME: if/when the output of the test harness can be tested on its own, this test should be
// adapted to use that, and that normalize line can go away

// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// failure-status: 101

/// ```compile_fail
/// println!("Hello");
/// ```
pub struct Foo;
14 changes: 14 additions & 0 deletions src/test/rustdoc-ui/failed-doctest-compile-fail.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

running 1 test
test $DIR/failed-doctest-compile-fail.rs - Foo (line 8) ... FAILED

failures:

---- $DIR/failed-doctest-compile-fail.rs - Foo (line 8) stdout ----
Test compiled successfully, but it's marked `compile_fail`.

failures:
$DIR/failed-doctest-compile-fail.rs - Foo (line 8)

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

11 changes: 11 additions & 0 deletions src/test/rustdoc-ui/failed-doctest-missing-codes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// FIXME: if/when the output of the test harness can be tested on its own, this test should be
// adapted to use that, and that normalize line can go away

// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// failure-status: 101

/// ```compile_fail,E0004
/// let x: () = 5i32;
/// ```
pub struct Foo;
26 changes: 26 additions & 0 deletions src/test/rustdoc-ui/failed-doctest-missing-codes.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

running 1 test
test $DIR/failed-doctest-missing-codes.rs - Foo (line 8) ... FAILED

failures:

---- $DIR/failed-doctest-missing-codes.rs - Foo (line 8) stdout ----
error[E0308]: mismatched types
--> $DIR/failed-doctest-missing-codes.rs:9:13
|
3 | let x: () = 5i32;
| ^^^^ expected (), found i32
|
= note: expected type `()`
found type `i32`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
Some expected error codes were not found: ["E0004"]

failures:
$DIR/failed-doctest-missing-codes.rs - Foo (line 8)

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

5 changes: 4 additions & 1 deletion src/test/rustdoc-ui/failed-doctest-output.rs
Original file line number Diff line number Diff line change
@@ -5,10 +5,13 @@
// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// failure-status: 101
// rustc-env:RUST_BACKTRACE=0

// doctest fails at runtime
/// ```
/// println!("stdout 1");
/// eprintln!("stderr 1");
/// println!("stdout 2");
/// eprintln!("stderr 2");
/// panic!("oh no");
/// ```
pub struct SomeStruct;
32 changes: 18 additions & 14 deletions src/test/rustdoc-ui/failed-doctest-output.stdout
Original file line number Diff line number Diff line change
@@ -1,35 +1,39 @@

running 2 tests
test $DIR/failed-doctest-output.rs - OtherStruct (line 17) ... FAILED
test $DIR/failed-doctest-output.rs - SomeStruct (line 11) ... FAILED
test $DIR/failed-doctest-output.rs - OtherStruct (line 20) ... FAILED
test $DIR/failed-doctest-output.rs - SomeStruct (line 10) ... FAILED

failures:

---- $DIR/failed-doctest-output.rs - OtherStruct (line 17) stdout ----
---- $DIR/failed-doctest-output.rs - OtherStruct (line 20) stdout ----
error[E0425]: cannot find value `no` in this scope
--> $DIR/failed-doctest-output.rs:18:1
--> $DIR/failed-doctest-output.rs:21:1
|
3 | no
| ^^ not found in this scope

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.
thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:320:13
Couldn't compile the test.
---- $DIR/failed-doctest-output.rs - SomeStruct (line 10) stdout ----
Test executable failed (exit code 101).

stdout:
stdout 1
stdout 2

stderr:
stderr 1
stderr 2
thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:7:1
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

---- $DIR/failed-doctest-output.rs - SomeStruct (line 11) stdout ----
thread '$DIR/failed-doctest-output.rs - SomeStruct (line 11)' panicked at 'test executable failed:

thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

', src/librustdoc/test.rs:342:17


failures:
$DIR/failed-doctest-output.rs - OtherStruct (line 17)
$DIR/failed-doctest-output.rs - SomeStruct (line 11)
$DIR/failed-doctest-output.rs - OtherStruct (line 20)
$DIR/failed-doctest-output.rs - SomeStruct (line 10)

test result: FAILED. 0 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out

11 changes: 11 additions & 0 deletions src/test/rustdoc-ui/failed-doctest-should-panic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// FIXME: if/when the output of the test harness can be tested on its own, this test should be
// adapted to use that, and that normalize line can go away

// compile-flags:--test
// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR"
// failure-status: 101

/// ```should_panic
/// println!("Hello, world!");
/// ```
pub struct Foo;
14 changes: 14 additions & 0 deletions src/test/rustdoc-ui/failed-doctest-should-panic.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

running 1 test
test $DIR/failed-doctest-should-panic.rs - Foo (line 8) ... FAILED

failures:

---- $DIR/failed-doctest-should-panic.rs - Foo (line 8) stdout ----
Test executable succeeded, but it's marked `should_panic`.

failures:
$DIR/failed-doctest-should-panic.rs - Foo (line 8)

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out

4 changes: 1 addition & 3 deletions src/test/rustdoc-ui/unparseable-doc-test.stdout
Original file line number Diff line number Diff line change
@@ -13,9 +13,7 @@ error: unterminated double quote string

error: aborting due to previous error

thread '$DIR/unparseable-doc-test.rs - foo (line 6)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:320:13
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

Couldn't compile the test.

failures:
$DIR/unparseable-doc-test.rs - foo (line 6)
21 changes: 21 additions & 0 deletions src/test/rustdoc/const-generics/add-impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// ignore-tidy-linelength

#![feature(const_generics)]

#![crate_name = "foo"]

use std::ops::Add;

// @has foo/struct.Simd.html '//pre[@class="rust struct"]' 'pub struct Simd<T, const WIDTH: usize>'
pub struct Simd<T, const WIDTH: usize> {
inner: T,
}

// @has foo/struct.Simd.html '//div[@id="implementations-list"]/h3/code' 'impl Add<Simd<u8, 16>> for Simd<u8, 16>'
impl Add for Simd<u8, 16> {
type Output = Self;

fn add(self, rhs: Self) -> Self::Output {
Self { inner: 0 }
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// ignore-tidy-linelength

#![feature(const_generics)]
#![crate_name = "foo"]

// ignore-tidy-linelength
#![crate_name = "foo"]

pub enum Order {
Sorted,
2 changes: 1 addition & 1 deletion src/test/ui/consts/const-size_of-cycle.stderr
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ LL | bytes: [u8; std::mem::size_of::<Foo>()]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`...
--> $SRC_DIR/libcore/mem.rs:LL:COL
--> $SRC_DIR/libcore/mem/mod.rs:LL:COL
|
LL | intrinsics::size_of::<T>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12 changes: 12 additions & 0 deletions src/test/ui/suggestions/issue-52820.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
struct Bravery {
guts: String,
brains: String,
}

fn main() {
let guts = "mettle";
let _ = Bravery {
guts, //~ ERROR mismatched types
brains: guts.clone(), //~ ERROR mismatched types
};
}
27 changes: 27 additions & 0 deletions src/test/ui/suggestions/issue-52820.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
error[E0308]: mismatched types
--> $DIR/issue-52820.rs:9:9
|
LL | guts,
| ^^^^
| |
| expected struct `std::string::String`, found &str
| help: try using a conversion method: `guts: guts.to_string()`
|
= note: expected type `std::string::String`
found type `&str`

error[E0308]: mismatched types
--> $DIR/issue-52820.rs:10:17
|
LL | brains: guts.clone(),
| ^^^^^^^^^^^^
| |
| expected struct `std::string::String`, found &str
| help: try using a conversion method: `guts.to_string()`
|
= note: expected type `std::string::String`
found type `&str`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0308`.
2 changes: 1 addition & 1 deletion src/test/ui/type_length_limit.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: reached the type-length limit while instantiating `std::mem::drop::<std::option::Op... G), (G, G, G), (G, G, G))))))>>`
--> $SRC_DIR/libcore/mem.rs:LL:COL
--> $SRC_DIR/libcore/mem/mod.rs:LL:COL
|
LL | pub fn drop<T>(_x: T) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^