diff options
| author | bors <bors@rust-lang.org> | 2024-01-20 02:58:08 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-01-20 02:58:08 +0000 |
| commit | 128148d4cf742c3056e9bfc65e7cc9531cb0f815 (patch) | |
| tree | 0eedeffb6a188f3dd18f99d070ba66e814779213 /tests | |
| parent | 0547c41f906760ce117a55ca690820b44d8e7eef (diff) | |
| parent | ee126973b0075060d9d95e401533181c5e8c5864 (diff) | |
Auto merge of #120136 - matthiaskrgr:rollup-3zzb0z9, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #117561 (Stabilize `slice_first_last_chunk`) - #117662 ([rustdoc] Allows links in headings) - #119815 (Format sources into the error message when loading codegen backends) - #119835 (Exhaustiveness: simplify empty pattern logic) - #119984 (Change return type of unstable `Waker::noop()` from `Waker` to `&Waker`.) - #120009 (never_patterns: typecheck never patterns) - #120122 (Don't add needs-triage to A-diagnostics) - #120126 (Suggest `.swap()` when encountering conflicting borrows from `mem::swap` on a slice) - #120134 (Restrict access to the private field of newtype indexes) Failed merges: - #119968 (Remove unused/unnecessary features) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'tests')
30 files changed, 315 insertions, 138 deletions
diff --git a/tests/coverage/async.coverage b/tests/coverage/async.coverage index 015e03d5165..23161458850 100644 --- a/tests/coverage/async.coverage +++ b/tests/coverage/async.coverage @@ -117,8 +117,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async.rs b/tests/coverage/async.rs index abc9e5f7f64..df29682968d 100644 --- a/tests/coverage/async.rs +++ b/tests/coverage/async.rs @@ -110,8 +110,7 @@ mod executor { #[coverage(off)] pub fn block_on<F: Future>(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async2.coverage b/tests/coverage/async2.coverage index acd83de9493..a69eefe72cb 100644 --- a/tests/coverage/async2.coverage +++ b/tests/coverage/async2.coverage @@ -41,8 +41,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async2.rs b/tests/coverage/async2.rs index 393573f7dc9..ae83f0103e6 100644 --- a/tests/coverage/async2.rs +++ b/tests/coverage/async2.rs @@ -39,8 +39,7 @@ mod executor { #[coverage(off)] pub fn block_on<F: Future>(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async_block.coverage b/tests/coverage/async_block.coverage index 297397ca26c..0e24b80124f 100644 --- a/tests/coverage/async_block.coverage +++ b/tests/coverage/async_block.coverage @@ -24,8 +24,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/async_block.rs b/tests/coverage/async_block.rs index 9d8647bf1f2..f94bcfe3193 100644 --- a/tests/coverage/async_block.rs +++ b/tests/coverage/async_block.rs @@ -23,8 +23,7 @@ mod executor { #[coverage(off)] pub fn block_on<F: Future>(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/closure_macro_async.coverage b/tests/coverage/closure_macro_async.coverage index 2c9bd4ac97a..2336d4d0528 100644 --- a/tests/coverage/closure_macro_async.coverage +++ b/tests/coverage/closure_macro_async.coverage @@ -54,8 +54,7 @@ LL| | #[coverage(off)] LL| | pub fn block_on<F: Future>(mut future: F) -> F::Output { LL| | let mut future = pin!(future); - LL| | let waker = Waker::noop(); - LL| | let mut context = Context::from_waker(&waker); + LL| | let mut context = Context::from_waker(Waker::noop()); LL| | LL| | loop { LL| | if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/coverage/closure_macro_async.rs b/tests/coverage/closure_macro_async.rs index a7f0cabb4c2..9f5721b5e26 100644 --- a/tests/coverage/closure_macro_async.rs +++ b/tests/coverage/closure_macro_async.rs @@ -53,8 +53,7 @@ mod executor { #[coverage(off)] pub fn block_on<F: Future>(mut future: F) -> F::Output { let mut future = pin!(future); - let waker = Waker::noop(); - let mut context = Context::from_waker(&waker); + let mut context = Context::from_waker(Waker::noop()); loop { if let Poll::Ready(val) = future.as_mut().poll(&mut context) { diff --git a/tests/rustdoc-gui/docblock-details.goml b/tests/rustdoc-gui/docblock-details.goml index 8e6d2ba824f..4b8f5b54fac 100644 --- a/tests/rustdoc-gui/docblock-details.goml +++ b/tests/rustdoc-gui/docblock-details.goml @@ -6,7 +6,7 @@ reload: // We first check that the headers in the `.top-doc` doc block still have their // bottom border. -assert-text: (".top-doc .docblock > h3", "Hello") +assert-text: (".top-doc .docblock > h3", "§Hello") assert-css: ( ".top-doc .docblock > h3", {"border-bottom": "1px solid #d2d2d2"}, diff --git a/tests/rustdoc-gui/headers-color.goml b/tests/rustdoc-gui/headers-color.goml index 19185818f40..80d11c9c849 100644 --- a/tests/rustdoc-gui/headers-color.goml +++ b/tests/rustdoc-gui/headers-color.goml @@ -1,4 +1,4 @@ -// This test check for headers text and background colors for the different themes. +// This test check for headings text and background colors for the different themes. define-function: ( "check-colors", @@ -45,7 +45,7 @@ call-function: ( "color": "#c5c5c5", "code_header_color": "#e6e1cf", "focus_background_color": "rgba(255, 236, 164, 0.06)", - "headings_color": "#39afd7", + "headings_color": "#c5c5c5", }, ) call-function: ( @@ -55,7 +55,7 @@ call-function: ( "color": "#ddd", "code_header_color": "#ddd", "focus_background_color": "#494a3d", - "headings_color": "#d2991d", + "headings_color": "#ddd", }, ) call-function: ( @@ -65,6 +65,6 @@ call-function: ( "color": "black", "code_header_color": "black", "focus_background_color": "#fdffd3", - "headings_color": "#3873ad", + "headings_color": "black", }, ) diff --git a/tests/rustdoc-gui/headings-anchor.goml b/tests/rustdoc-gui/headings-anchor.goml new file mode 100644 index 00000000000..f568caa3b07 --- /dev/null +++ b/tests/rustdoc-gui/headings-anchor.goml @@ -0,0 +1,32 @@ +// Test to ensure that the headings anchor behave as expected. +go-to: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" +show-text: true + +define-function: ( + "check-heading-anchor", + (heading_id), + block { + // The anchor should not be displayed by default. + assert-css: ("#" + |heading_id| + " .doc-anchor", { "display": "none" }) + // We ensure that hovering the heading makes the anchor visible. + move-cursor-to: "#" + |heading_id| + assert-css: ("#" + |heading_id| + ":hover .doc-anchor", { "display": "block" }) + // We then ensure that moving from the heading to the anchor doesn't make the anchor + // disappear. + move-cursor-to: "#" + |heading_id| + " .doc-anchor" + assert-css: ("#" + |heading_id| + " .doc-anchor:hover", { + "display": "block", + // We also ensure that there is no underline decoration. + "text-decoration-line": "none", + }) + } +) + +move-cursor-to: "#top-doc-prose-title" +// If the top documentation block first element is a heading, we should never display its anchor +// to prevent it from overlapping with the `[-]` element. +assert-css: ("#top-doc-prose-title:hover .doc-anchor", { "display": "none" }) + +call-function: ("check-heading-anchor", ("top-doc-prose-sub-heading")) +call-function: ("check-heading-anchor", ("top-doc-prose-sub-sub-heading")) +call-function: ("check-heading-anchor", ("you-know-the-drill")) diff --git a/tests/rustdoc/disambiguate-anchors-header-29449.rs b/tests/rustdoc/disambiguate-anchors-header-29449.rs index 38a4954fc13..1388af7df4b 100644 --- a/tests/rustdoc/disambiguate-anchors-header-29449.rs +++ b/tests/rustdoc/disambiguate-anchors-header-29449.rs @@ -5,18 +5,23 @@ pub struct Foo; impl Foo { - // @has - '//*[@id="examples"]//a' 'Examples' - // @has - '//*[@id="panics"]//a' 'Panics' + // @has - '//*[@id="examples"]' 'Examples' + // @has - '//*[@id="examples"]/a[@href="#examples"]' '§' + // @has - '//*[@id="panics"]' 'Panics' + // @has - '//*[@id="panics"]/a[@href="#panics"]' '§' /// # Examples /// # Panics pub fn bar() {} - // @has - '//*[@id="examples-1"]//a' 'Examples' + // @has - '//*[@id="examples-1"]' 'Examples' + // @has - '//*[@id="examples-1"]/a[@href="#examples-1"]' '§' /// # Examples pub fn bar_1() {} - // @has - '//*[@id="examples-2"]//a' 'Examples' - // @has - '//*[@id="panics-1"]//a' 'Panics' + // @has - '//*[@id="examples-2"]' 'Examples' + // @has - '//*[@id="examples-2"]/a[@href="#examples-2"]' '§' + // @has - '//*[@id="panics-1"]' 'Panics' + // @has - '//*[@id="panics-1"]/a[@href="#panics-1"]' '§' /// # Examples /// # Panics pub fn bar_2() {} diff --git a/tests/rustdoc/links-in-headings.rs b/tests/rustdoc/links-in-headings.rs new file mode 100644 index 00000000000..c5bee1a7975 --- /dev/null +++ b/tests/rustdoc/links-in-headings.rs @@ -0,0 +1,14 @@ +#![crate_name = "foo"] + +//! # Heading with [a link](https://a.com) inside +//! +//! And even with +//! +//! ## [multiple](https://b.com) [links](https://c.com) +//! +//! ! + +// @has 'foo/index.html' +// @has - '//h2/a[@href="https://a.com"]' 'a link' +// @has - '//h3/a[@href="https://b.com"]' 'multiple' +// @has - '//h3/a[@href="https://c.com"]' 'links' diff --git a/tests/rustdoc/remove-url-from-headings.rs b/tests/rustdoc/remove-url-from-headings.rs index 599c429a6e1..8f477028619 100644 --- a/tests/rustdoc/remove-url-from-headings.rs +++ b/tests/rustdoc/remove-url-from-headings.rs @@ -1,9 +1,12 @@ +// It actually checks that the link is kept in the headings as expected now. + #![crate_name = "foo"] // @has foo/fn.foo.html -// @!has - '//a[@href="http://a.a"]' '' -// @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere' -// @has - '//a[@href="#another-one-urg"]' 'Another one urg' +// @has - '//a[@href="http://a.a"]' 'stuff' +// @has - '//*[@id="implementing-stuff-somewhere"]' 'Implementing stuff somewhere' +// @has - '//a[@href="http://b.b"]' 'one' +// @has - '//*[@id="another-one-urg"]' 'Another one urg' /// fooo /// @@ -13,5 +16,5 @@ /// /// # Another [one][two] urg /// -/// [two]: http://a.a +/// [two]: http://b.b pub fn foo() {} diff --git a/tests/rustdoc/short-docblock.rs b/tests/rustdoc/short-docblock.rs index 791d3547c9f..151a42a9c9e 100644 --- a/tests/rustdoc/short-docblock.rs +++ b/tests/rustdoc/short-docblock.rs @@ -2,8 +2,9 @@ // @has foo/index.html '//*[@class="desc docblock-short"]' 'fooo' // @!has foo/index.html '//*[@class="desc docblock-short"]/h1' 'fooo' -// @has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' 'fooo' +// @has foo/fn.foo.html '//h2[@id="fooo"]' 'fooo' +// @has foo/fn.foo.html '//h2[@id="fooo"]/a[@href="#fooo"]' '§' /// # fooo /// /// foo @@ -11,8 +12,9 @@ pub fn foo() {} // @has foo/index.html '//*[@class="desc docblock-short"]' 'mooood' // @!has foo/index.html '//*[@class="desc docblock-short"]/h2' 'mooood' -// @has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' 'mooood' +// @has foo/foo/index.html '//h3[@id="mooood"]' 'mooood' +// @has foo/foo/index.html '//h3[@id="mooood"]/a[@href="#mooood"]' '§' /// ## mooood /// /// foo mod diff --git a/tests/ui/async-await/for-await-passthrough.rs b/tests/ui/async-await/for-await-passthrough.rs index 7fa133aaedc..b1a382958a1 100644 --- a/tests/ui/async-await/for-await-passthrough.rs +++ b/tests/ui/async-await/for-await-passthrough.rs @@ -25,8 +25,7 @@ async fn real_main() { fn main() { let future = real_main(); - let waker = std::task::Waker::noop(); - let mut cx = &mut core::task::Context::from_waker(&waker); + let mut cx = &mut core::task::Context::from_waker(std::task::Waker::noop()); let mut future = core::pin::pin!(future); while let core::task::Poll::Pending = future.as_mut().poll(&mut cx) {} } diff --git a/tests/ui/async-await/for-await.rs b/tests/ui/async-await/for-await.rs index 6345ceb0c27..00dbdfb2389 100644 --- a/tests/ui/async-await/for-await.rs +++ b/tests/ui/async-await/for-await.rs @@ -17,8 +17,7 @@ async fn real_main() { fn main() { let future = real_main(); - let waker = std::task::Waker::noop(); - let mut cx = &mut core::task::Context::from_waker(&waker); + let mut cx = &mut core::task::Context::from_waker(std::task::Waker::noop()); let mut future = core::pin::pin!(future); while let core::task::Poll::Pending = future.as_mut().poll(&mut cx) {} } diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs index 491dfcc6ae0..8c01f1bddef 100644 --- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs +++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs @@ -40,8 +40,7 @@ fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs index f21abf012ba..e2fd9f9dfea 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs @@ -43,8 +43,7 @@ fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr index 0560cd9c5fe..b7336485eb8 100644 --- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr +++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr @@ -21,7 +21,7 @@ LL | default async fn foo(_: T) -> &'static str { = note: specialization behaves in inconsistent and surprising ways with async functions in traits, and for now is disallowed error[E0599]: no method named `poll` found for struct `Pin<&mut impl Future<Output = ()>>` in the current scope - --> $DIR/dont-project-to-specializable-projection.rs:50:28 + --> $DIR/dont-project-to-specializable-projection.rs:49:28 | LL | match fut.as_mut().poll(ctx) { | ^^^^ method not found in `Pin<&mut impl Future<Output = ()>>` diff --git a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs index aac74d3eacb..80c0b69a6f7 100644 --- a/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs +++ b/tests/ui/coroutine/async-gen-yield-ty-is-unit.rs @@ -11,7 +11,6 @@ async gen fn gen_fn() -> &'static str { pub fn main() { let async_iterator = pin!(gen_fn()); - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); async_iterator.poll_next(ctx); } diff --git a/tests/ui/coroutine/async_gen_fn_iter.rs b/tests/ui/coroutine/async_gen_fn_iter.rs index ec6464d0048..604156b4d37 100644 --- a/tests/ui/coroutine/async_gen_fn_iter.rs +++ b/tests/ui/coroutine/async_gen_fn_iter.rs @@ -74,8 +74,7 @@ fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/dyn-star/dispatch-on-pin-mut.rs b/tests/ui/dyn-star/dispatch-on-pin-mut.rs index c4ae279e6c1..151aa9092fb 100644 --- a/tests/ui/dyn-star/dispatch-on-pin-mut.rs +++ b/tests/ui/dyn-star/dispatch-on-pin-mut.rs @@ -19,15 +19,14 @@ async fn async_main() { // ------------------------------------------------------------------------- // // Implementation Details Below... -use std::task::*; use std::pin::pin; +use std::task::*; fn main() { let mut fut = pin!(async_main()); // Poll loop, just to test the future... - let waker = Waker::noop(); - let ctx = &mut Context::from_waker(&waker); + let ctx = &mut Context::from_waker(Waker::noop()); loop { match fut.as_mut().poll(ctx) { diff --git a/tests/ui/pattern/never_patterns.rs b/tests/ui/pattern/never_patterns.rs deleted file mode 100644 index 8f44f8a6559..00000000000 --- a/tests/ui/pattern/never_patterns.rs +++ /dev/null @@ -1,73 +0,0 @@ -#![feature(never_patterns)] -#![allow(incomplete_features)] - -enum Void {} - -fn main() {} - -// The classic use for empty types. -fn safe_unwrap_result<T>(res: Result<T, Void>) { - let Ok(_x) = res; //~ ERROR refutable pattern in local binding - let (Ok(_x) | Err(!)) = &res; - let (Ok(_x) | Err(&!)) = res.as_ref(); -} - -// Check we only accept `!` where we want to. -fn never_pattern_location(void: Void) { - // FIXME(never_patterns): Don't accept on a non-empty type. - match Some(0) { - None => {} - Some(!), - } - // FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches. - match () { - () => {} - !, - } - // FIXME(never_patterns): Don't accept even on an empty branch. - match None::<Void> { - None => {} - !, - } - // FIXME(never_patterns): Let alone if the emptiness is behind a reference. - match None::<&Void> { - None => {} - !, - } - // Participate in match ergonomics. - match &void { - ! - } - match &&void { - ! - } - match &&void { - &! - } - match &None::<Void> { - None => {} - Some(!) - } - match None::<&Void> { - None => {} - Some(!), - } - // Accept on a composite empty type. - match None::<&(u32, Void)> { - None => {} - Some(&!), - } - // Accept on an simple empty type. - match None::<Void> { - None => {} - Some(!), - } - match None::<&Void> { - None => {} - Some(&!), - } - match None::<&(u32, Void)> { - None => {} - Some(&(_, !)), - } -} diff --git a/tests/ui/pattern/never_patterns.stderr b/tests/ui/pattern/never_patterns.stderr deleted file mode 100644 index 20eeb01cf71..00000000000 --- a/tests/ui/pattern/never_patterns.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0005]: refutable pattern in local binding - --> $DIR/never_patterns.rs:10:9 - | -LL | let Ok(_x) = res; - | ^^^^^^ pattern `Err(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html - = note: the matched value is of type `Result<T, Void>` -help: you might want to use `let else` to handle the variant that isn't matched - | -LL | let Ok(_x) = res else { todo!() }; - | ++++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0005`. diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr new file mode 100644 index 00000000000..013a8b53a55 --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.fail.stderr @@ -0,0 +1,66 @@ +error: mismatched types + --> $DIR/typeck.rs:25:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `()` + +error: mismatched types + --> $DIR/typeck.rs:29:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `(i32, bool)` + +error: mismatched types + --> $DIR/typeck.rs:33:13 + | +LL | (_, !), + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `bool` + +error: mismatched types + --> $DIR/typeck.rs:38:14 + | +LL | Some(!), + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `i32` + +error: mismatched types + --> $DIR/typeck.rs:45:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `()` + +error: mismatched types + --> $DIR/typeck.rs:52:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `Option<Void>` + +error: mismatched types + --> $DIR/typeck.rs:57:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `[Void]` + +error: mismatched types + --> $DIR/typeck.rs:63:9 + | +LL | !, + | ^ a never pattern must be used on an uninhabited type + | + = note: the matched value is of type `Option<&Void>` + +error: aborting due to 8 previous errors + diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs new file mode 100644 index 00000000000..31a23fa002c --- /dev/null +++ b/tests/ui/rfcs/rfc-0000-never_patterns/typeck.rs @@ -0,0 +1,125 @@ +// revisions: pass fail +//[pass] check-pass +//[fail] check-fail +#![feature(never_patterns)] +#![feature(exhaustive_patterns)] +#![allow(incomplete_features)] + +#[derive(Copy, Clone)] +enum Void {} + +fn main() {} + +// The classic use for empty types. +fn safe_unwrap_result<T: Copy>(res: Result<T, Void>) { + let Ok(_x) = res; + let (Ok(_x) | Err(!)) = &res; + let (Ok(_x) | Err(!)) = res.as_ref(); +} + +// Check we only accept `!` where we want to. +#[cfg(fail)] +fn never_pattern_typeck_fail(void: Void) { + // Don't accept on a non-empty type. + match () { + !, + //[fail]~^ ERROR: mismatched types + } + match (0, false) { + !, + //[fail]~^ ERROR: mismatched types + } + match (0, false) { + (_, !), + //[fail]~^ ERROR: mismatched types + } + match Some(0) { + None => {} + Some(!), + //[fail]~^ ERROR: mismatched types + } + + // Don't accept on an arbitrary type, even if there are no more branches. + match () { + () => {} + !, + //[fail]~^ ERROR: mismatched types + } + + // Don't accept even on an empty branch. + match None::<Void> { + None => {} + !, + //[fail]~^ ERROR: mismatched types + } + match (&[] as &[Void]) { + [] => {} + !, + //[fail]~^ ERROR: mismatched types + } + // Let alone if the emptiness is behind a reference. + match None::<&Void> { + None => {} + !, + //[fail]~^ ERROR: mismatched types + } +} + +#[cfg(pass)] +fn never_pattern_typeck_pass(void: Void) { + // Participate in match ergonomics. + match &void { + !, + } + match &&void { + !, + } + match &&void { + &!, + } + match &None::<Void> { + None => {} + Some(!), + } + match None::<&Void> { + None => {} + Some(!), + } + + // Accept on a directly empty type. + match void { + !, + } + match &void { + &!, + } + match None::<Void> { + None => {} + Some(!), + } + match None::<&Void> { + None => {} + Some(&!), + } + match None::<&(u32, Void)> { + None => {} + Some(&(_, !)), + } + match (&[] as &[Void]) { + [] => {} + [!], + } + // Accept on a composite empty type. + match None::<&(u32, Void)> { + None => {} + Some(&!), + } + match None::<&(u32, Void)> { + None => {} + Some(!), + } + match None::<&Result<Void, Void>> { + None => {} + Some(!), + } +} diff --git a/tests/ui/suggestions/suggest-slice-swap.fixed b/tests/ui/suggestions/suggest-slice-swap.fixed new file mode 100644 index 00000000000..05b7ec26379 --- /dev/null +++ b/tests/ui/suggestions/suggest-slice-swap.fixed @@ -0,0 +1,9 @@ +// run-rustfix +#![allow(dead_code)] + +fn swap(arr: &mut [u32; 2]) { + arr.swap(1, 0); + //~^ ERROR cannot borrow `arr[_]` as mutable more than once at a time +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-slice-swap.rs b/tests/ui/suggestions/suggest-slice-swap.rs new file mode 100644 index 00000000000..9f3659aac16 --- /dev/null +++ b/tests/ui/suggestions/suggest-slice-swap.rs @@ -0,0 +1,9 @@ +// run-rustfix +#![allow(dead_code)] + +fn swap(arr: &mut [u32; 2]) { + std::mem::swap(&mut arr[0], &mut arr[1]); + //~^ ERROR cannot borrow `arr[_]` as mutable more than once at a time +} + +fn main() {} diff --git a/tests/ui/suggestions/suggest-slice-swap.stderr b/tests/ui/suggestions/suggest-slice-swap.stderr new file mode 100644 index 00000000000..2840fc0a761 --- /dev/null +++ b/tests/ui/suggestions/suggest-slice-swap.stderr @@ -0,0 +1,17 @@ +error[E0499]: cannot borrow `arr[_]` as mutable more than once at a time + --> $DIR/suggest-slice-swap.rs:5:33 + | +LL | std::mem::swap(&mut arr[0], &mut arr[1]); + | -------------- ----------- ^^^^^^^^^^^ second mutable borrow occurs here + | | | + | | first mutable borrow occurs here + | first borrow later used by call + | +help: use `.swap()` to swap elements at the specified indices instead + | +LL | arr.swap(1, 0); + | ~~~~~~~~~~~~~~ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0499`. |
