diff --git a/Cargo.lock b/Cargo.lock index d5e2969e9649a..e082fc5088aa2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 9c3a17bff6b7a..5605ec34083be 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -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`. diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 736b4633b38f9..593a09b6866db 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -170,16 +170,11 @@ pub enum Set1 { impl Set1 { 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, + }; } } diff --git a/src/librustc_macros/Cargo.toml b/src/librustc_macros/Cargo.toml index 6e32a53c364a6..f989ebc6dfd8e 100644 --- a/src/librustc_macros/Cargo.toml +++ b/src/librustc_macros/Cargo.toml @@ -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" diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index f464e58e36b15..e3a79b24cabe8 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -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> { + 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(), + ) }) } diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index a292115707d8e..7c8a3e2f68afd 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -7,7 +7,7 @@ use rustc::mir::{ use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::{self, Const, DefIdTree, Ty, TyS, TyCtxt}; use rustc_data_structures::indexed_vec::Idx; -use syntax_pos::Span; +use syntax_pos::{Span, CompilerDesugaringKind}; use syntax_pos::symbol::kw; use crate::dataflow::move_paths::InitLocation; @@ -41,14 +41,19 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { ); let mut err; - let item_msg; let reason; let access_place_desc = self.describe_place(access_place); debug!("report_mutability_error: access_place_desc={:?}", access_place_desc); + let mut item_msg = match (&access_place_desc, &the_place_err) { + (Some(desc), _) => format!("`{}`", desc), + (None, Place::Base(PlaceBase::Local(local))) if self.mir.local_decls[*local] + .source_info.span.is_compiler_desugaring(CompilerDesugaringKind::Async) + => "`async fn` parameter".to_string(), + (None, _) => "temporary place".to_string(), + }; match the_place_err { Place::Base(PlaceBase::Local(local)) => { - item_msg = format!("`{}`", access_place_desc.unwrap()); if let Place::Base(PlaceBase::Local(_)) = access_place { reason = ", as it is not declared as mutable".to_string(); } else { @@ -67,7 +72,6 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { base.ty(self.mir, self.infcx.tcx).ty )); - item_msg = format!("`{}`", access_place_desc.unwrap()); if self.is_upvar_field_projection(access_place).is_some() { reason = ", as it is not declared as mutable".to_string(); } else { @@ -82,7 +86,6 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { }) => { if *base == Place::Base(PlaceBase::Local(Local::new(1))) && !self.upvars.is_empty() { - item_msg = format!("`{}`", access_place_desc.unwrap()); debug_assert!(self.mir.local_decls[Local::new(1)].ty.is_region_ptr()); debug_assert!(is_closure_or_generator( the_place_err.ty(self.mir, self.infcx.tcx).ty @@ -105,7 +108,6 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { false } } { - item_msg = format!("`{}`", access_place_desc.unwrap()); reason = ", as it is immutable for the pattern guard".to_string(); } else { let pointer_type = @@ -114,8 +116,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { } else { "`*const` pointer" }; - if let Some(desc) = access_place_desc { - item_msg = format!("`{}`", desc); + if access_place_desc.is_some() { reason = match error_access { AccessKind::Move | AccessKind::Mutate => format!(" which is behind a {}", pointer_type), @@ -135,10 +136,9 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> { Place::Base(PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. })) => { if let Place::Base(PlaceBase::Static(_)) = access_place { - item_msg = format!("immutable static item `{}`", access_place_desc.unwrap()); + item_msg = format!("immutable static item {}", item_msg); reason = String::new(); } else { - item_msg = format!("`{}`", access_place_desc.unwrap()); let static_name = &self.infcx.tcx.item_name(*def_id); reason = format!(", as `{}` is an immutable static item", static_name); } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 724f8d886e8a7..c3ea9ff40a843 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -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) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 8701d751f2d91..c5b85d52566d3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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() { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4ee63a4c9703b..e68ad6a7c3b4b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3145,10 +3145,7 @@ impl<'tcx> Clean 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), } } } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index d76d4380755f2..9d1a0cc074c88 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -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, libs: Vec, - cg: CodegenOptions, externs: Externs, - should_panic: bool, no_run: bool, as_test_harness: bool, - compile_fail: bool, mut error_codes: Vec, opts: &TestOptions, - maybe_sysroot: Option, linker: Option, edition: Edition, - persist_doctests: Option) { +/// 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), + /// 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, + libs: Vec, + cg: CodegenOptions, + externs: Externs, + should_panic: bool, + no_run: bool, + as_test_harness: bool, + compile_fail: bool, + mut error_codes: Vec, + opts: &TestOptions, + maybe_sysroot: Option, + linker: Option, + edition: Edition, + persist_doctests: Option, +) -> 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 ()); + } }), }); } diff --git a/src/test/rustdoc-ui/failed-doctest-compile-fail.rs b/src/test/rustdoc-ui/failed-doctest-compile-fail.rs new file mode 100644 index 0000000000000..297d6efd45fee --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-compile-fail.rs @@ -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; diff --git a/src/test/rustdoc-ui/failed-doctest-compile-fail.stdout b/src/test/rustdoc-ui/failed-doctest-compile-fail.stdout new file mode 100644 index 0000000000000..74e33d7beebeb --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-compile-fail.stdout @@ -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 + diff --git a/src/test/rustdoc-ui/failed-doctest-missing-codes.rs b/src/test/rustdoc-ui/failed-doctest-missing-codes.rs new file mode 100644 index 0000000000000..62102062d4991 --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-missing-codes.rs @@ -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; diff --git a/src/test/rustdoc-ui/failed-doctest-missing-codes.stdout b/src/test/rustdoc-ui/failed-doctest-missing-codes.stdout new file mode 100644 index 0000000000000..d206b721765b2 --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-missing-codes.stdout @@ -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 + diff --git a/src/test/rustdoc-ui/failed-doctest-output.rs b/src/test/rustdoc-ui/failed-doctest-output.rs index 48f1424e6b23d..d2cdeb8f8f50e 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.rs +++ b/src/test/rustdoc-ui/failed-doctest-output.rs @@ -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; diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout index 45efa30d9919c..0c42c652d786c 100644 --- a/src/test/rustdoc-ui/failed-doctest-output.stdout +++ b/src/test/rustdoc-ui/failed-doctest-output.stdout @@ -1,13 +1,13 @@ 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 @@ -15,21 +15,25 @@ error[E0425]: cannot find value `no` 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 diff --git a/src/test/rustdoc-ui/failed-doctest-should-panic.rs b/src/test/rustdoc-ui/failed-doctest-should-panic.rs new file mode 100644 index 0000000000000..400fb97804aab --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-should-panic.rs @@ -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; diff --git a/src/test/rustdoc-ui/failed-doctest-should-panic.stdout b/src/test/rustdoc-ui/failed-doctest-should-panic.stdout new file mode 100644 index 0000000000000..081b64b50af9b --- /dev/null +++ b/src/test/rustdoc-ui/failed-doctest-should-panic.stdout @@ -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 + diff --git a/src/test/rustdoc-ui/unparseable-doc-test.stdout b/src/test/rustdoc-ui/unparseable-doc-test.stdout index f31b64fbce36a..0350c01643607 100644 --- a/src/test/rustdoc-ui/unparseable-doc-test.stdout +++ b/src/test/rustdoc-ui/unparseable-doc-test.stdout @@ -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) diff --git a/src/test/rustdoc/const-generics/add-impl.rs b/src/test/rustdoc/const-generics/add-impl.rs new file mode 100644 index 0000000000000..ed45d339728bc --- /dev/null +++ b/src/test/rustdoc/const-generics/add-impl.rs @@ -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' +pub struct Simd { + inner: T, +} + +// @has foo/struct.Simd.html '//div[@id="implementations-list"]/h3/code' 'impl Add> for Simd' +impl Add for Simd { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + Self { inner: 0 } + } +} diff --git a/src/test/rustdoc/generic-const.rs b/src/test/rustdoc/const-generics/const-impl.rs similarity index 99% rename from src/test/rustdoc/generic-const.rs rename to src/test/rustdoc/const-generics/const-impl.rs index d6794ac8f1d94..85ee6d3376b27 100644 --- a/src/test/rustdoc/generic-const.rs +++ b/src/test/rustdoc/const-generics/const-impl.rs @@ -1,7 +1,8 @@ +// ignore-tidy-linelength + #![feature(const_generics)] -#![crate_name = "foo"] -// ignore-tidy-linelength +#![crate_name = "foo"] pub enum Order { Sorted, diff --git a/src/test/ui/async-await/issues/issue-61187.rs b/src/test/ui/async-await/issues/issue-61187.rs new file mode 100644 index 0000000000000..8b939b43b8bd4 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-61187.rs @@ -0,0 +1,9 @@ +// edition:2018 +#![feature(async_await)] + +fn main() { +} + +async fn response(data: Vec) { + data.reverse(); //~ ERROR E0596 +} diff --git a/src/test/ui/async-await/issues/issue-61187.stderr b/src/test/ui/async-await/issues/issue-61187.stderr new file mode 100644 index 0000000000000..52fe15e8cf7c7 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-61187.stderr @@ -0,0 +1,11 @@ +error[E0596]: cannot borrow `async fn` parameter as mutable, as it is not declared as mutable + --> $DIR/issue-61187.rs:8:5 + | +LL | async fn response(data: Vec) { + | ---- help: consider changing this to be mutable: `mut data` +LL | data.reverse(); + | ^^^^ cannot borrow as mutable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/suggestions/issue-52820.rs b/src/test/ui/suggestions/issue-52820.rs new file mode 100644 index 0000000000000..075b07f565203 --- /dev/null +++ b/src/test/ui/suggestions/issue-52820.rs @@ -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 + }; +} diff --git a/src/test/ui/suggestions/issue-52820.stderr b/src/test/ui/suggestions/issue-52820.stderr new file mode 100644 index 0000000000000..fb568aca250e7 --- /dev/null +++ b/src/test/ui/suggestions/issue-52820.stderr @@ -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`.