diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 320f5a97e0a24..e034adde1be86 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -2029,34 +2029,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.help("the semantics of slice patterns changed recently; see issue #62254"); } } else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span) - .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..))) + .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..))) { if let (Some(span), true) = (ti.span, ti.origin_expr) { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { - let applicability = match self.resolve_vars_if_possible(ti.expected).kind() { - ty::Adt(adt_def, _) - if self.tcx.is_diagnostic_item(sym::Option, adt_def.did) - || self.tcx.is_diagnostic_item(sym::Result, adt_def.did) => - { - // Slicing won't work here, but `.as_deref()` might (issue #91328). - err.span_suggestion( - span, - "consider using `as_deref` here", - format!("{}.as_deref()", snippet), - Applicability::MaybeIncorrect, - ); - None - } - // FIXME: instead of checking for Vec only, we could check whether the - // type implements `Deref`; see - // https://github.com/rust-lang/rust/pull/91343#discussion_r761466979 - ty::Adt(adt_def, _) - if self.tcx.is_diagnostic_item(sym::Vec, adt_def.did) => - { - Some(Applicability::MachineApplicable) + let applicability = Autoderef::new( + &self.infcx, + self.param_env, + self.body_id, + span, + self.resolve_vars_if_possible(ti.expected), + span, + ) + .find_map(|(ty, _)| { + match ty.kind() { + ty::Adt(adt_def, _) + if self.tcx.is_diagnostic_item(sym::Option, adt_def.did) + || self.tcx.is_diagnostic_item(sym::Result, adt_def.did) => + { + // Slicing won't work here, but `.as_deref()` might (issue #91328). + err.span_suggestion( + span, + "consider using `as_deref` here", + format!("{}.as_deref()", snippet), + Applicability::MaybeIncorrect, + ); + Some(None) + } + + ty::Slice(..) | ty::Array(..) => { + Some(Some(Applicability::MachineApplicable)) + } + + _ => None, } - _ => Some(Applicability::MaybeIncorrect), - }; + }) + .unwrap_or(Some(Applicability::MaybeIncorrect)); if let Some(applicability) = applicability { err.span_suggestion( diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile index 52c73fd3bd199..f1c42b248f4bd 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile @@ -72,7 +72,7 @@ ENV PATH="/node-v14.4.0-linux-x64/bin:${PATH}" # https://github.com/puppeteer/puppeteer/issues/375 # # We also specify the version in case we need to update it to go around cache limitations. -RUN npm install -g browser-ui-test@0.7.1 --unsafe-perm=true +RUN npm install -g browser-ui-test@0.7.2 --unsafe-perm=true ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ diff --git a/src/doc/book b/src/doc/book index 98904efaa4fc9..67b768c0b660a 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 98904efaa4fc968db8ff59cf2744d9f7ed158166 +Subproject commit 67b768c0b660a069a45f0e5d8ae2f679df1022ab diff --git a/src/doc/nomicon b/src/doc/nomicon index 9493715a6280a..90993eeac93db 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 9493715a6280a1f74be759c7e1ef9999b5d13e6f +Subproject commit 90993eeac93dbf9388992de92965f99cf6f29a03 diff --git a/src/doc/reference b/src/doc/reference index 411c2f0d5cebf..70fc73a6b908e 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 411c2f0d5cebf48453ae2d136ad0c5e611d39aec +Subproject commit 70fc73a6b908e08e66aa0306856c5211312f6c05 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 8763adb62c712..62f58394ba7b2 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 8763adb62c712df69b1d39ea3e692b6d696cc4d9 +Subproject commit 62f58394ba7b203f55ac35ddcc4c0b79578f5706 diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 9de2e733de7c7..3ce57f88938f7 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -381,7 +381,7 @@ the same CSS rules as the official `light` theme. `--check-theme` flag, it discards all other flags and only performs the CSS rule comparison operation. -### `--crate-version`: control the crate version +## `--crate-version`: control the crate version Using this flag looks like this: @@ -418,9 +418,22 @@ Rustdoc only supports Rust source code and Markdown input formats. If the file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file. Otherwise, it assumes that the input file is Rust. +# Unstable command line arguments + ## `--nocapture` When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be captured by rustdoc. Instead, the output will be directed to your terminal, as if you had run the test executable manually. This is especially useful for debugging your tests! + +## `--check` + +When this flag is supplied, rustdoc will type check and lint your code, but will not generate any +documentation or run your doctests. + +Using this flag looks like: + +```bash +rustdoc -Z unstable-options --check src/lib.rs +``` diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml index 82fcca94a1820..7a32d9029103a 100644 --- a/src/test/rustdoc-gui/item-info-width.goml +++ b/src/test/rustdoc-gui/item-info-width.goml @@ -4,5 +4,5 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html size: (1100, 800) // We check that ".item-info" is bigger than its content. assert-css: (".item-info", {"width": "790px"}) -assert-css: (".item-info .stab", {"width": "339.562px"}) +assert-css: (".item-info .stab", {"width": "340px"}) assert-position: (".item-info .stab", {"x": 295}) diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.rs b/src/test/ui/generic-associated-types/bugs/issue-80626.rs index aea8aaf4bb393..a637da6cf6fa7 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-80626.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.rs @@ -1,4 +1,5 @@ // check-fail +// known-bug // This should pass, but it requires `Sized` to be coinductive. @@ -11,7 +12,6 @@ trait Allocator { enum LinkedList { Head, Next(A::Allocated) - //~^ overflow } fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr index e18af9c257f7f..8b0cc78e99949 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-80626.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-80626.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `LinkedList: Sized` - --> $DIR/issue-80626.rs:13:10 + --> $DIR/issue-80626.rs:14:10 | LL | Next(A::Allocated) | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.rs b/src/test/ui/generic-associated-types/bugs/issue-86218.rs index 3f8776a363770..68cd0fd7efce0 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.rs @@ -1,4 +1,5 @@ // check-fail +// known-bug // This should pass, but seems to run into a TAIT issue. @@ -20,7 +21,6 @@ trait Yay { impl<'a> Yay<&'a ()> for () { type InnerStream<'s> = impl Stream + 's; - //~^ the type fn foo<'s>() -> Self::InnerStream<'s> { todo!() } } diff --git a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr index 9f4efc0addb73..98a5f4254bb1b 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-86218.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-86218.stderr @@ -1,11 +1,11 @@ error[E0477]: the type `impl Stream` does not fulfill the required lifetime - --> $DIR/issue-86218.rs:22:28 + --> $DIR/issue-86218.rs:23:28 | LL | type InnerStream<'s> = impl Stream + 's; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: type must outlive the lifetime `'s` as defined here as required by this binding - --> $DIR/issue-86218.rs:22:22 + --> $DIR/issue-86218.rs:23:22 | LL | type InnerStream<'s> = impl Stream + 's; | ^^ diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.rs b/src/test/ui/generic-associated-types/bugs/issue-87735.rs index 5f7a42a740df6..6d6063f8085ba 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87735.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.rs @@ -1,4 +1,5 @@ // check-fail +// known-bug // This should pass, but we need an extension of implied bounds (probably). @@ -23,7 +24,7 @@ struct Foo(T); #[derive(Debug)] struct FooRef<'a, U>(&'a [U]); -impl<'b, T, U> AsRef2 for Foo //~ the type parameter +impl<'b, T, U> AsRef2 for Foo where // * `for<'b, 'c> T: AsRef2 = &'c [U]>>` does not work // diff --git a/src/test/ui/generic-associated-types/bugs/issue-87735.stderr b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr index 31b3a9619b6af..0a18b5f0cbdaa 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87735.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87735.stderr @@ -1,5 +1,5 @@ error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-87735.rs:26:13 + --> $DIR/issue-87735.rs:27:13 | LL | impl<'b, T, U> AsRef2 for Foo | ^ unconstrained type parameter diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.rs b/src/test/ui/generic-associated-types/bugs/issue-87748.rs index 4dbaf429ead26..ffcfd62cbb3be 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87748.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.rs @@ -1,4 +1,5 @@ // check-fail +// known-bug // This should pass, but unnormalized input args aren't treated as implied. @@ -14,7 +15,7 @@ struct Foo; impl MyTrait for Foo { type Assoc<'a, 'b> where 'b: 'a = u32; - fn do_sth(_: u32) {} //~ lifetime bound + fn do_sth(_: u32) {} // fn do_sth(_: Self::Assoc<'static, 'static>) {} // fn do_sth(_: Self::Assoc<'_, '_>) {} } diff --git a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr index c38d447859233..60bb48efbc895 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87748.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87748.stderr @@ -1,16 +1,16 @@ error[E0478]: lifetime bound not satisfied - --> $DIR/issue-87748.rs:17:5 + --> $DIR/issue-87748.rs:18:5 | LL | fn do_sth(_: u32) {} | ^^^^^^^^^^^^^^^^^ | note: lifetime parameter instantiated with the anonymous lifetime #2 defined here - --> $DIR/issue-87748.rs:17:5 + --> $DIR/issue-87748.rs:18:5 | LL | fn do_sth(_: u32) {} | ^^^^^^^^^^^^^^^^^ note: but lifetime parameter must outlive the anonymous lifetime #1 defined here - --> $DIR/issue-87748.rs:17:5 + --> $DIR/issue-87748.rs:18:5 | LL | fn do_sth(_: u32) {} | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.rs b/src/test/ui/generic-associated-types/bugs/issue-87755.rs index 1cd3534ba77a0..31cea12a3e241 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87755.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87755.rs @@ -1,4 +1,5 @@ // check-fail +// known-bug // This should pass. @@ -15,7 +16,6 @@ struct Bar; impl Foo for Bar { type Ass = Bar; - //~^ overflow } fn main() {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-87755.stderr b/src/test/ui/generic-associated-types/bugs/issue-87755.stderr index d2dc991a2b640..5d1aff0117c13 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87755.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87755.stderr @@ -1,5 +1,5 @@ error[E0275]: overflow evaluating the requirement `::Ass == _` - --> $DIR/issue-87755.rs:17:16 + --> $DIR/issue-87755.rs:18:16 | LL | type Ass = Bar; | ^^^ diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.rs b/src/test/ui/generic-associated-types/bugs/issue-87803.rs index 3d2ff38ab049e..57a4b028d93ea 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87803.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-87803.rs @@ -1,4 +1,5 @@ // check-fail +// known-bug // This should pass, but using a type alias vs a reference directly // changes late-bound -> early-bound. @@ -18,7 +19,7 @@ impl Scanner for IdScanner { type Input<'a> = &'a str; type Token<'a> = &'a str; - fn scan<'a>(&mut self, s : &'a str) -> &'a str { //~ lifetime parameters + fn scan<'a>(&mut self, s : &'a str) -> &'a str { s } } diff --git a/src/test/ui/generic-associated-types/bugs/issue-87803.stderr b/src/test/ui/generic-associated-types/bugs/issue-87803.stderr index 759c0440d07ba..c81c051d32a89 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-87803.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-87803.stderr @@ -1,5 +1,5 @@ error[E0195]: lifetime parameters or bounds on method `scan` do not match the trait declaration - --> $DIR/issue-87803.rs:21:12 + --> $DIR/issue-87803.rs:22:12 | LL | fn scan<'a>(&mut self, i : Self::Input<'a>) -> Self::Token<'a>; | ---- lifetimes in impl do not match this method in trait diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.rs b/src/test/ui/generic-associated-types/bugs/issue-88382.rs index f4633ca516999..c9f342405278a 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88382.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.rs @@ -1,4 +1,5 @@ // check-fail +// known-bug // This should pass, but has a missed normalization due to HRTB. @@ -25,7 +26,6 @@ fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) fn main() { do_something(SomeImplementation(), |_| ()); do_something(SomeImplementation(), test); - //~^ type mismatch } fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} diff --git a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr index 05bc58cbba4e6..d06c3ec8de75e 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88382.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88382.stderr @@ -1,5 +1,5 @@ error[E0631]: type mismatch in function arguments - --> $DIR/issue-88382.rs:27:40 + --> $DIR/issue-88382.rs:28:40 | LL | do_something(SomeImplementation(), test); | ------------ ^^^^ expected signature of `for<'a> fn(&mut ::Iterator<'a>) -> _` @@ -10,7 +10,7 @@ LL | fn test<'a, I: Iterable>(_: &mut I::Iterator<'a>) {} | ------------------------------------------------- found signature of `for<'r> fn(&'r mut std::iter::Empty) -> _` | note: required by a bound in `do_something` - --> $DIR/issue-88382.rs:21:56 + --> $DIR/issue-88382.rs:22:56 | LL | fn do_something(i: I, mut f: impl for<'a> Fn(&mut I::Iterator<'a>)) { | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `do_something` diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.rs b/src/test/ui/generic-associated-types/bugs/issue-88460.rs index 7e62790cc50c3..b31d012d2fc41 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88460.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.rs @@ -1,4 +1,5 @@ // check-fail +// known-bug // This should pass, but has a missed normalization due to HRTB. @@ -27,5 +28,4 @@ impl Trait for Foo { fn main() { test(Foo); - //~^ the trait bound } diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr index 604658da7d2c2..0b83e9da1ab7a 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied - --> $DIR/issue-88460.rs:29:5 + --> $DIR/issue-88460.rs:30:5 | LL | test(Foo); | ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>` | note: required by a bound in `test` - --> $DIR/issue-88460.rs:16:27 + --> $DIR/issue-88460.rs:17:27 | LL | fn test(value: T) | ---- required by a bound in this diff --git a/src/test/ui/generic-associated-types/bugs/issue-88526.rs b/src/test/ui/generic-associated-types/bugs/issue-88526.rs index 90568fcb40125..c72a450b9261c 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88526.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-88526.rs @@ -1,4 +1,5 @@ // check-fail +// known-bug // This should pass, but requires more logic. @@ -23,7 +24,7 @@ struct TestB f: F, } -impl<'q, Q, I, F> A for TestB //~ the type parameter +impl<'q, Q, I, F> A for TestB where Q: A = &'q I>, F: Fn(I), diff --git a/src/test/ui/generic-associated-types/bugs/issue-88526.stderr b/src/test/ui/generic-associated-types/bugs/issue-88526.stderr index ccc5ae0b621a1..127c889bf715e 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-88526.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-88526.stderr @@ -1,5 +1,5 @@ error[E0207]: the type parameter `I` is not constrained by the impl trait, self type, or predicates - --> $DIR/issue-88526.rs:26:13 + --> $DIR/issue-88526.rs:27:13 | LL | impl<'q, Q, I, F> A for TestB | ^ unconstrained type parameter diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.rs b/src/test/ui/generic-associated-types/bugs/issue-89008.rs index 5d850849fd21c..1581b7105a867 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-89008.rs +++ b/src/test/ui/generic-associated-types/bugs/issue-89008.rs @@ -1,5 +1,6 @@ // check-fail // edition:2021 +// known-bug // This should pass, but seems to run into a TAIT bug. @@ -31,11 +32,11 @@ trait X { struct Y; impl X for Y { - type LineStream<'a, Repr> = impl Stream; //~ could not find + type LineStream<'a, Repr> = impl Stream; type LineStreamFut<'a, Repr> = impl Future> ; - fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { //~ type mismatch + fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { async {empty()} } } diff --git a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr index 48745fe0fbd96..c2687ca540153 100644 --- a/src/test/ui/generic-associated-types/bugs/issue-89008.stderr +++ b/src/test/ui/generic-associated-types/bugs/issue-89008.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving ` as Future>::Output == impl Stream` - --> $DIR/issue-89008.rs:38:43 + --> $DIR/issue-89008.rs:39:43 | LL | type LineStream<'a, Repr> = impl Stream; | ------------------------ the expected opaque type @@ -11,7 +11,7 @@ LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> { found struct `Empty<_>` error: could not find defining uses - --> $DIR/issue-89008.rs:34:33 + --> $DIR/issue-89008.rs:35:33 | LL | type LineStream<'a, Repr> = impl Stream; | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/typeck/issue-91328.fixed b/src/test/ui/typeck/issue-91328.fixed index 81b6a99607215..c0384399a92e6 100644 --- a/src/test/ui/typeck/issue-91328.fixed +++ b/src/test/ui/typeck/issue-91328.fixed @@ -34,4 +34,14 @@ fn baz(v: Vec) -> i32 { } } +fn qux(a: &Option>) -> i32 { + match a.as_deref() { + //~^ HELP: consider using `as_deref` here + Some([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + fn main() {} diff --git a/src/test/ui/typeck/issue-91328.rs b/src/test/ui/typeck/issue-91328.rs index e938d8f5c9f04..63602d26f970d 100644 --- a/src/test/ui/typeck/issue-91328.rs +++ b/src/test/ui/typeck/issue-91328.rs @@ -34,4 +34,14 @@ fn baz(v: Vec) -> i32 { } } +fn qux(a: &Option>) -> i32 { + match a { + //~^ HELP: consider using `as_deref` here + Some([a, b]) => a + b, + //~^ ERROR: expected an array or slice + //~| NOTE: pattern cannot match with input type + _ => 42, + } +} + fn main() {} diff --git a/src/test/ui/typeck/issue-91328.stderr b/src/test/ui/typeck/issue-91328.stderr index 96ad00cde4f7b..f2f407bcafff2 100644 --- a/src/test/ui/typeck/issue-91328.stderr +++ b/src/test/ui/typeck/issue-91328.stderr @@ -25,6 +25,15 @@ LL | LL | [a, b] => a + b, | ^^^^^^ pattern cannot match with input type `Vec` -error: aborting due to 3 previous errors +error[E0529]: expected an array or slice, found `Box<[i32; 2]>` + --> $DIR/issue-91328.rs:40:14 + | +LL | match a { + | - help: consider using `as_deref` here: `a.as_deref()` +LL | +LL | Some([a, b]) => a + b, + | ^^^^^^ pattern cannot match with input type `Box<[i32; 2]>` + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0529`. diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index da7a19139c65b..5b8ee9fbdc97e 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -41,12 +41,15 @@ impl EarlyProps { pub fn from_reader(config: &Config, testfile: &Path, rdr: R) -> Self { let mut props = EarlyProps::default(); iter_header(testfile, rdr, &mut |_, ln| { - if let Some(s) = config.parse_aux_build(ln) { - props.aux.push(s); - } - if let Some(ac) = config.parse_aux_crate(ln) { - props.aux_crate.push(ac); - } + config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| { + r.trim().to_string() + }); + config.push_name_value_directive( + ln, + directives::AUX_CRATE, + &mut props.aux_crate, + Config::parse_aux_crate, + ); config.parse_and_update_revisions(ln, &mut props.revisions); }); return props; @@ -126,6 +129,12 @@ pub struct TestProps { // empty before the test starts. Incremental mode tests will reuse the // incremental directory between passes in the same test. pub incremental: bool, + // If `true`, this test is a known bug. + // + // When set, some requirements are relaxed. Currently, this only means no + // error annotations are needed, but this may be updated in the future to + // include other relaxations. + pub known_bug: bool, // How far should the test proceed while still passing. pass_mode: Option, // Ignore `--pass` overrides from the command line for this test. @@ -150,6 +159,38 @@ pub struct TestProps { pub stderr_per_bitwidth: bool, } +mod directives { + pub const ERROR_PATTERN: &'static str = "error-pattern"; + pub const COMPILE_FLAGS: &'static str = "compile-flags"; + pub const RUN_FLAGS: &'static str = "run-flags"; + pub const SHOULD_ICE: &'static str = "should-ice"; + pub const BUILD_AUX_DOCS: &'static str = "build-aux-docs"; + pub const FORCE_HOST: &'static str = "force-host"; + pub const CHECK_STDOUT: &'static str = "check-stdout"; + pub const CHECK_RUN_RESULTS: &'static str = "check-run-results"; + pub const DONT_CHECK_COMPILER_STDOUT: &'static str = "dont-check-compiler-stdout"; + pub const DONT_CHECK_COMPILER_STDERR: &'static str = "dont-check-compiler-stderr"; + pub const NO_PREFER_DYNAMIC: &'static str = "no-prefer-dynamic"; + pub const PRETTY_EXPANDED: &'static str = "pretty-expanded"; + pub const PRETTY_MODE: &'static str = "pretty-mode"; + pub const PRETTY_COMPARE_ONLY: &'static str = "pretty-compare-only"; + pub const AUX_BUILD: &'static str = "aux-build"; + pub const AUX_CRATE: &'static str = "aux-crate"; + pub const EXEC_ENV: &'static str = "exec-env"; + pub const RUSTC_ENV: &'static str = "rustc-env"; + pub const UNSET_RUSTC_ENV: &'static str = "unset-rustc-env"; + pub const FORBID_OUTPUT: &'static str = "forbid-output"; + pub const CHECK_TEST_LINE_NUMBERS_MATCH: &'static str = "check-test-line-numbers-match"; + pub const IGNORE_PASS: &'static str = "ignore-pass"; + pub const FAILURE_STATUS: &'static str = "failure-status"; + pub const RUN_RUSTFIX: &'static str = "run-rustfix"; + pub const RUSTFIX_ONLY_MACHINE_APPLICABLE: &'static str = "rustfix-only-machine-applicable"; + pub const ASSEMBLY_OUTPUT: &'static str = "assembly-output"; + pub const STDERR_PER_BITWIDTH: &'static str = "stderr-per-bitwidth"; + pub const INCREMENTAL: &'static str = "incremental"; + pub const KNOWN_BUG: &'static str = "known-bug"; +} + impl TestProps { pub fn new() -> Self { TestProps { @@ -176,6 +217,7 @@ impl TestProps { forbid_output: vec![], incremental_dir: None, incremental: false, + known_bug: false, pass_mode: None, fail_mode: None, ignore_pass: false, @@ -228,11 +270,16 @@ impl TestProps { return; } - if let Some(ep) = config.parse_error_pattern(ln) { - self.error_patterns.push(ep); - } + use directives::*; - if let Some(flags) = config.parse_compile_flags(ln) { + config.push_name_value_directive( + ln, + ERROR_PATTERN, + &mut self.error_patterns, + |r| r, + ); + + if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) { self.compile_flags.extend(flags.split_whitespace().map(|s| s.to_owned())); } @@ -243,93 +290,73 @@ impl TestProps { config.parse_and_update_revisions(ln, &mut self.revisions); - if self.run_flags.is_none() { - self.run_flags = config.parse_run_flags(ln); - } + config.set_name_value_directive(ln, RUN_FLAGS, &mut self.run_flags, |r| r); if self.pp_exact.is_none() { self.pp_exact = config.parse_pp_exact(ln, testfile); } - if !self.should_ice { - self.should_ice = config.parse_should_ice(ln); - } - - if !self.build_aux_docs { - self.build_aux_docs = config.parse_build_aux_docs(ln); - } - - if !self.force_host { - self.force_host = config.parse_force_host(ln); - } - - if !self.check_stdout { - self.check_stdout = config.parse_check_stdout(ln); - } - - if !self.check_run_results { - self.check_run_results = config.parse_check_run_results(ln); - } - - if !self.dont_check_compiler_stdout { - self.dont_check_compiler_stdout = config.parse_dont_check_compiler_stdout(ln); - } - - if !self.dont_check_compiler_stderr { - self.dont_check_compiler_stderr = config.parse_dont_check_compiler_stderr(ln); - } - - if !self.no_prefer_dynamic { - self.no_prefer_dynamic = config.parse_no_prefer_dynamic(ln); - } - - if !self.pretty_expanded { - self.pretty_expanded = config.parse_pretty_expanded(ln); - } - - if let Some(m) = config.parse_pretty_mode(ln) { + config.set_name_directive(ln, SHOULD_ICE, &mut self.should_ice); + config.set_name_directive(ln, BUILD_AUX_DOCS, &mut self.build_aux_docs); + config.set_name_directive(ln, FORCE_HOST, &mut self.force_host); + config.set_name_directive(ln, CHECK_STDOUT, &mut self.check_stdout); + config.set_name_directive(ln, CHECK_RUN_RESULTS, &mut self.check_run_results); + config.set_name_directive( + ln, + DONT_CHECK_COMPILER_STDOUT, + &mut self.dont_check_compiler_stdout, + ); + config.set_name_directive( + ln, + DONT_CHECK_COMPILER_STDERR, + &mut self.dont_check_compiler_stderr, + ); + config.set_name_directive(ln, NO_PREFER_DYNAMIC, &mut self.no_prefer_dynamic); + config.set_name_directive(ln, PRETTY_EXPANDED, &mut self.pretty_expanded); + + if let Some(m) = config.parse_name_value_directive(ln, PRETTY_MODE) { self.pretty_mode = m; } - if !self.pretty_compare_only { - self.pretty_compare_only = config.parse_pretty_compare_only(ln); - } - - if let Some(ab) = config.parse_aux_build(ln) { - self.aux_builds.push(ab); - } - - if let Some(ac) = config.parse_aux_crate(ln) { - self.aux_crates.push(ac); - } - - if let Some(ee) = config.parse_env(ln, "exec-env") { - self.exec_env.push(ee); - } - - if let Some(ee) = config.parse_env(ln, "rustc-env") { - self.rustc_env.push(ee); - } - - if let Some(ev) = config.parse_name_value_directive(ln, "unset-rustc-env") { - self.unset_rustc_env.push(ev); - } - - if let Some(of) = config.parse_forbid_output(ln) { - self.forbid_output.push(of); - } - - if !self.check_test_line_numbers_match { - self.check_test_line_numbers_match = - config.parse_check_test_line_numbers_match(ln); - } + config.set_name_directive(ln, PRETTY_COMPARE_ONLY, &mut self.pretty_compare_only); + config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| { + r.trim().to_string() + }); + config.push_name_value_directive( + ln, + AUX_CRATE, + &mut self.aux_crates, + Config::parse_aux_crate, + ); + config.push_name_value_directive( + ln, + EXEC_ENV, + &mut self.exec_env, + Config::parse_env, + ); + config.push_name_value_directive( + ln, + RUSTC_ENV, + &mut self.rustc_env, + Config::parse_env, + ); + config.push_name_value_directive( + ln, + UNSET_RUSTC_ENV, + &mut self.unset_rustc_env, + |r| r, + ); + config.push_name_value_directive(ln, FORBID_OUTPUT, &mut self.forbid_output, |r| r); + config.set_name_directive( + ln, + CHECK_TEST_LINE_NUMBERS_MATCH, + &mut self.check_test_line_numbers_match, + ); self.update_pass_mode(ln, cfg, config); self.update_fail_mode(ln, config); - if !self.ignore_pass { - self.ignore_pass = config.parse_ignore_pass(ln); - } + config.set_name_directive(ln, IGNORE_PASS, &mut self.ignore_pass); if let Some(rule) = config.parse_custom_normalization(ln, "normalize-stdout") { self.normalize_stdout.push(rule); @@ -338,30 +365,28 @@ impl TestProps { self.normalize_stderr.push(rule); } - if let Some(code) = config.parse_failure_status(ln) { + if let Some(code) = config + .parse_name_value_directive(ln, FAILURE_STATUS) + .and_then(|code| code.trim().parse::().ok()) + { self.failure_status = code; } - if !self.run_rustfix { - self.run_rustfix = config.parse_run_rustfix(ln); - } - - if !self.rustfix_only_machine_applicable { - self.rustfix_only_machine_applicable = - config.parse_rustfix_only_machine_applicable(ln); - } - - if self.assembly_output.is_none() { - self.assembly_output = config.parse_assembly_output(ln); - } - - if !self.stderr_per_bitwidth { - self.stderr_per_bitwidth = config.parse_stderr_per_bitwidth(ln); - } - - if !self.incremental { - self.incremental = config.parse_incremental(ln); - } + config.set_name_directive(ln, RUN_RUSTFIX, &mut self.run_rustfix); + config.set_name_directive( + ln, + RUSTFIX_ONLY_MACHINE_APPLICABLE, + &mut self.rustfix_only_machine_applicable, + ); + config.set_name_value_directive( + ln, + ASSEMBLY_OUTPUT, + &mut self.assembly_output, + |r| r.trim().to_string(), + ); + config.set_name_directive(ln, STDERR_PER_BITWIDTH, &mut self.stderr_per_bitwidth); + config.set_name_directive(ln, INCREMENTAL, &mut self.incremental); + config.set_name_directive(ln, KNOWN_BUG, &mut self.known_bug); }); } @@ -503,33 +528,12 @@ fn iter_header(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str> } impl Config { - fn parse_should_ice(&self, line: &str) -> bool { - self.parse_name_directive(line, "should-ice") - } - fn parse_error_pattern(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "error-pattern") - } - - fn parse_forbid_output(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "forbid-output") - } - - fn parse_aux_build(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "aux-build").map(|r| r.trim().to_string()) - } - - fn parse_aux_crate(&self, line: &str) -> Option<(String, String)> { - self.parse_name_value_directive(line, "aux-crate").map(|r| { - let mut parts = r.trim().splitn(2, '='); - ( - parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(), - parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(), - ) - }) - } - - fn parse_compile_flags(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "compile-flags") + fn parse_aux_crate(r: String) -> (String, String) { + let mut parts = r.trim().splitn(2, '='); + ( + parts.next().expect("missing aux-crate name (e.g. log=log.rs)").to_string(), + parts.next().expect("missing aux-crate value (e.g. log=log.rs)").to_string(), + ) } fn parse_and_update_revisions(&self, line: &str, existing: &mut Vec) { @@ -544,87 +548,18 @@ impl Config { } } - fn parse_run_flags(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "run-flags") - } - - fn parse_force_host(&self, line: &str) -> bool { - self.parse_name_directive(line, "force-host") - } - - fn parse_build_aux_docs(&self, line: &str) -> bool { - self.parse_name_directive(line, "build-aux-docs") - } - - fn parse_check_stdout(&self, line: &str) -> bool { - self.parse_name_directive(line, "check-stdout") - } - - fn parse_check_run_results(&self, line: &str) -> bool { - self.parse_name_directive(line, "check-run-results") - } - - fn parse_dont_check_compiler_stdout(&self, line: &str) -> bool { - self.parse_name_directive(line, "dont-check-compiler-stdout") - } - - fn parse_dont_check_compiler_stderr(&self, line: &str) -> bool { - self.parse_name_directive(line, "dont-check-compiler-stderr") - } - - fn parse_no_prefer_dynamic(&self, line: &str) -> bool { - self.parse_name_directive(line, "no-prefer-dynamic") - } - - fn parse_pretty_expanded(&self, line: &str) -> bool { - self.parse_name_directive(line, "pretty-expanded") - } - - fn parse_pretty_mode(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "pretty-mode") - } - - fn parse_pretty_compare_only(&self, line: &str) -> bool { - self.parse_name_directive(line, "pretty-compare-only") - } - - fn parse_failure_status(&self, line: &str) -> Option { - match self.parse_name_value_directive(line, "failure-status") { - Some(code) => code.trim().parse::().ok(), - _ => None, - } - } - - fn parse_check_test_line_numbers_match(&self, line: &str) -> bool { - self.parse_name_directive(line, "check-test-line-numbers-match") - } - - fn parse_ignore_pass(&self, line: &str) -> bool { - self.parse_name_directive(line, "ignore-pass") - } - - fn parse_stderr_per_bitwidth(&self, line: &str) -> bool { - self.parse_name_directive(line, "stderr-per-bitwidth") - } - - fn parse_assembly_output(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "assembly-output").map(|r| r.trim().to_string()) - } - - fn parse_env(&self, line: &str, name: &str) -> Option<(String, String)> { - self.parse_name_value_directive(line, name).map(|nv| { - // nv is either FOO or FOO=BAR - let mut strs: Vec = nv.splitn(2, '=').map(str::to_owned).collect(); + fn parse_env(nv: String) -> (String, String) { + // nv is either FOO or FOO=BAR + let mut strs: Vec = nv.splitn(2, '=').map(str::to_owned).collect(); - match strs.len() { - 1 => (strs.pop().unwrap(), String::new()), - 2 => { - let end = strs.pop().unwrap(); - (strs.pop().unwrap(), end) - } - n => panic!("Expected 1 or 2 strings, not {}", n), + match strs.len() { + 1 => (strs.pop().unwrap(), String::new()), + 2 => { + let end = strs.pop().unwrap(); + (strs.pop().unwrap(), end) } - }) + n => panic!("Expected 1 or 2 strings, not {}", n), + } } fn parse_pp_exact(&self, line: &str, testfile: &Path) -> Option { @@ -736,20 +671,38 @@ impl Config { None } - fn parse_run_rustfix(&self, line: &str) -> bool { - self.parse_name_directive(line, "run-rustfix") + fn parse_edition(&self, line: &str) -> Option { + self.parse_name_value_directive(line, "edition") } - fn parse_rustfix_only_machine_applicable(&self, line: &str) -> bool { - self.parse_name_directive(line, "rustfix-only-machine-applicable") + fn set_name_directive(&self, line: &str, directive: &str, value: &mut bool) { + if !*value { + *value = self.parse_name_directive(line, directive) + } } - fn parse_edition(&self, line: &str) -> Option { - self.parse_name_value_directive(line, "edition") + fn set_name_value_directive( + &self, + line: &str, + directive: &str, + value: &mut Option, + parse: impl FnOnce(String) -> T, + ) { + if value.is_none() { + *value = self.parse_name_value_directive(line, directive).map(parse); + } } - fn parse_incremental(&self, line: &str) -> bool { - self.parse_name_directive(line, "incremental") + fn push_name_value_directive( + &self, + line: &str, + directive: &str, + values: &mut Vec, + parse: impl FnOnce(String) -> T, + ) { + if let Some(value) = self.parse_name_value_directive(line, directive).map(parse) { + values.push(value); + } } } @@ -901,7 +854,8 @@ pub fn make_test_description( ignore |= !has_hwasan && config.parse_name_directive(ln, "needs-sanitizer-hwaddress"); ignore |= config.target_panic == PanicStrategy::Abort && config.parse_name_directive(ln, "needs-unwind"); - ignore |= config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln); + ignore |= config.target == "wasm32-unknown-unknown" + && config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS); ignore |= config.debugger == Some(Debugger::Cdb) && ignore_cdb(config, ln); ignore |= config.debugger == Some(Debugger::Gdb) && ignore_gdb(config, ln); ignore |= config.debugger == Some(Debugger::Lldb) && ignore_lldb(config, ln); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f6ddac3a65e06..7fe7db0801b47 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1274,6 +1274,16 @@ impl<'test> TestCx<'test> { self.fatal_proc_rec("process did not return an error status", proc_res); } + if self.props.known_bug { + if !expected_errors.is_empty() { + self.fatal_proc_rec( + "`known_bug` tests should not have an expected errors", + proc_res, + ); + } + return; + } + // On Windows, keep all '\' path separators to match the paths reported in the JSON output // from the compiler let os_file_name = self.testpaths.file.display().to_string(); @@ -1310,6 +1320,7 @@ impl<'test> TestCx<'test> { } None => { + // If the test is a known bug, don't require that the error is annotated if self.is_unexpected_compiler_message(actual_error, expect_help, expect_note) { self.error(&format!( "{}:{}: unexpected {}: '{}'",