From 1990f1560801ca3f9e6a3286e58204aa329ee037 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 30 Oct 2024 01:10:33 +0000 Subject: [PATCH 01/54] Reject raw lifetime followed by \' as well --- compiler/rustc_lexer/src/lib.rs | 12 +++++++++++- .../ui/lifetimes/raw/immediately-followed-by-lt.rs | 14 ++++++++++++++ .../raw/immediately-followed-by-lt.stderr | 13 +++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lifetimes/raw/immediately-followed-by-lt.rs create mode 100644 tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index b0ab50dd773..f9f2a14dbd2 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -715,7 +715,17 @@ fn lifetime_or_char(&mut self) -> TokenKind { self.bump(); self.bump(); self.eat_while(is_id_continue); - return RawLifetime; + match self.first() { + '\'' => { + // Check if after skipping literal contents we've met a closing + // single quote (which means that user attempted to create a + // string with single quotes). + self.bump(); + let kind = Char { terminated: true }; + return Literal { kind, suffix_start: self.pos_within_token() }; + } + _ => return RawLifetime, + } } // Either a lifetime or a character literal with diff --git a/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs b/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs new file mode 100644 index 00000000000..fe2b6de7bb3 --- /dev/null +++ b/tests/ui/lifetimes/raw/immediately-followed-by-lt.rs @@ -0,0 +1,14 @@ +//@ edition: 2021 + +// Make sure we reject the case where a raw lifetime is immediately followed by another +// lifetime. This reserves a modest amount of space for changing lexing to, for example, +// delay rejection of overlong char literals like `'r#long'id`. + +macro_rules! w { + ($($tt:tt)*) => {} +} + +w!('r#long'id); +//~^ ERROR character literal may only contain one codepoint + +fn main() {} diff --git a/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr b/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr new file mode 100644 index 00000000000..1caeec84b22 --- /dev/null +++ b/tests/ui/lifetimes/raw/immediately-followed-by-lt.stderr @@ -0,0 +1,13 @@ +error: character literal may only contain one codepoint + --> $DIR/immediately-followed-by-lt.rs:11:4 + | +LL | w!('r#long'id); + | ^^^^^^^^ + | +help: if you meant to write a string literal, use double quotes + | +LL | w!("r#long"id); + | ~ ~ + +error: aborting due to 1 previous error + From 9785c7cf94f5e30742f886764f2d25b6a4da66e8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 30 Oct 2024 14:45:17 +0000 Subject: [PATCH 02/54] Enforce that raw lifetime identifiers must be valid raw identifiers --- compiler/rustc_parse/messages.ftl | 2 ++ compiler/rustc_parse/src/errors.rs | 8 +++++ compiler/rustc_parse/src/lexer/mod.rs | 14 +++++--- .../ui/lifetimes/raw/raw-lt-invalid-raw-id.rs | 20 ++++++++++++ .../raw/raw-lt-invalid-raw-id.stderr | 32 +++++++++++++++++++ 5 files changed, 72 insertions(+), 4 deletions(-) create mode 100644 tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs create mode 100644 tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index 1af7fb9b86a..ef259703f0c 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -77,6 +77,8 @@ parse_box_syntax_removed_suggestion = use `Box::new()` instead parse_cannot_be_raw_ident = `{$ident}` cannot be a raw identifier +parse_cannot_be_raw_lifetime = `{$ident}` cannot be a raw lifetime + parse_catch_after_try = keyword `catch` cannot follow a `try` block .help = try using `match` on the result of the `try` block instead diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index fdd500e90f8..7ec4ad6dc35 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2018,6 +2018,14 @@ pub(crate) struct CannotBeRawIdent { pub ident: Symbol, } +#[derive(Diagnostic)] +#[diag(parse_cannot_be_raw_lifetime)] +pub(crate) struct CannotBeRawLifetime { + #[primary_span] + pub span: Span, + pub ident: Symbol, +} + #[derive(Diagnostic)] #[diag(parse_keyword_lifetime)] pub(crate) struct KeywordLifetime { diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index d627ef3d2cb..226de65445c 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -294,15 +294,21 @@ fn next_token(&mut self) -> (Token, bool) { let prefix_span = self.mk_sp(start, ident_start); if prefix_span.at_least_rust_2021() { - let lifetime_name_without_tick = self.str_from(ident_start); + let span = self.mk_sp(start, self.pos); + + let lifetime_name_without_tick = Symbol::intern(&self.str_from(ident_start)); + if !lifetime_name_without_tick.can_be_raw() { + self.dcx().emit_err(errors::CannotBeRawLifetime { span, ident: lifetime_name_without_tick }); + } + // Put the `'` back onto the lifetime name. - let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.len() + 1); + let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.as_str().len() + 1); lifetime_name.push('\''); - lifetime_name += lifetime_name_without_tick; + lifetime_name += lifetime_name_without_tick.as_str(); let sym = Symbol::intern(&lifetime_name); // Make sure we mark this as a raw identifier. - self.psess.raw_identifier_spans.push(self.mk_sp(start, self.pos)); + self.psess.raw_identifier_spans.push(span); token::Lifetime(sym, IdentIsRaw::Yes) } else { diff --git a/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs new file mode 100644 index 00000000000..882fad925f3 --- /dev/null +++ b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.rs @@ -0,0 +1,20 @@ +//@ edition: 2021 + +// Reject raw lifetimes with identifier parts that wouldn't be valid raw identifiers. + +macro_rules! w { + ($tt:tt) => {}; +} + +w!('r#_); +//~^ ERROR `_` cannot be a raw lifetime +w!('r#self); +//~^ ERROR `self` cannot be a raw lifetime +w!('r#super); +//~^ ERROR `super` cannot be a raw lifetime +w!('r#Self); +//~^ ERROR `Self` cannot be a raw lifetime +w!('r#crate); +//~^ ERROR `crate` cannot be a raw lifetime + +fn main() {} diff --git a/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr new file mode 100644 index 00000000000..4cbb89b7a55 --- /dev/null +++ b/tests/ui/lifetimes/raw/raw-lt-invalid-raw-id.stderr @@ -0,0 +1,32 @@ +error: `_` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:9:4 + | +LL | w!('r#_); + | ^^^^ + +error: `self` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:11:4 + | +LL | w!('r#self); + | ^^^^^^^ + +error: `super` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:13:4 + | +LL | w!('r#super); + | ^^^^^^^^ + +error: `Self` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:15:4 + | +LL | w!('r#Self); + | ^^^^^^^ + +error: `crate` cannot be a raw lifetime + --> $DIR/raw-lt-invalid-raw-id.rs:17:4 + | +LL | w!('r#crate); + | ^^^^^^^^ + +error: aborting due to 5 previous errors + From 322d392d9086abf7c08c85c726834c1503e539a9 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Fri, 1 Nov 2024 17:07:18 +0100 Subject: [PATCH 03/54] Move versioned LLVM target creation to rustc_codegen_ssa The OS version depends on the deployment target environment variables, the access of which we want to move to later in the compilation pipeline that has access to more information, for example `env_depinfo`. --- src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 602b1b98200..fc3bd0abd78 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,7 @@ use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::settings::{self, Configurable}; use rustc_codegen_ssa::CodegenResults; +use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::ErrorGuaranteed; @@ -260,7 +261,9 @@ fn link( } fn target_triple(sess: &Session) -> target_lexicon::Triple { - match sess.target.llvm_target.parse() { + // FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS. + // See + match versioned_llvm_target(sess).parse() { Ok(triple) => triple, Err(err) => sess.dcx().fatal(format!("target not recognized: {}", err)), } From e2a5108657befd0f680242dec5852caa98cb8ae8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 2 Nov 2024 14:53:30 +0000 Subject: [PATCH 04/54] Merge commit '5b1246bb4bed72fd0bb8fa497d8e5ed2c7f3515c' into sync_cg_clif-2024-11-02 --- Cargo.lock | 136 ++++++++---------- Cargo.toml | 14 +- build_system/build_sysroot.rs | 9 -- build_system/prepare.rs | 33 +++-- .../0002-abi-cafe-Disable-broken-tests.patch | 32 ++--- ...oretests-Disable-not-compiling-tests.patch | 4 +- ...7-coretests-128bit-atomic-operations.patch | 7 +- ...coretests-Disable-long-running-tests.patch | 22 +-- rust-toolchain | 2 +- scripts/test_rustc_tests.sh | 94 ++---------- src/abi/mod.rs | 9 +- src/base.rs | 22 +-- src/debuginfo/line_info.rs | 7 +- src/debuginfo/mod.rs | 3 +- src/debuginfo/unwind.rs | 4 +- src/inline_asm.rs | 4 +- src/intrinsics/mod.rs | 5 +- src/intrinsics/simd.rs | 6 +- src/lib.rs | 7 +- src/pretty_clif.rs | 13 +- src/trap.rs | 2 +- 21 files changed, 168 insertions(+), 267 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c2ca95b075..e4f77472802 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "ahash" @@ -46,24 +46,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b80c3a50b9c4c7e5b5f73c0ed746687774fc9e36ef652b110da8daebf0c6e0e6" +checksum = "8ea5e7afe85cadb55c4c1176268a2ac046fdff8dfaeca39e18581b9dc319ca9e" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38778758c2ca918b05acb2199134e0c561fb577c50574259b26190b6c2d95ded" +checksum = "8ab25ef3be935a80680e393183e1f94ef507e93a24a8369494d2c6818aedb3e3" [[package]] name = "cranelift-codegen" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58258667ad10e468bfc13a8d620f50dfcd4bb35d668123e97defa2549b9ad397" +checksum = "900a19b84545924f1851cbfe386962edfc4ecbc3366a254825cf1ecbcda8ba08" dependencies = [ "bumpalo", "cranelift-bforest", @@ -74,7 +74,7 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown 0.14.5", + "hashbrown", "log", "regalloc2", "rustc-hash", @@ -84,42 +84,42 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043f0b702e529dcb07ff92bd7d40e7d5317b5493595172c5eb0983343751ee06" +checksum = "08c73b2395ffe9e7b4fdf7e2ebc052e7e27af13f68a964985346be4da477a5fc" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7763578888ab53eca5ce7da141953f828e82c2bfadcffc106d10d1866094ffbb" +checksum = "7d9ed0854e96a4ff0879bff39d078de8dea7f002721c9494c1fdb4e1baa86ccc" [[package]] name = "cranelift-control" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32db15f08c05df570f11e8ab33cb1ec449a64b37c8a3498377b77650bef33d8b" +checksum = "b4aca921dd422e781409de0129c255768fec5dec1dae83239b497fb9138abb89" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5289cdb399381a27e7bbfa1b42185916007c3d49aeef70b1d01cb4caa8010130" +checksum = "e2d770e6605eccee15b49decdd82cd26f2b6404767802471459ea49c57379a98" dependencies = [ "cranelift-bitset", ] [[package]] name = "cranelift-frontend" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31ba8ab24eb9470477e98ddfa3c799a649ac5a0d9a2042868c4c952133c234e8" +checksum = "29268711cb889cb39215b10faf88b9087d4c9e1d2633581e4f722a2bf4bb4ef9" dependencies = [ "cranelift-codegen", "log", @@ -129,15 +129,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b72a3c5c166a70426dcb209bdd0bb71a787c1ea76023dc0974fbabca770e8f9" +checksum = "dc65156f010aed1985767ad1bff0eb8d186743b7b03e23d0c17604a253e3f356" [[package]] name = "cranelift-jit" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df32578a47582e49b4fc1f9a5786839d9be1fedaa9f00bea7612c54425663c6b" +checksum = "40ba6b46367a4f466cfb1abe32793fa1a0f96d862251491b01a44726b8ed9445" dependencies = [ "anyhow", "cranelift-codegen", @@ -150,14 +150,14 @@ dependencies = [ "region", "target-lexicon", "wasmtime-jit-icache-coherence", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "cranelift-module" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96094a758cdb543c9143f70817cd31069fecd49f50981a0fac06820ac011dc2f" +checksum = "007607022a4883ebdffc46c0925e2e10babf2a565ae78518034ade722aa825d2" dependencies = [ "anyhow", "cranelift-codegen", @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a42424c956bbc31fc5c2706073df896156c5420ae8fa2a5d48dbc7b295d71b" +checksum = "d8bf9b361eaf5a7627647270fabf1dc910d993edbeaf272a652c107861ebe9c2" dependencies = [ "cranelift-codegen", "libc", @@ -177,9 +177,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.111.0" +version = "0.113.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cf5e2484ab47fe38a3150747cdd2016535f13542a925acca152b63383a6591b" +checksum = "30ca5c38fa00c0cd943035391bdcc84ed00748f17c66c682e410f5a62f234d44" dependencies = [ "anyhow", "cranelift-codegen", @@ -213,24 +213,15 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" dependencies = [ "fallible-iterator", "indexmap", "stable_deref_trait", ] -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.14.5" @@ -247,7 +238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -273,10 +264,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] -name = "mach" -version = "0.3.2" +name = "mach2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" dependencies = [ "libc", ] @@ -294,7 +285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "crc32fast", - "hashbrown 0.14.5", + "hashbrown", "indexmap", "memchr", ] @@ -325,11 +316,11 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" +checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0" dependencies = [ - "hashbrown 0.13.2", + "hashbrown", "log", "rustc-hash", "slice-group-by", @@ -338,21 +329,21 @@ dependencies = [ [[package]] name = "region" -version = "2.2.0" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877e54ea2adcd70d80e9179344c97f93ef0dffd6b03e1f4529e6e83ab2fa9ae0" +checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7" dependencies = [ "bitflags", "libc", - "mach", - "winapi", + "mach2", + "windows-sys 0.52.0", ] [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustc_codegen_cranelift" @@ -421,38 +412,16 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "24.0.0" +version = "26.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15de8429db996f0d17a4163a35eccc3f874cbfb50f29c379951ea1bbb39452e" +checksum = "6e458e6a1a010a53f86ac8d75837c0c6b2ce3e54b7503b2f1dc5629a4a541f5a" dependencies = [ "anyhow", "cfg-if", "libc", - "windows-sys", + "windows-sys 0.59.0", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.52.0" @@ -462,6 +431,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 6594ffb5d66..f352ef72cb0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,14 +8,14 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.111.0", default-features = false, features = ["std", "unwind", "all-arch"] } -cranelift-frontend = { version = "0.111.0" } -cranelift-module = { version = "0.111.0" } -cranelift-native = { version = "0.111.0" } -cranelift-jit = { version = "0.111.0", optional = true } -cranelift-object = { version = "0.111.0" } +cranelift-codegen = { version = "0.113.0", default-features = false, features = ["std", "unwind", "all-native-arch"] } +cranelift-frontend = { version = "0.113.0" } +cranelift-module = { version = "0.113.0" } +cranelift-native = { version = "0.113.0" } +cranelift-jit = { version = "0.113.0", optional = true } +cranelift-object = { version = "0.113.0" } target-lexicon = "0.12.0" -gimli = { version = "0.29", default-features = false, features = ["write"] } +gimli = { version = "0.31", default-features = false, features = ["write"] } object = { version = "0.36", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 82558999afa..f1f4489bcbc 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -102,15 +102,6 @@ pub(crate) fn build_sysroot( .install_into_sysroot(&dist_dir); } - // Copy std for the host to the lib dir. This is necessary for the jit mode to find - // libstd. - for lib in host.libs { - let filename = lib.file_name().unwrap().to_str().unwrap(); - if filename.contains("std-") && !filename.contains(".rlib") { - try_hard_link(&lib, dist_dir.join("lib").join(lib.file_name().unwrap())); - } - } - let mut target_compiler = { let rustc_clif = dist_dir.join(wrapper_base_name.replace("____", "rustc-clif")); let rustdoc_clif = dist_dir.join(wrapper_base_name.replace("____", "rustdoc-clif")); diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 30bd7ae26a1..c6f979f0278 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -1,8 +1,8 @@ use std::ffi::OsStr; -use std::fs; use std::hash::{Hash, Hasher}; use std::path::{Path, PathBuf}; use std::process::Command; +use std::{fs, io}; use crate::path::{Dirs, RelPath}; use crate::utils::{copy_dir_recursively, ensure_empty_dir, spawn_and_wait}; @@ -89,6 +89,19 @@ pub(crate) const fn source_dir(&self) -> RelPath { } } + fn verify_checksum(&self, dirs: &Dirs) { + let download_dir = self.download_dir(dirs); + let actual_hash = format!("{:016x}", hash_dir(&download_dir)); + if actual_hash != self.content_hash { + eprintln!( + "Mismatched content hash for {download_dir}: {actual_hash} != {content_hash}. Please run ./y.sh prepare again.", + download_dir = download_dir.display(), + content_hash = self.content_hash, + ); + std::process::exit(1); + } + } + pub(crate) fn fetch(&self, dirs: &Dirs) { let download_dir = self.download_dir(dirs); @@ -126,18 +139,11 @@ pub(crate) fn fetch(&self, dirs: &Dirs) { assert!(target_lockfile.exists()); } - let actual_hash = format!("{:016x}", hash_dir(&download_dir)); - if actual_hash != self.content_hash { - eprintln!( - "Download of {download_dir} failed with mismatched content hash: {actual_hash} != {content_hash}", - download_dir = download_dir.display(), - content_hash = self.content_hash, - ); - std::process::exit(1); - } + self.verify_checksum(dirs); } pub(crate) fn patch(&self, dirs: &Dirs) { + self.verify_checksum(dirs); apply_patches( dirs, self.patch_name, @@ -149,6 +155,13 @@ pub(crate) fn patch(&self, dirs: &Dirs) { fn clone_repo(download_dir: &Path, repo: &str, rev: &str) { eprintln!("[CLONE] {}", repo); + + match fs::remove_dir_all(download_dir) { + Ok(()) => {} + Err(err) if err.kind() == io::ErrorKind::NotFound => {} + Err(err) => panic!("Failed to remove {path}: {err}", path = download_dir.display()), + } + // Ignore exit code as the repo may already have been checked out git_command(None, "clone").arg(repo).arg(download_dir).spawn().unwrap().wait().unwrap(); diff --git a/patches/0002-abi-cafe-Disable-broken-tests.patch b/patches/0002-abi-cafe-Disable-broken-tests.patch index 8a2565f1668..01b6a990b72 100644 --- a/patches/0002-abi-cafe-Disable-broken-tests.patch +++ b/patches/0002-abi-cafe-Disable-broken-tests.patch @@ -7,11 +7,23 @@ Subject: [PATCH] Disable broken tests src/report.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) +diff --git a/src/toolchains/rust.rs b/src/toolchains/rust.rs +index 0c50f7a..bfde2b1 100644 +--- a/src/toolchains/rust.rs ++++ b/src/toolchains/rust.rs +@@ -83,6 +83,7 @@ impl Toolchain for RustcToolchain { + .arg(out_dir) + .arg("--target") + .arg(built_info::TARGET) ++ .arg("-g") + .arg(format!("-Cmetadata={lib_name}")) + .arg(src_path); + if let Some(codegen_backend) = &self.codegen_backend { diff --git a/src/report.rs b/src/report.rs index 958ab43..dcf1044 100644 --- a/src/report.rs +++ b/src/report.rs -@@ -48,6 +48,58 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn Toolchain, callee: &dyn Toolc +@@ -48,6 +48,40 @@ pub fn get_test_rules(test: &TestKey, caller: &dyn Toolchain, callee: &dyn Toolc // // THIS AREA RESERVED FOR VENDORS TO APPLY PATCHES @@ -19,10 +31,6 @@ index 958ab43..dcf1044 100644 + if test.test == "F32Array" && test.options.convention == CallingConvention::C { + result.check = Busted(Check); + } -+ -+ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust && test.options.repr == LangRepr::C { -+ result.check = Busted(Check); -+ } + } + + if cfg!(all(target_arch = "aarch64", target_os = "macos")) { @@ -39,21 +47,7 @@ index 958ab43..dcf1044 100644 + } + } + -+ if cfg!(all(target_arch = "x86_64", unix)) { -+ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust && test.options.repr == LangRepr::Rust { -+ result.check = Busted(Run); -+ } -+ } -+ + if cfg!(all(target_arch = "x86_64", windows)) { -+ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust { -+ result.check = Busted(Check); -+ } -+ -+ if test.test == "OptionU128" && test.options.convention == CallingConvention::Rust && (test.caller == "rustc" || test.options.repr == LangRepr::Rust) { -+ result.check = Busted(Run); -+ } -+ + if test.test == "simple" && test.options.convention == CallingConvention::Rust { + result.check = Busted(Check); + } diff --git a/patches/0022-coretests-Disable-not-compiling-tests.patch b/patches/0022-coretests-Disable-not-compiling-tests.patch index 5117b04fd34..6ed22c5a18e 100644 --- a/patches/0022-coretests-Disable-not-compiling-tests.patch +++ b/patches/0022-coretests-Disable-not-compiling-tests.patch @@ -38,7 +38,7 @@ index 42a26ae..5ac1042 100644 @@ -1,3 +1,4 @@ +#![cfg(test)] // tidy-alphabetical-start - #![cfg_attr(bootstrap, feature(const_mut_refs))] - #![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] + #![cfg_attr(bootstrap, feature(strict_provenance))] + #![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] -- 2.21.0 (Apple Git-122) diff --git a/patches/0027-coretests-128bit-atomic-operations.patch b/patches/0027-coretests-128bit-atomic-operations.patch index efd721d9df8..50a42aea322 100644 --- a/patches/0027-coretests-128bit-atomic-operations.patch +++ b/patches/0027-coretests-128bit-atomic-operations.patch @@ -14,13 +14,14 @@ diff --git a/lib.rs b/lib.rs index 1e336bf..35e6f54 100644 --- a/lib.rs +++ b/lib.rs -@@ -1,6 +1,5 @@ - #![cfg(test)] +@@ -2,7 +2,6 @@ // tidy-alphabetical-start - #![cfg_attr(bootstrap, feature(const_mut_refs))] + #![cfg_attr(bootstrap, feature(strict_provenance))] + #![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] #![cfg_attr(test, feature(cfg_match))] #![feature(alloc_layout_extra)] + #![feature(array_chunks)] diff --git a/atomic.rs b/atomic.rs index b735957..ea728b6 100644 --- a/atomic.rs diff --git a/patches/0028-coretests-Disable-long-running-tests.patch b/patches/0028-coretests-Disable-long-running-tests.patch index d7204add7a7..b98326c54a6 100644 --- a/patches/0028-coretests-Disable-long-running-tests.patch +++ b/patches/0028-coretests-Disable-long-running-tests.patch @@ -12,7 +12,7 @@ index 8402833..84592e0 100644 --- a/slice.rs +++ b/slice.rs @@ -1809,6 +1809,7 @@ fn sort_unstable() { - assert!(v == [0xDEADBEEF]); + } } +/* @@ -43,26 +43,6 @@ index 8402833..84592e0 100644 #[test] fn test_slice_from_ptr_range() { -diff --git a/lazy.rs b/lazy.rs -index 711511e..49c8d78 100644 ---- a/lazy.rs -+++ b/lazy.rs -@@ -113,6 +113,7 @@ fn lazy_type_inference() { - let _ = LazyCell::new(|| ()); - } - -+/* - #[test] - #[should_panic = "LazyCell instance has previously been poisoned"] - fn lazy_force_mut_panic() { -@@ -123,6 +124,7 @@ fn lazy_force_mut_panic() { - .unwrap_err(); - let _ = &*lazy; - } -+*/ - - #[test] - fn lazy_force_mut() { -- 2.26.2.7.g19db9cfb68 diff --git a/rust-toolchain b/rust-toolchain index 651770be377..2558b2b9f5d 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-09-23" +channel = "nightly-2024-11-02" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" diff --git a/scripts/test_rustc_tests.sh b/scripts/test_rustc_tests.sh index 93512f82c8b..a820da286f5 100755 --- a/scripts/test_rustc_tests.sh +++ b/scripts/test_rustc_tests.sh @@ -47,9 +47,6 @@ rm tests/ui/abi/variadic-ffi.rs # requires callee side vararg support rm -r tests/run-make/c-link-to-rust-va-list-fn # requires callee side vararg support rm tests/ui/delegation/fn-header.rs -# unsized locals -rm -r tests/run-pass-valgrind/unsized-locals - # misc unimplemented things rm tests/ui/target-feature/missing-plusminus.rs # error not implemented rm -r tests/run-make/repr128-dwarf # debuginfo test @@ -148,6 +145,7 @@ rm tests/ui/intrinsics/panic-uninitialized-zeroed.rs # same rm tests/ui/process/process-panic-after-fork.rs # same cp ../dist/bin/rustdoc-clif ../dist/bin/rustdoc # some tests expect bin/rustdoc to exist +cp $(../dist/rustc-clif --print target-libdir)/libstd-*.so ../dist/lib/ # prevent $(RUSTDOC) from picking up the sysroot built by x.py. It conflicts with the one used by # rustdoc-clif @@ -180,92 +178,20 @@ index 9607ff02f96..b7d97caf9a2 100644 Self { cmd } } -diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs -index 2047345d78a..a7e9352bb1c 100644 ---- a/src/bootstrap/src/core/build_steps/test.rs -+++ b/src/bootstrap/src/core/build_steps/test.rs -@@ -1733,11 +1733,6 @@ fn run(self, builder: &Builder<'_>) { - - let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js"); - -- if mode == "run-make" { -- let cargo = builder.ensure(tool::Cargo { compiler, target: compiler.host }); -- cmd.arg("--cargo-path").arg(cargo); -- } -- - // Avoid depending on rustdoc when we don't need it. - if mode == "rustdoc" - || mode == "run-make" -diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs -index 414f9f3a7f1..5c18179b6fe 100644 ---- a/src/tools/compiletest/src/common.rs -+++ b/src/tools/compiletest/src/common.rs -@@ -183,9 +183,6 @@ pub struct Config { - /// The rustc executable. - pub rustc_path: PathBuf, - -- /// The cargo executable. -- pub cargo_path: Option, -- - /// The rustdoc executable. - pub rustdoc_path: Option, - -diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs -index 3339116d542..250b5084d13 100644 ---- a/src/tools/compiletest/src/lib.rs -+++ b/src/tools/compiletest/src/lib.rs -@@ -47,7 +47,6 @@ pub fn parse_config(args: Vec) -> Config { - opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH") - .reqopt("", "run-lib-path", "path to target shared libraries", "PATH") - .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH") -- .optopt("", "cargo-path", "path to cargo to use for compiling", "PATH") - .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH") - .optopt("", "coverage-dump-path", "path to coverage-dump to use in tests", "PATH") - .reqopt("", "python", "path to python to use for doc tests", "PATH") -@@ -261,7 +260,6 @@ fn make_absolute(path: PathBuf) -> PathBuf { - compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), - run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), - rustc_path: opt_path(matches, "rustc-path"), -- cargo_path: matches.opt_str("cargo-path").map(PathBuf::from), - rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from), - coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from), - python: matches.opt_str("python").unwrap(), -@@ -366,7 +364,6 @@ pub fn log_config(config: &Config) { - logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path)); - logv(c, format!("run_lib_path: {:?}", config.run_lib_path)); - logv(c, format!("rustc_path: {:?}", config.rustc_path.display())); -- logv(c, format!("cargo_path: {:?}", config.cargo_path)); - logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path)); - logv(c, format!("src_base: {:?}", config.src_base.display())); - logv(c, format!("build_base: {:?}", config.build_base.display())); diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs -index 75fe6a6baaf..852568ae925 100644 +index e7ae773ffa1d3..04bc2d7787da7 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs -@@ -61,10 +61,6 @@ fn run_rmake_legacy_test(&self) { - .env_remove("MFLAGS") - .env_remove("CARGO_MAKEFLAGS"); +@@ -329,7 +329,6 @@ impl TestCx<'_> { + .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy())) + .arg("--edition=2021") + .arg(&self.testpaths.file.join("rmake.rs")) +- .arg("-Cprefer-dynamic") + // Provide necessary library search paths for rustc. + .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap()); -- if let Some(ref cargo) = self.config.cargo_path { -- cmd.env("CARGO", cwd.join(cargo)); -- } -- - if let Some(ref rustdoc) = self.config.rustdoc_path { - cmd.env("RUSTDOC", cwd.join(rustdoc)); - } -@@ -413,10 +409,6 @@ fn run_rmake_v2_test(&self) { - // through a specific CI runner). - .env("LLVM_COMPONENTS", &self.config.llvm_components); - -- if let Some(ref cargo) = self.config.cargo_path { -- cmd.env("CARGO", source_root.join(cargo)); -- } -- - if let Some(ref rustdoc) = self.config.rustdoc_path { - cmd.env("RUSTDOC", source_root.join(rustdoc)); - } EOF echo "[TEST] rustc test suite" -COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 --test-args=--nocapture tests/{codegen-units,run-make,run-pass-valgrind,ui,incremental} +COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 --test-args=--nocapture tests/{codegen-units,run-make,ui,incremental} popd diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 089b09d06ae..dfca5dcbec8 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -389,7 +389,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( let callee = with_no_trimmed_paths!(fx.tcx.def_path_str(def_id)); fx.tcx.dcx().emit_err(CompilerBuiltinsCannotCall { caller, callee }); } else { - fx.bcx.ins().trap(TrapCode::User(0)); + fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return; } } @@ -562,6 +562,11 @@ enum CallTarget { adjust_call_for_c_variadic(fx, &fn_abi, source_info, func_ref, &mut call_args); } + if fx.clif_comments.enabled() { + let nop_inst = fx.bcx.ins().nop(); + with_no_trimmed_paths!(fx.add_comment(nop_inst, format!("abi: {:?}", fn_abi))); + } + match func_ref { CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args), CallTarget::Indirect(sig, func_ptr) => { @@ -574,7 +579,7 @@ enum CallTarget { let ret_block = fx.get_block(dest); fx.bcx.ins().jump(ret_block, &[]); } else { - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } fn adjust_call_for_c_variadic<'tcx>( diff --git a/src/base.rs b/src/base.rs index 99e39971b74..10d5dce9b36 100644 --- a/src/base.rs +++ b/src/base.rs @@ -103,12 +103,12 @@ pub(crate) fn codegen_fn<'tcx>( let block_map: IndexVec = (0..mir.basic_blocks.len()).map(|_| bcx.create_block()).collect(); + let fn_abi = RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()); + // Make FunctionCx let target_config = module.target_config(); let pointer_type = target_config.pointer_type(); - let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance); - - let fn_abi = RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()); + let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance, fn_abi); let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context { Some(debug_context.define_function(tcx, type_dbg, instance, fn_abi, &symbol_name, mir.span)) @@ -294,7 +294,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { if arg_uninhabited { fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]); fx.bcx.switch_to_block(fx.block_map[START_BLOCK]); - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); return; } fx.tcx @@ -311,7 +311,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { if !reachable_blocks.contains(bb) { // We want to skip this block, because it's not reachable. But we still create // the block so terminators in other blocks can reference it. - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); continue; } @@ -379,7 +379,6 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { let target = fx.get_block(*target); let failure = fx.bcx.create_block(); - fx.bcx.set_cold_block(failure); if *expected { fx.bcx.ins().brif(cond, target, &[], failure, &[]); @@ -541,10 +540,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { } TerminatorKind::UnwindResume => { // FIXME implement unwinding - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } TerminatorKind::Unreachable => { - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.set_cold_block(block); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } TerminatorKind::Yield { .. } | TerminatorKind::FalseEdge { .. } @@ -1075,12 +1075,14 @@ fn codegen_panic_inner<'tcx>( args: &[Value], span: Option, ) { + fx.bcx.set_cold_block(fx.bcx.current_block().unwrap()); + let def_id = fx.tcx.require_lang_item(lang_item, span); let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx); if is_call_from_compiler_builtins_to_upstream_monomorphization(fx.tcx, instance) { - fx.bcx.ins().trap(TrapCode::User(0)); + fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return; } @@ -1093,5 +1095,5 @@ fn codegen_panic_inner<'tcx>( args, ); - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } diff --git a/src/debuginfo/line_info.rs b/src/debuginfo/line_info.rs index c3d9d635084..fa7b39c836f 100644 --- a/src/debuginfo/line_info.rs +++ b/src/debuginfo/line_info.rs @@ -50,7 +50,12 @@ fn make_file_info(hash: SourceFileHash) -> Option { if hash.kind == SourceFileHashAlgorithm::Md5 { let mut buf = [0u8; MD5_LEN]; buf.copy_from_slice(hash.hash_bytes()); - Some(FileInfo { timestamp: 0, size: 0, md5: buf }) + Some(FileInfo { + timestamp: 0, + size: 0, + md5: buf, + source: None, // FIXME implement -Zembed-source + }) } else { None } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 79d76925df9..78ae43b1c4d 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -101,6 +101,7 @@ pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, cgu_name: &str) -> Self None => (tcx.crate_name(LOCAL_CRATE).to_string(), None), }; + let file_has_md5 = file_info.is_some(); let mut line_program = LineProgram::new( encoding, LineEncoding::default(), @@ -108,7 +109,7 @@ pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, cgu_name: &str) -> Self LineString::new(name.as_bytes(), encoding, &mut dwarf.line_strings), file_info, ); - line_program.file_has_md5 = file_info.is_some(); + line_program.file_has_md5 = file_has_md5; dwarf.unit.line_program = line_program; diff --git a/src/debuginfo/unwind.rs b/src/debuginfo/unwind.rs index 9399230f292..362333d35a4 100644 --- a/src/debuginfo/unwind.rs +++ b/src/debuginfo/unwind.rs @@ -60,8 +60,8 @@ pub(crate) fn add_function(&mut self, func_id: FuncId, context: &Context, isa: & self.frame_table .add_fde(self.cie_id.unwrap(), unwind_info.to_fde(address_for_func(func_id))); } - UnwindInfo::WindowsX64(_) => { - // FIXME implement this + UnwindInfo::WindowsX64(_) | UnwindInfo::WindowsArm64(_) => { + // Windows does not have debug info for its unwind info. } unwind_info => unimplemented!("{:?}", unwind_info), } diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 41f1b30d10b..0fbd5a16830 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -47,7 +47,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( // asm!() by accident and breaks with the GNU assembler as well as global_asm!() for // the LLVM backend. if template.len() == 1 && template[0] == InlineAsmTemplatePiece::String("int $$0x29".into()) { - fx.bcx.ins().trap(TrapCode::User(1)); + fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return; } @@ -137,7 +137,7 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>( fx.bcx.ins().jump(destination_block, &[]); } None => { - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(0 /* unreachable */).unwrap()); } } } diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index aae6794891d..e5a12162687 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -47,7 +47,7 @@ fn report_atomic_type_validation_error<'tcx>( ), ); // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>) -> Type { @@ -449,7 +449,8 @@ fn codegen_regular_intrinsic_call<'tcx>( match intrinsic { sym::abort => { - fx.bcx.ins().trap(TrapCode::User(0)); + fx.bcx.set_cold_block(fx.bcx.current_block().unwrap()); + fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return Ok(()); } sym::likely | sym::unlikely => { diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index e7f9f894381..16fb68a7bdf 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -14,7 +14,7 @@ fn report_simd_type_validation_error( ) { fx.tcx.dcx().span_err(span, format!("invalid monomorphization of `{}` intrinsic: expected SIMD input type, found non-SIMD `{}`", intrinsic, ty)); // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); } pub(super) fn codegen_simd_intrinsic_call<'tcx>( @@ -190,7 +190,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( format!("simd_shuffle index must be a SIMD vector of `u32`, got `{}`", idx_ty), ); // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(1 /* unreachable */).unwrap()); return; }; let n: u16 = idx_ty.simd_size_and_type(fx.tcx).0.try_into().unwrap(); @@ -1135,7 +1135,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( _ => { fx.tcx.dcx().span_err(span, format!("Unknown SIMD intrinsic {}", intrinsic)); // Prevent verifier error - fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); + fx.bcx.ins().trap(TrapCode::user(0 /* unreachable */).unwrap()); return; } } diff --git a/src/lib.rs b/src/lib.rs index fc3bd0abd78..aba0c28f6b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -302,8 +302,11 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Arc { flags_builder.set("opt_level", "none").unwrap(); } - OptLevel::Less | OptLevel::Default => {} - OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => { + OptLevel::Less + | OptLevel::Default + | OptLevel::Size + | OptLevel::SizeMin + | OptLevel::Aggressive => { flags_builder.set("opt_level", "speed_and_size").unwrap(); } } diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index 13877b3b1e9..282763279dd 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -62,9 +62,9 @@ use cranelift_codegen::ir::Fact; use cranelift_codegen::ir::entities::AnyEntity; use cranelift_codegen::write::{FuncWriter, PlainWriter}; -use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::config::{OutputFilenames, OutputType}; +use rustc_target::abi::call::FnAbi; use crate::prelude::*; @@ -76,17 +76,18 @@ pub(crate) struct CommentWriter { } impl CommentWriter { - pub(crate) fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { + pub(crate) fn new<'tcx>( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>, + ) -> Self { let enabled = should_write_ir(tcx); let global_comments = if enabled { with_no_trimmed_paths!({ vec![ format!("symbol {}", tcx.symbol_name(instance).name), format!("instance {:?}", instance), - format!( - "abi {:?}", - RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty()) - ), + format!("abi {:?}", fn_abi), String::new(), ] }) diff --git a/src/trap.rs b/src/trap.rs index a61e1e334ec..9ef1a523d6d 100644 --- a/src/trap.rs +++ b/src/trap.rs @@ -30,5 +30,5 @@ pub(crate) fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRe let one = fx.bcx.ins().iconst(types::I32, 1); fx.lib_call("exit", vec![AbiParam::new(types::I32)], vec![], &[one]); - fx.bcx.ins().trap(TrapCode::User(!0)); + fx.bcx.ins().trap(TrapCode::user(3).unwrap()); } From 541c33ec4187628639be7202545a2caad966b995 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:02:32 +0200 Subject: [PATCH 05/54] Rename target triple to target tuple in many places in the compiler This changes the naming to the new naming, used by `--print target-tuple`. It does not change all locations, but many. --- src/global_asm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/global_asm.rs b/src/global_asm.rs index 0c99a5ce12f..6f90d17920d 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -118,8 +118,8 @@ pub(crate) fn new(tcx: TyCtxt<'_>) -> Self { GlobalAsmConfig { assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"), target: match &tcx.sess.opts.target_triple { - rustc_target::spec::TargetTriple::TargetTriple(triple) => triple.clone(), - rustc_target::spec::TargetTriple::TargetJson { path_for_rustdoc, .. } => { + rustc_target::spec::TargetTuple::TargetTuple(triple) => triple.clone(), + rustc_target::spec::TargetTuple::TargetJson { path_for_rustdoc, .. } => { path_for_rustdoc.to_str().unwrap().to_owned() } }, From 29d225d66540200f07e5b2ce63596f9839f62f4d Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 3 Nov 2024 13:24:53 +0000 Subject: [PATCH 06/54] Manual rustup to rustc 1.84.0-nightly (b3f75cc87 2024-11-02) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 2558b2b9f5d..2f77f3326ae 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-11-02" +channel = "nightly-2024-11-03" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 521288ef0f332ae0f50a80fb36ba88e4a2f65b02 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 3 Nov 2024 13:47:58 +0000 Subject: [PATCH 07/54] Skip testing extended_sysroot tests with cg_llvm on CI --- .github/workflows/main.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2ee94146c1a..70fee3baf21 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -140,7 +140,9 @@ jobs: if: matrix.os != 'windows-latest' || matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu' env: TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} - run: ./y.sh test --sysroot llvm --no-unstable-features + # Skip tests that need cg_clif specific unstable features. Also skip tests that are not + # cg_clif specific and thus unlikely to be broken with cg_llvm. + run: ./y.sh test --sysroot llvm --no-unstable-features --skip-test testsuite.extended_sysroot # This job doesn't use cg_clif in any way. It checks that all cg_clif tests work with cg_llvm too. From 42f71282a76b09e35959cde65f662d459025de7d Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Sat, 2 Nov 2024 18:06:23 -0700 Subject: [PATCH 08/54] cg_clif: Directly use rustc_abi --- src/abi/comments.rs | 2 +- src/abi/mod.rs | 8 ++++---- src/abi/pass_mode.rs | 5 +++-- src/abi/returning.rs | 2 +- src/base.rs | 2 +- src/common.rs | 16 ++++++++-------- src/debuginfo/mod.rs | 2 +- src/inline_asm.rs | 2 +- src/intrinsics/simd.rs | 2 +- src/pointer.rs | 2 +- src/pretty_clif.rs | 2 +- 11 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/abi/comments.rs b/src/abi/comments.rs index daea789ee3e..521a250ab82 100644 --- a/src/abi/comments.rs +++ b/src/abi/comments.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; -use rustc_target::abi::call::PassMode; +use rustc_target::callconv::PassMode; use crate::prelude::*; diff --git a/src/abi/mod.rs b/src/abi/mod.rs index dfca5dcbec8..f647ee36c48 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -10,6 +10,7 @@ use cranelift_codegen::ir::{ArgumentPurpose, SigRef}; use cranelift_codegen::isa::CallConv; use cranelift_module::ModuleError; +use rustc_abi::ExternAbi; use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_codegen_ssa::errors::CompilerBuiltinsCannotCall; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; @@ -18,8 +19,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::Session; use rustc_span::source_map::Spanned; -use rustc_target::abi::call::{Conv, FnAbi, PassMode}; -use rustc_target::spec::abi::Abi; +use rustc_target::callconv::{Conv, FnAbi, PassMode}; use self::pass_mode::*; pub(crate) use self::returning::codegen_return; @@ -443,7 +443,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( RevealAllLayoutCx(fx.tcx).fn_abi_of_fn_ptr(fn_sig, extra_args) }; - let is_cold = if fn_sig.abi() == Abi::RustCold { + let is_cold = if fn_sig.abi() == ExternAbi::RustCold { true } else { instance.is_some_and(|inst| { @@ -458,7 +458,7 @@ pub(crate) fn codegen_terminator_call<'tcx>( } // Unpack arguments tuple for closures - let mut args = if fn_sig.abi() == Abi::RustCall { + let mut args = if fn_sig.abi() == ExternAbi::RustCall { let (self_arg, pack_arg) = match args { [pack_arg] => (None, codegen_call_argument_operand(fx, &pack_arg.node)), [self_arg, pack_arg] => ( diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index ad0a13dc7e5..7594a53fc75 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -1,8 +1,9 @@ //! Argument passing use cranelift_codegen::ir::{ArgumentExtension, ArgumentPurpose}; -use rustc_target::abi::call::{ - ArgAbi, ArgAttributes, ArgExtension as RustcArgExtension, CastTarget, PassMode, Reg, RegKind, +use rustc_abi::{Reg, RegKind}; +use rustc_target::callconv::{ + ArgAbi, ArgAttributes, ArgExtension as RustcArgExtension, CastTarget, PassMode, }; use smallvec::{SmallVec, smallvec}; diff --git a/src/abi/returning.rs b/src/abi/returning.rs index a294c789b22..9e048c7badb 100644 --- a/src/abi/returning.rs +++ b/src/abi/returning.rs @@ -1,6 +1,6 @@ //! Return value handling -use rustc_target::abi::call::{ArgAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, PassMode}; use smallvec::{SmallVec, smallvec}; use crate::prelude::*; diff --git a/src/base.rs b/src/base.rs index 10d5dce9b36..da3818ca25e 100644 --- a/src/base.rs +++ b/src/base.rs @@ -934,7 +934,7 @@ fn is_wide_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool { let dst = codegen_operand(fx, dst); let pointee = dst .layout() - .pointee_info_at(fx, rustc_target::abi::Size::ZERO) + .pointee_info_at(fx, rustc_abi::Size::ZERO) .expect("Expected pointer"); let dst = dst.load_scalar(fx); let src = codegen_operand(fx, src).load_scalar(fx); diff --git a/src/common.rs b/src/common.rs index 69a32cc3d43..27e71b92561 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,13 +1,13 @@ use cranelift_codegen::isa::TargetFrontendConfig; use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; +use rustc_abi::{Float, Integer, Primitive}; use rustc_index::IndexVec; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::layout::{ self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, }; use rustc_span::source_map::Spanned; -use rustc_target::abi::call::FnAbi; -use rustc_target::abi::{Float, Integer, Primitive}; +use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, Target}; use crate::constant::ConstantCx; @@ -162,8 +162,8 @@ pub(crate) fn codegen_icmp_imm( pub(crate) fn codegen_bitcast(fx: &mut FunctionCx<'_, '_, '_>, dst_ty: Type, val: Value) -> Value { let mut flags = MemFlags::new(); flags.set_endianness(match fx.tcx.data_layout.endian { - rustc_target::abi::Endian::Big => cranelift_codegen::ir::Endianness::Big, - rustc_target::abi::Endian::Little => cranelift_codegen::ir::Endianness::Little, + rustc_abi::Endian::Big => cranelift_codegen::ir::Endianness::Big, + rustc_abi::Endian::Little => cranelift_codegen::ir::Endianness::Little, }); fx.bcx.ins().bitcast(dst_ty, flags, val) } @@ -333,8 +333,8 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { } } -impl<'tcx> rustc_target::abi::HasDataLayout for FunctionCx<'_, '_, 'tcx> { - fn data_layout(&self) -> &rustc_target::abi::TargetDataLayout { +impl<'tcx> rustc_abi::HasDataLayout for FunctionCx<'_, '_, 'tcx> { + fn data_layout(&self) -> &rustc_abi::TargetDataLayout { &self.tcx.data_layout } } @@ -491,8 +491,8 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { } } -impl<'tcx> rustc_target::abi::HasDataLayout for RevealAllLayoutCx<'tcx> { - fn data_layout(&self) -> &rustc_target::abi::TargetDataLayout { +impl<'tcx> rustc_abi::HasDataLayout for RevealAllLayoutCx<'tcx> { + fn data_layout(&self) -> &rustc_abi::TargetDataLayout { &self.0.data_layout } } diff --git a/src/debuginfo/mod.rs b/src/debuginfo/mod.rs index 78ae43b1c4d..9025ea97b81 100644 --- a/src/debuginfo/mod.rs +++ b/src/debuginfo/mod.rs @@ -20,7 +20,7 @@ use rustc_hir::def_id::DefIdMap; use rustc_session::Session; use rustc_span::{FileNameDisplayPreference, SourceFileHash, StableSourceFileId}; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; pub(crate) use self::emit::{DebugReloc, DebugRelocName}; pub(crate) use self::types::TypeDebugContext; diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 0fbd5a16830..a3f816f70a9 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -464,7 +464,7 @@ fn allocate_stack_slots(&mut self) { let new_slot_fn = |slot_size: &mut Size, reg_class: InlineAsmRegClass| { let reg_size = reg_class.supported_types(self.arch).iter().map(|(ty, _)| ty.size()).max().unwrap(); - let align = rustc_target::abi::Align::from_bytes(reg_size.bytes()).unwrap(); + let align = rustc_abi::Align::from_bytes(reg_size.bytes()).unwrap(); let offset = slot_size.align_to(align); *slot_size = offset + reg_size; offset diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 16fb68a7bdf..816cab4b1a1 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -1,7 +1,7 @@ //! Codegen `extern "platform-intrinsic"` intrinsics. use cranelift_codegen::ir::immediates::Offset32; -use rustc_target::abi::Endian; +use rustc_abi::Endian; use super::*; use crate::prelude::*; diff --git a/src/pointer.rs b/src/pointer.rs index 11ac6b94678..2750caa216e 100644 --- a/src/pointer.rs +++ b/src/pointer.rs @@ -2,7 +2,7 @@ //! operations. use cranelift_codegen::ir::immediates::Offset32; -use rustc_target::abi::Align; +use rustc_abi::Align; use crate::prelude::*; diff --git a/src/pretty_clif.rs b/src/pretty_clif.rs index 282763279dd..cd254b04ed9 100644 --- a/src/pretty_clif.rs +++ b/src/pretty_clif.rs @@ -64,7 +64,7 @@ use cranelift_codegen::write::{FuncWriter, PlainWriter}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::config::{OutputFilenames, OutputType}; -use rustc_target::abi::call::FnAbi; +use rustc_target::callconv::FnAbi; use crate::prelude::*; From 5e1298ccdb4f33841569ad4b84a64b733bb42a39 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 3 Nov 2024 14:36:21 +0000 Subject: [PATCH 09/54] Revert "Skip testing extended_sysroot tests with cg_llvm on CI" This reverts commit 521288ef0f332ae0f50a80fb36ba88e4a2f65b02. I got what it tests backwards. It tests against a sysroot compiled with LLVM. Not with the LLVM backend. The latter is done by the test_llvm CI job. --- .github/workflows/main.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 70fee3baf21..2ee94146c1a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -140,9 +140,7 @@ jobs: if: matrix.os != 'windows-latest' || matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu' env: TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }} - # Skip tests that need cg_clif specific unstable features. Also skip tests that are not - # cg_clif specific and thus unlikely to be broken with cg_llvm. - run: ./y.sh test --sysroot llvm --no-unstable-features --skip-test testsuite.extended_sysroot + run: ./y.sh test --sysroot llvm --no-unstable-features # This job doesn't use cg_clif in any way. It checks that all cg_clif tests work with cg_llvm too. From 44a056a50b5eecad9e16188d18ea55011c153e7a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 4 Nov 2024 12:11:01 +1100 Subject: [PATCH 10/54] Move `LLVMRustAttribute[Kind]` out of `LLVMWrapper.h` --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- .../rustc_llvm/llvm-wrapper/LLVMWrapper.h | 45 ------ .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 136 ++++++++++++------ 3 files changed, 92 insertions(+), 91 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index d84ae8d8836..26b32d6b886 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -204,7 +204,7 @@ pub enum DLLStorageClass { DllExport = 2, // Function to be accessible from DLL. } -/// Matches LLVMRustAttribute in LLVMWrapper.h +/// Must match the layout of `LLVMRustAttributeKind`. /// Semantically a subset of the C++ enum llvm::Attribute::AttrKind, /// though it is not ABI compatible (since it's a C++ enum) #[repr(C)] diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 73bbc9de855..f2bfdfed8d2 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -55,51 +55,6 @@ extern "C" void LLVMRustSetLastError(const char *); enum class LLVMRustResult { Success, Failure }; -enum LLVMRustAttribute { - AlwaysInline = 0, - ByVal = 1, - Cold = 2, - InlineHint = 3, - MinSize = 4, - Naked = 5, - NoAlias = 6, - NoCapture = 7, - NoInline = 8, - NonNull = 9, - NoRedZone = 10, - NoReturn = 11, - NoUnwind = 12, - OptimizeForSize = 13, - ReadOnly = 14, - SExt = 15, - StructRet = 16, - UWTable = 17, - ZExt = 18, - InReg = 19, - SanitizeThread = 20, - SanitizeAddress = 21, - SanitizeMemory = 22, - NonLazyBind = 23, - OptimizeNone = 24, - ReadNone = 26, - SanitizeHWAddress = 28, - WillReturn = 29, - StackProtectReq = 30, - StackProtectStrong = 31, - StackProtect = 32, - NoUndef = 33, - SanitizeMemTag = 34, - NoCfCheck = 35, - ShadowCallStack = 36, - AllocSize = 37, - AllocatedPointer = 38, - AllocAlign = 39, - SanitizeSafeStack = 40, - FnRetThunkExtern = 41, - Writable = 42, - DeadOnUnwind = 43, -}; - typedef struct OpaqueRustString *RustStringRef; typedef struct LLVMOpaqueTwine *LLVMTwineRef; typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 645b4082be5..22d7d10327b 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -228,94 +228,140 @@ extern "C" LLVMValueRef LLVMRustInsertPrivateGlobal(LLVMModuleRef M, GlobalValue::PrivateLinkage, nullptr)); } -static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { +// Must match the layout of `rustc_codegen_llvm::llvm::ffi::AttributeKind`. +enum class LLVMRustAttributeKind { + AlwaysInline = 0, + ByVal = 1, + Cold = 2, + InlineHint = 3, + MinSize = 4, + Naked = 5, + NoAlias = 6, + NoCapture = 7, + NoInline = 8, + NonNull = 9, + NoRedZone = 10, + NoReturn = 11, + NoUnwind = 12, + OptimizeForSize = 13, + ReadOnly = 14, + SExt = 15, + StructRet = 16, + UWTable = 17, + ZExt = 18, + InReg = 19, + SanitizeThread = 20, + SanitizeAddress = 21, + SanitizeMemory = 22, + NonLazyBind = 23, + OptimizeNone = 24, + ReadNone = 26, + SanitizeHWAddress = 28, + WillReturn = 29, + StackProtectReq = 30, + StackProtectStrong = 31, + StackProtect = 32, + NoUndef = 33, + SanitizeMemTag = 34, + NoCfCheck = 35, + ShadowCallStack = 36, + AllocSize = 37, + AllocatedPointer = 38, + AllocAlign = 39, + SanitizeSafeStack = 40, + FnRetThunkExtern = 41, + Writable = 42, + DeadOnUnwind = 43, +}; + +static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) { switch (Kind) { - case AlwaysInline: + case LLVMRustAttributeKind::AlwaysInline: return Attribute::AlwaysInline; - case ByVal: + case LLVMRustAttributeKind::ByVal: return Attribute::ByVal; - case Cold: + case LLVMRustAttributeKind::Cold: return Attribute::Cold; - case InlineHint: + case LLVMRustAttributeKind::InlineHint: return Attribute::InlineHint; - case MinSize: + case LLVMRustAttributeKind::MinSize: return Attribute::MinSize; - case Naked: + case LLVMRustAttributeKind::Naked: return Attribute::Naked; - case NoAlias: + case LLVMRustAttributeKind::NoAlias: return Attribute::NoAlias; - case NoCapture: + case LLVMRustAttributeKind::NoCapture: return Attribute::NoCapture; - case NoCfCheck: + case LLVMRustAttributeKind::NoCfCheck: return Attribute::NoCfCheck; - case NoInline: + case LLVMRustAttributeKind::NoInline: return Attribute::NoInline; - case NonNull: + case LLVMRustAttributeKind::NonNull: return Attribute::NonNull; - case NoRedZone: + case LLVMRustAttributeKind::NoRedZone: return Attribute::NoRedZone; - case NoReturn: + case LLVMRustAttributeKind::NoReturn: return Attribute::NoReturn; - case NoUnwind: + case LLVMRustAttributeKind::NoUnwind: return Attribute::NoUnwind; - case OptimizeForSize: + case LLVMRustAttributeKind::OptimizeForSize: return Attribute::OptimizeForSize; - case ReadOnly: + case LLVMRustAttributeKind::ReadOnly: return Attribute::ReadOnly; - case SExt: + case LLVMRustAttributeKind::SExt: return Attribute::SExt; - case StructRet: + case LLVMRustAttributeKind::StructRet: return Attribute::StructRet; - case UWTable: + case LLVMRustAttributeKind::UWTable: return Attribute::UWTable; - case ZExt: + case LLVMRustAttributeKind::ZExt: return Attribute::ZExt; - case InReg: + case LLVMRustAttributeKind::InReg: return Attribute::InReg; - case SanitizeThread: + case LLVMRustAttributeKind::SanitizeThread: return Attribute::SanitizeThread; - case SanitizeAddress: + case LLVMRustAttributeKind::SanitizeAddress: return Attribute::SanitizeAddress; - case SanitizeMemory: + case LLVMRustAttributeKind::SanitizeMemory: return Attribute::SanitizeMemory; - case NonLazyBind: + case LLVMRustAttributeKind::NonLazyBind: return Attribute::NonLazyBind; - case OptimizeNone: + case LLVMRustAttributeKind::OptimizeNone: return Attribute::OptimizeNone; - case ReadNone: + case LLVMRustAttributeKind::ReadNone: return Attribute::ReadNone; - case SanitizeHWAddress: + case LLVMRustAttributeKind::SanitizeHWAddress: return Attribute::SanitizeHWAddress; - case WillReturn: + case LLVMRustAttributeKind::WillReturn: return Attribute::WillReturn; - case StackProtectReq: + case LLVMRustAttributeKind::StackProtectReq: return Attribute::StackProtectReq; - case StackProtectStrong: + case LLVMRustAttributeKind::StackProtectStrong: return Attribute::StackProtectStrong; - case StackProtect: + case LLVMRustAttributeKind::StackProtect: return Attribute::StackProtect; - case NoUndef: + case LLVMRustAttributeKind::NoUndef: return Attribute::NoUndef; - case SanitizeMemTag: + case LLVMRustAttributeKind::SanitizeMemTag: return Attribute::SanitizeMemTag; - case ShadowCallStack: + case LLVMRustAttributeKind::ShadowCallStack: return Attribute::ShadowCallStack; - case AllocSize: + case LLVMRustAttributeKind::AllocSize: return Attribute::AllocSize; - case AllocatedPointer: + case LLVMRustAttributeKind::AllocatedPointer: return Attribute::AllocatedPointer; - case AllocAlign: + case LLVMRustAttributeKind::AllocAlign: return Attribute::AllocAlign; - case SanitizeSafeStack: + case LLVMRustAttributeKind::SanitizeSafeStack: return Attribute::SafeStack; - case FnRetThunkExtern: + case LLVMRustAttributeKind::FnRetThunkExtern: return Attribute::FnRetThunkExtern; - case Writable: + case LLVMRustAttributeKind::Writable: return Attribute::Writable; - case DeadOnUnwind: + case LLVMRustAttributeKind::DeadOnUnwind: return Attribute::DeadOnUnwind; } - report_fatal_error("bad AttributeKind"); + report_fatal_error("bad LLVMRustAttributeKind"); } template @@ -345,7 +391,7 @@ extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, } extern "C" LLVMAttributeRef -LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttribute RustAttr) { +LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) { return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr))); } From 920d2774ac92b102dedf07d04d5fd80214881699 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 3 Nov 2024 21:09:01 +1100 Subject: [PATCH 11/54] Trim and tidy includes in `rustc_llvm` --- .../llvm-wrapper/CoverageMappingWrapper.cpp | 4 ++ .../rustc_llvm/llvm-wrapper/LLVMWrapper.h | 53 ++++--------------- compiler/rustc_llvm/llvm-wrapper/Linker.cpp | 8 +-- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 37 +++++++------ .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 20 +++++-- .../rustc_llvm/llvm-wrapper/SymbolWrapper.cpp | 4 +- 6 files changed, 53 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp index b32af5e5e75..fd1054ef50a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp @@ -1,5 +1,9 @@ #include "LLVMWrapper.h" + #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Module.h" #include "llvm/ProfileData/Coverage/CoverageMapping.h" #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" #include "llvm/ProfileData/InstrProf.h" diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index f2bfdfed8d2..40714eb8dbe 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -1,31 +1,12 @@ +#ifndef INCLUDED_RUSTC_LLVM_LLVMWRAPPER_H +#define INCLUDED_RUSTC_LLVM_LLVMWRAPPER_H + #include "SuppressLLVMWarnings.h" -#include "llvm-c/BitReader.h" -#include "llvm-c/Core.h" -#include "llvm-c/Object.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Analysis/Lint.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/InlineAsm.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/JSON.h" -#include "llvm/Support/Memory.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/Timer.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Scalar.h" +#include "llvm/Config/llvm-config.h" // LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR +#include "llvm/Support/raw_ostream.h" // llvm::raw_ostream +#include // size_t etc +#include // uint64_t etc #define LLVM_VERSION_GE(major, minor) \ (LLVM_VERSION_MAJOR > (major) || \ @@ -33,24 +14,6 @@ #define LLVM_VERSION_LT(major, minor) (!LLVM_VERSION_GE((major), (minor))) -#if LLVM_VERSION_GE(20, 0) -#include "llvm/Transforms/Utils/Instrumentation.h" -#else -#include "llvm/Transforms/Instrumentation.h" -#endif - -#include "llvm/IR/LegacyPassManager.h" - -#include "llvm/Bitcode/BitcodeReader.h" -#include "llvm/Bitcode/BitcodeWriter.h" - -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/IRPrintingPasses.h" -#include "llvm/Linker/Linker.h" - -#include "llvm/TargetParser/Triple.h" - extern "C" void LLVMRustSetLastError(const char *); enum class LLVMRustResult { Success, Failure }; @@ -81,3 +44,5 @@ public: flush(); } }; + +#endif // INCLUDED_RUSTC_LLVM_LLVMWRAPPER_H diff --git a/compiler/rustc_llvm/llvm-wrapper/Linker.cpp b/compiler/rustc_llvm/llvm-wrapper/Linker.cpp index f43128ed550..fdf54e2d9b4 100644 --- a/compiler/rustc_llvm/llvm-wrapper/Linker.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/Linker.cpp @@ -1,8 +1,10 @@ -#include "llvm/Linker/Linker.h" -#include "SuppressLLVMWarnings.h" - #include "LLVMWrapper.h" +#include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/IR/Module.h" +#include "llvm/Linker/Linker.h" +#include "llvm/Support/MemoryBuffer.h" + using namespace llvm; struct RustLinker { diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 5d2df6ddfc9..39d36fc3408 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1,25 +1,21 @@ -#include - -#include -#include -#include -#include - #include "LLVMWrapper.h" -#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm-c/Core.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Analysis/Lint.h" #include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/CodeGen/CommandFlags.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/AssemblyAnnotationWriter.h" #include "llvm/IR/AutoUpgrade.h" -#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/PassManager.h" #include "llvm/IR/Verifier.h" #include "llvm/LTO/LTO.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/TargetRegistry.h" -#include "llvm/Object/IRObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Passes/PassPlugin.h" @@ -30,25 +26,28 @@ #include "llvm/Support/VirtualFileSystem.h" #include "llvm/Target/TargetMachine.h" #include "llvm/TargetParser/Host.h" -#include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/FunctionImport.h" #include "llvm/Transforms/IPO/Internalize.h" #include "llvm/Transforms/IPO/LowerTypeTests.h" #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include "llvm/Transforms/Instrumentation/AddressSanitizer.h" #include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h" -#include "llvm/Transforms/Utils/AddDiscriminators.h" -#include "llvm/Transforms/Utils/FunctionImportUtils.h" -#if LLVM_VERSION_GE(19, 0) -#include "llvm/Support/PGOOptions.h" -#endif #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" #include "llvm/Transforms/Instrumentation/InstrProfiling.h" #include "llvm/Transforms/Instrumentation/MemorySanitizer.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" -#include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/CanonicalizeAliases.h" +#include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/Transforms/Utils/NameAnonGlobals.h" +#include +#include +#include + +// Conditional includes prevent clang-format from fully sorting the list, +// so keep them separate. +#if LLVM_VERSION_GE(19, 0) +#include "llvm/Support/PGOOptions.h" +#endif using namespace llvm; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 22d7d10327b..b15060f3647 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1,28 +1,38 @@ #include "LLVMWrapper.h" + +#include "llvm-c/Core.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/BinaryFormat/Magic.h" #include "llvm/Bitcode/BitcodeWriter.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DiagnosticHandler.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/Intrinsics.h" #include "llvm/IR/IntrinsicsARM.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/LLVMRemarkStreamer.h" #include "llvm/IR/Mangler.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Value.h" -#include "llvm/Object/Archive.h" #include "llvm/Object/COFFImportFile.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Pass.h" #include "llvm/Remarks/RemarkFormat.h" #include "llvm/Remarks/RemarkSerializer.h" #include "llvm/Remarks/RemarkStreamer.h" +#include "llvm/Support/Compression.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/JSON.h" #include "llvm/Support/ModRef.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/Timer.h" #include "llvm/Support/ToolOutputFile.h" - #include // for raw `write` in the bad-alloc handler diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp index 54ee79dc290..a910e78d489 100644 --- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp @@ -8,14 +8,14 @@ // * https://github.com/llvm/llvm-project/blob/ef6d1ec07c693352c4a60dd58db08d2d8558f6ea/llvm/lib/Object/ArchiveWriter.cpp #include "LLVMWrapper.h" -#include "SuppressLLVMWarnings.h" + #include "llvm/ADT/SmallString.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Object/COFF.h" #include "llvm/Object/COFFImportFile.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Object/ObjectFile.h" -#include +#include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::sys; From b71483b2a14a404932e1167d567468fefa43d27c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:40:15 +0000 Subject: [PATCH 12/54] Rustup to rustc 1.84.0-nightly (854980293 2024-11-06) --- patches/0022-coretests-Disable-not-compiling-tests.patch | 2 +- patches/0027-coretests-128bit-atomic-operations.patch | 2 +- rust-toolchain | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/patches/0022-coretests-Disable-not-compiling-tests.patch b/patches/0022-coretests-Disable-not-compiling-tests.patch index 6ed22c5a18e..1860810e7f3 100644 --- a/patches/0022-coretests-Disable-not-compiling-tests.patch +++ b/patches/0022-coretests-Disable-not-compiling-tests.patch @@ -38,7 +38,7 @@ index 42a26ae..5ac1042 100644 @@ -1,3 +1,4 @@ +#![cfg(test)] // tidy-alphabetical-start + #![cfg_attr(bootstrap, feature(const_three_way_compare))] #![cfg_attr(bootstrap, feature(strict_provenance))] - #![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] -- 2.21.0 (Apple Git-122) diff --git a/patches/0027-coretests-128bit-atomic-operations.patch b/patches/0027-coretests-128bit-atomic-operations.patch index 50a42aea322..59653c6e875 100644 --- a/patches/0027-coretests-128bit-atomic-operations.patch +++ b/patches/0027-coretests-128bit-atomic-operations.patch @@ -15,7 +15,7 @@ index 1e336bf..35e6f54 100644 --- a/lib.rs +++ b/lib.rs @@ -2,7 +2,6 @@ - // tidy-alphabetical-start + #![cfg_attr(bootstrap, feature(const_three_way_compare))] #![cfg_attr(bootstrap, feature(strict_provenance))] #![cfg_attr(not(bootstrap), feature(strict_provenance_lints))] -#![cfg_attr(target_has_atomic = "128", feature(integer_atomics))] diff --git a/rust-toolchain b/rust-toolchain index 2f77f3326ae..af89725b72c 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-11-03" +channel = "nightly-2024-11-07" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From b5966e4e88b649997bce5948ced6730a4913e692 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:33:34 +0000 Subject: [PATCH 13/54] Fix bootstrap test --- scripts/test_bootstrap.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scripts/test_bootstrap.sh b/scripts/test_bootstrap.sh index 791d457993d..770f2b6df6c 100755 --- a/scripts/test_bootstrap.sh +++ b/scripts/test_bootstrap.sh @@ -11,5 +11,22 @@ rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src} cp ../Cargo.* compiler/rustc_codegen_cranelift/ cp -r ../src compiler/rustc_codegen_cranelift/src +# FIXME(rust-lang/rust#132719) remove once it doesn't break without this patch +cat <) -> Compiler { + } + } + +- { ++ if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled { + // \`llvm-strip\` is used by rustc, which is actually just a symlink to \`llvm-objcopy\`, + // so copy and rename \`llvm-objcopy\`. + let src_exe = exe("llvm-objcopy", target_compiler.host); +EOF + ./x.py build --stage 1 library/std popd From ba6a38495f993253ec7b53e4f06aba8c498ff29f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 7 Nov 2024 17:42:49 +0100 Subject: [PATCH 14/54] remove 'platform-intrinsic' ABI leftovers --- src/intrinsics/mod.rs | 2 +- src/intrinsics/simd.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index e5a12162687..1e2e41b3122 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1,4 +1,4 @@ -//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, `extern "platform-intrinsic"` +//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, //! and LLVM intrinsics that have symbol names starting with `llvm.`. macro_rules! intrinsic_args { diff --git a/src/intrinsics/simd.rs b/src/intrinsics/simd.rs index 16fb68a7bdf..36a35d42c3e 100644 --- a/src/intrinsics/simd.rs +++ b/src/intrinsics/simd.rs @@ -1,4 +1,4 @@ -//! Codegen `extern "platform-intrinsic"` intrinsics. +//! Codegen SIMD intrinsics. use cranelift_codegen::ir::immediates::Offset32; use rustc_target::abi::Endian; From 90fa5b608ddf6b8715dbd780e7f986e741ac9bf3 Mon Sep 17 00:00:00 2001 From: binarycat Date: Thu, 7 Nov 2024 14:23:53 -0600 Subject: [PATCH 15/54] add regression test for #90781 --- tests/rustdoc/hidden-implementors-90781.rs | 78 ++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 tests/rustdoc/hidden-implementors-90781.rs diff --git a/tests/rustdoc/hidden-implementors-90781.rs b/tests/rustdoc/hidden-implementors-90781.rs new file mode 100644 index 00000000000..960a85b91f0 --- /dev/null +++ b/tests/rustdoc/hidden-implementors-90781.rs @@ -0,0 +1,78 @@ +//@ compile-flags: -Z unstable-options --document-hidden-items --document-private-items + +// regression test for https://github.com/rust-lang/rust/issues/90781 +#![crate_name = "foo"] + +//@ has foo/trait.TPubVis.html +//@ has - '//*[@id="implementors-list"]' 'HidPriv' +//@ has - '//*[@id="implementors-list"]' 'HidPub' +//@ has - '//*[@id="implementors-list"]' 'VisPriv' +//@ has - '//*[@id="implementors-list"]' 'VisPub' +pub trait TPubVis {} + +//@ has foo/trait.TPubHidden.html +//@ has - '//*[@id="implementors-list"]' 'HidPriv' +//@ has - '//*[@id="implementors-list"]' 'HidPub' +//@ has - '//*[@id="implementors-list"]' 'VisPriv' +//@ has - '//*[@id="implementors-list"]' 'VisPub' +#[doc(hidden)] +pub trait TPubHidden {} + +//@ has foo/trait.TPrivVis.html +//@ has - '//*[@id="implementors-list"]' 'HidPriv' +//@ has - '//*[@id="implementors-list"]' 'HidPub' +//@ has - '//*[@id="implementors-list"]' 'VisPriv' +//@ has - '//*[@id="implementors-list"]' 'VisPub' +trait TPrivVis {} + +#[doc(hidden)] +//@ has foo/trait.TPrivHidden.html +//@ has - '//*[@id="impl-TPrivHidden-for-HidPriv"]' 'HidPriv' +//@ has - '//*[@id="impl-TPrivHidden-for-HidPub"]' 'HidPub' +//@ has - '//*[@id="impl-TPrivHidden-for-VisPriv"]' 'VisPriv' +//@ has - '//*[@id="impl-TPrivHidden-for-VisPub"]' 'VisPub' +trait TPrivHidden {} + +//@ has foo/struct.VisPub.html +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivVis' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubVis' +pub struct VisPub; + +//@ has foo/struct.VisPriv.html +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivVis' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubVis' +struct VisPriv; + +//@ has foo/struct.HidPub.html +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivVis' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubVis' +#[doc(hidden)] +pub struct HidPub; + +//@ has foo/struct.HidPriv.html +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPrivVis' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubHidden' +//@ has - '//*[@id="trait-implementations-list"]' 'TPubVis' +#[doc(hidden)] +struct HidPriv; + +macro_rules! implement { + ($trait:ident - $($struct:ident)+) => { + $( + impl $trait for $struct {} + )+ + } +} + + +implement!(TPubVis - VisPub VisPriv HidPub HidPriv); +implement!(TPubHidden - VisPub VisPriv HidPub HidPriv); +implement!(TPrivVis - VisPub VisPriv HidPub HidPriv); +implement!(TPrivHidden - VisPub VisPriv HidPub HidPriv); From ab62a352ba5eeae79ff3dab0788a2134eac3f674 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 2 Oct 2024 05:26:15 +0900 Subject: [PATCH 16/54] Stabilize s390x inline assembly --- compiler/rustc_ast_lowering/src/asm.rs | 1 + .../asm-experimental-arch.md | 21 ++----------------- tests/assembly/asm/s390x-types.rs | 2 +- tests/codegen/asm/s390x-clobbers.rs | 2 +- 4 files changed, 5 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 6585a7de245..3acca94a54b 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -48,6 +48,7 @@ pub(crate) fn lower_inline_asm( | asm::InlineAsmArch::RiscV32 | asm::InlineAsmArch::RiscV64 | asm::InlineAsmArch::LoongArch64 + | asm::InlineAsmArch::S390x ); if !is_stable && !self.tcx.features().asm_experimental_arch() { feature_err( diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md index 3029c3989c9..f00a0fe7287 100644 --- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md +++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md @@ -18,7 +18,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect - MSP430 - M68k - CSKY -- s390x - Arm64EC - SPARC @@ -52,11 +51,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `reg_addr` | `a[0-3]` | `a` | | CSKY | `reg` | `r[0-31]` | `r` | | CSKY | `freg` | `f[0-31]` | `f` | -| s390x | `reg` | `r[0-10]`, `r[12-14]` | `r` | -| s390x | `reg_addr` | `r[1-10]`, `r[12-14]` | `a` | -| s390x | `freg` | `f[0-15]` | `f` | -| s390x | `vreg` | `v[0-31]` | Only clobbers | -| s390x | `areg` | `a[2-15]` | Only clobbers | | SPARC | `reg` | `r[2-29]` | `r` | | SPARC | `yreg` | `y` | Only clobbers | | Arm64EC | `reg` | `x[0-12]`, `x[15-22]`, `x[25-27]`, `x30` | `r` | @@ -96,10 +90,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | M68k | `reg_data` | None | `i8`, `i16`, `i32` | | CSKY | `reg` | None | `i8`, `i16`, `i32` | | CSKY | `freg` | None | `f32`, | -| s390x | `reg`, `reg_addr` | None | `i8`, `i16`, `i32`, `i64` | -| s390x | `freg` | None | `f32`, `f64` | -| s390x | `vreg` | N/A | Only clobbers | -| s390x | `areg` | N/A | Only clobbers | | SPARC | `reg` | None | `i8`, `i16`, `i32`, `i64` (SPARC64 only) | | SPARC | `yreg` | N/A | Only clobbers | | Arm64EC | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` | @@ -159,8 +149,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | Architecture | Unsupported register | Reason | | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| All | `sp`, `r15` (s390x), `r14`/`o6` (SPARC) | The stack pointer must be restored to its original value at the end of an asm code block. | -| All | `fr` (Hexagon), `fp` (PowerPC), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r11` (s390x), `r30`/`i6` (SPARC), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output. | +| All | `sp`, `r14`/`o6` (SPARC) | The stack pointer must be restored to its original value at the end of an asm code block. | +| All | `fr` (Hexagon), `fp` (PowerPC), `$fp` (MIPS), `Y` (AVR), `r4` (MSP430), `a6` (M68k), `r30`/`i6` (SPARC), `x29` (Arm64EC) | The frame pointer cannot be used as an input or output. | | All | `r19` (Hexagon), `r29` (PowerPC), `r30` (PowerPC), `x19` (Arm64EC) | These are used internally by LLVM as "base pointer" for functions with complex stack frames. | | MIPS | `$0` or `$zero` | This is a constant zero register which can't be modified. | | MIPS | `$1` or `$at` | Reserved for assembler. | @@ -181,8 +171,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | CSKY | `r15` | This is the link register. | | CSKY | `r[26-30]` | Reserved by its ABI. | | CSKY | `r31` | This is the TLS register. | -| s390x | `c[0-15]` | Reserved by the kernel. | -| s390x | `a[0-1]` | Reserved for system use. | | SPARC | `r0`/`g0` | This is always zero and cannot be used as inputs or outputs. | | SPARC | `r1`/`g1` | Used internally by LLVM. | | SPARC | `r5`/`g5` | Reserved for system. (SPARC32 only) | @@ -206,9 +194,6 @@ This feature tracks `asm!` and `global_asm!` support for the following architect | PowerPC | `reg` | None | `0` | None | | PowerPC | `reg_nonzero` | None | `3` | None | | PowerPC | `freg` | None | `0` | None | -| s390x | `reg` | None | `%r0` | None | -| s390x | `reg_addr` | None | `%r1` | None | -| s390x | `freg` | None | `%f0` | None | | SPARC | `reg` | None | `%o0` | None | | CSKY | `reg` | None | `r0` | None | | CSKY | `freg` | None | `f0` | None | @@ -232,8 +217,6 @@ These flags registers must be restored upon exiting the asm block if the `preser - The status register `r2`. - M68k - The condition code register `ccr`. -- s390x - - The condition code register `cc`. - SPARC - Integer condition codes (`icc` and `xcc`) - Floating-point condition codes (`fcc[0-3]`) diff --git a/tests/assembly/asm/s390x-types.rs b/tests/assembly/asm/s390x-types.rs index e68b18d7aa6..b1522198a08 100644 --- a/tests/assembly/asm/s390x-types.rs +++ b/tests/assembly/asm/s390x-types.rs @@ -4,7 +4,7 @@ //@[s390x] needs-llvm-components: systemz //@ compile-flags: -Zmerge-functions=disabled -#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)] +#![feature(no_core, lang_items, rustc_attrs, repr_simd)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] diff --git a/tests/codegen/asm/s390x-clobbers.rs b/tests/codegen/asm/s390x-clobbers.rs index 45f72206bdf..56d82b4b044 100644 --- a/tests/codegen/asm/s390x-clobbers.rs +++ b/tests/codegen/asm/s390x-clobbers.rs @@ -3,7 +3,7 @@ //@[s390x] needs-llvm-components: systemz #![crate_type = "rlib"] -#![feature(no_core, rustc_attrs, lang_items, asm_experimental_arch)] +#![feature(no_core, rustc_attrs, lang_items)] #![no_core] #[lang = "sized"] From 8f7f9b93b2cf1f16d4ded534ff14ce9a673177c0 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 8 Nov 2024 00:11:21 +1100 Subject: [PATCH 17/54] Add a run-make test for `rustc --help` and similar --- src/tools/run-make-support/src/lib.rs | 1 + tests/run-make/rustc-help/help-v.diff | 29 ++++++++++ tests/run-make/rustc-help/help-v.stdout | 77 +++++++++++++++++++++++++ tests/run-make/rustc-help/help.stdout | 60 +++++++++++++++++++ tests/run-make/rustc-help/rmake.rs | 21 +++++++ 5 files changed, 188 insertions(+) create mode 100644 tests/run-make/rustc-help/help-v.diff create mode 100644 tests/run-make/rustc-help/help-v.stdout create mode 100644 tests/run-make/rustc-help/help.stdout create mode 100644 tests/run-make/rustc-help/rmake.rs diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 368b98c9f0d..5765cb97a7e 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -41,6 +41,7 @@ pub mod rfs { pub use object; pub use regex; pub use serde_json; +pub use similar; pub use wasmparser; // tidy-alphabetical-end diff --git a/tests/run-make/rustc-help/help-v.diff b/tests/run-make/rustc-help/help-v.diff new file mode 100644 index 00000000000..22c5dd81bdb --- /dev/null +++ b/tests/run-make/rustc-help/help-v.diff @@ -0,0 +1,29 @@ +@@ -51,10 +51,27 @@ + Set a codegen option + -V, --version Print version info and exit + -v, --verbose Use verbose output ++ --extern NAME[=PATH] ++ Specify where an external rust library is located ++ --sysroot PATH Override the system root ++ --error-format human|json|short ++ How errors and other messages are produced ++ --json CONFIG Configure the JSON output of the compiler ++ --color auto|always|never ++ Configure coloring of output: ++ auto = colorize, if output goes to a tty (default); ++ always = always colorize output; ++ never = never colorize output ++ --diagnostic-width WIDTH ++ Inform rustc of the width of the output so that ++ diagnostics can be truncated to fit ++ --remap-path-prefix FROM=TO ++ Remap source names in all output (compiler messages ++ and output files) ++ @path Read newline separated options from `path` + + Additional help: + -C help Print codegen options + -W help Print 'lint' options and default settings + -Z help Print unstable compiler options +- --help -v Print the full set of options rustc accepts + diff --git a/tests/run-make/rustc-help/help-v.stdout b/tests/run-make/rustc-help/help-v.stdout new file mode 100644 index 00000000000..dbd67b57df2 --- /dev/null +++ b/tests/run-make/rustc-help/help-v.stdout @@ -0,0 +1,77 @@ +Usage: rustc [OPTIONS] INPUT + +Options: + -h, --help Display this message + --cfg SPEC Configure the compilation environment. + SPEC supports the syntax `NAME[="VALUE"]`. + --check-cfg SPEC + Provide list of expected cfgs for checking + -L [KIND=]PATH Add a directory to the library search path. The + optional KIND can be one of dependency, crate, native, + framework, or all (the default). + -l [KIND[:MODIFIERS]=]NAME[:RENAME] + Link the generated crate(s) to the specified native + library NAME. The optional KIND can be one of + static, framework, or dylib (the default). + Optional comma separated MODIFIERS + (bundle|verbatim|whole-archive|as-needed) + may be specified each with a prefix of either '+' to + enable or '-' to disable. + --crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro] + Comma separated list of types of crates + for the compiler to emit + --crate-name NAME + Specify the name of the crate being built + --edition 2015|2018|2021|2024 + Specify which edition of the compiler to use when + compiling code. The default is 2015 and the latest + stable edition is 2021. + --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] + Comma separated list of types of output for the + compiler to emit + --print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target] + Compiler information to print on stdout + -g Equivalent to -C debuginfo=2 + -O Equivalent to -C opt-level=2 + -o FILENAME Write output to + --out-dir DIR Write output to compiler-chosen filename in + --explain OPT Provide a detailed explanation of an error message + --test Build a test harness + --target TARGET Target triple for which the code is compiled + -A, --allow LINT Set lint allowed + -W, --warn LINT Set lint warnings + --force-warn LINT + Set lint force-warn + -D, --deny LINT Set lint denied + -F, --forbid LINT Set lint forbidden + --cap-lints LEVEL + Set the most restrictive lint level. More restrictive + lints are capped at this level + -C, --codegen OPT[=VALUE] + Set a codegen option + -V, --version Print version info and exit + -v, --verbose Use verbose output + --extern NAME[=PATH] + Specify where an external rust library is located + --sysroot PATH Override the system root + --error-format human|json|short + How errors and other messages are produced + --json CONFIG Configure the JSON output of the compiler + --color auto|always|never + Configure coloring of output: + auto = colorize, if output goes to a tty (default); + always = always colorize output; + never = never colorize output + --diagnostic-width WIDTH + Inform rustc of the width of the output so that + diagnostics can be truncated to fit + --remap-path-prefix FROM=TO + Remap source names in all output (compiler messages + and output files) + @path Read newline separated options from `path` + +Additional help: + -C help Print codegen options + -W help Print 'lint' options and default settings + -Z help Print unstable compiler options + diff --git a/tests/run-make/rustc-help/help.stdout b/tests/run-make/rustc-help/help.stdout new file mode 100644 index 00000000000..a7d07162799 --- /dev/null +++ b/tests/run-make/rustc-help/help.stdout @@ -0,0 +1,60 @@ +Usage: rustc [OPTIONS] INPUT + +Options: + -h, --help Display this message + --cfg SPEC Configure the compilation environment. + SPEC supports the syntax `NAME[="VALUE"]`. + --check-cfg SPEC + Provide list of expected cfgs for checking + -L [KIND=]PATH Add a directory to the library search path. The + optional KIND can be one of dependency, crate, native, + framework, or all (the default). + -l [KIND[:MODIFIERS]=]NAME[:RENAME] + Link the generated crate(s) to the specified native + library NAME. The optional KIND can be one of + static, framework, or dylib (the default). + Optional comma separated MODIFIERS + (bundle|verbatim|whole-archive|as-needed) + may be specified each with a prefix of either '+' to + enable or '-' to disable. + --crate-type [bin|lib|rlib|dylib|cdylib|staticlib|proc-macro] + Comma separated list of types of crates + for the compiler to emit + --crate-name NAME + Specify the name of the crate being built + --edition 2015|2018|2021|2024 + Specify which edition of the compiler to use when + compiling code. The default is 2015 and the latest + stable edition is 2021. + --emit [asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir] + Comma separated list of types of output for the + compiler to emit + --print [crate-name|file-names|sysroot|target-libdir|cfg|check-cfg|calling-conventions|target-list|target-cpus|target-features|relocation-models|code-models|tls-models|target-spec-json|all-target-specs-json|native-static-libs|stack-protector-strategies|link-args|deployment-target] + Compiler information to print on stdout + -g Equivalent to -C debuginfo=2 + -O Equivalent to -C opt-level=2 + -o FILENAME Write output to + --out-dir DIR Write output to compiler-chosen filename in + --explain OPT Provide a detailed explanation of an error message + --test Build a test harness + --target TARGET Target triple for which the code is compiled + -A, --allow LINT Set lint allowed + -W, --warn LINT Set lint warnings + --force-warn LINT + Set lint force-warn + -D, --deny LINT Set lint denied + -F, --forbid LINT Set lint forbidden + --cap-lints LEVEL + Set the most restrictive lint level. More restrictive + lints are capped at this level + -C, --codegen OPT[=VALUE] + Set a codegen option + -V, --version Print version info and exit + -v, --verbose Use verbose output + +Additional help: + -C help Print codegen options + -W help Print 'lint' options and default settings + -Z help Print unstable compiler options + --help -v Print the full set of options rustc accepts + diff --git a/tests/run-make/rustc-help/rmake.rs b/tests/run-make/rustc-help/rmake.rs new file mode 100644 index 00000000000..85e90e6352d --- /dev/null +++ b/tests/run-make/rustc-help/rmake.rs @@ -0,0 +1,21 @@ +// Tests `rustc --help` and similar invocations against snapshots and each other. + +use run_make_support::{bare_rustc, diff, similar}; + +fn main() { + // `rustc --help` + let help = bare_rustc().arg("--help").run().stdout_utf8(); + diff().expected_file("help.stdout").actual_text("(rustc --help)", &help).run(); + + // `rustc` should be the same as `rustc --help` + let bare = bare_rustc().run().stdout_utf8(); + diff().expected_text("(rustc --help)", &help).actual_text("(rustc)", &bare).run(); + + // `rustc --help -v` should give a similar but longer help message + let help_v = bare_rustc().arg("--help").arg("-v").run().stdout_utf8(); + diff().expected_file("help-v.stdout").actual_text("(rustc --help -v)", &help_v).run(); + + // Check the diff between `rustc --help` and `rustc --help -v`. + let help_v_diff = similar::TextDiff::from_lines(&help, &help_v).unified_diff().to_string(); + diff().expected_file("help-v.diff").actual_text("actual", &help_v_diff).run(); +} From 584c8200de3c83078d7cbb271a16ef4962be761e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 8 Nov 2024 12:20:51 +1100 Subject: [PATCH 18/54] Use a method to apply `RustcOptGroup` to `getopts::Options` --- compiler/rustc_driver_impl/src/lib.rs | 6 +++--- compiler/rustc_interface/src/tests.rs | 2 +- compiler/rustc_session/src/config.rs | 6 +++++- src/librustdoc/lib.rs | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index d2c4335cf2b..78ba841d89f 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -937,7 +937,7 @@ fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) { let groups = if verbose { config::rustc_optgroups() } else { config::rustc_short_optgroups() }; let mut options = getopts::Options::new(); for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) { - (option.apply)(&mut options); + option.apply(&mut options); } let message = "Usage: rustc [OPTIONS] INPUT"; let nightly_help = if nightly_build { @@ -1219,7 +1219,7 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option = match e { @@ -1233,7 +1233,7 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option(locations: I) -> ExternEntry fn optgroups() -> getopts::Options { let mut opts = getopts::Options::new(); for group in rustc_optgroups() { - (group.apply)(&mut opts); + group.apply(&mut opts); } return opts; } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fe05605c1b9..0c4827ef54d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1373,7 +1373,7 @@ enum OptionStability { } pub struct RustcOptGroup { - pub apply: Box &mut getopts::Options>, + apply: Box &mut getopts::Options>, pub name: &'static str, stability: OptionStability, } @@ -1383,6 +1383,10 @@ pub fn is_stable(&self) -> bool { self.stability == OptionStability::Stable } + pub fn apply(&self, options: &mut getopts::Options) { + (self.apply)(options); + } + pub fn stable(name: &'static str, f: F) -> RustcOptGroup where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 7c9dcd41e6a..40e649915cf 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -685,7 +685,7 @@ fn opts() -> Vec { fn usage(argv0: &str) { let mut options = getopts::Options::new(); for option in opts() { - (option.apply)(&mut options); + option.apply(&mut options); } println!("{}", options.usage(&format!("{argv0} [options] "))); println!(" @path Read newline separated options from `path`\n"); @@ -769,7 +769,7 @@ fn main_args( let mut options = getopts::Options::new(); for option in opts() { - (option.apply)(&mut options); + option.apply(&mut options); } let matches = match options.parse(&args) { Ok(m) => m, From 001013c63cccb3ca88b547596cec5b891e09151a Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 7 Nov 2024 22:47:15 +1100 Subject: [PATCH 19/54] Simplify command-line-option declarations in the compiler --- compiler/rustc_session/src/config.rs | 264 +++++++++++++++------------ 1 file changed, 147 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 0c4827ef54d..979db9424f3 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -12,7 +12,7 @@ use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; use std::sync::LazyLock; -use std::{fmt, fs, iter}; +use std::{cmp, fmt, fs, iter}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; @@ -1367,11 +1367,36 @@ pub fn build_target_config(early_dcx: &EarlyDiagCtxt, opts: &Options, sysroot: & } #[derive(Copy, Clone, PartialEq, Eq, Debug)] -enum OptionStability { +pub enum OptionStability { Stable, Unstable, } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum OptionKind { + /// An option that takes a value, and cannot appear more than once (e.g. `--out-dir`). + /// + /// Corresponds to [`getopts::Options::optopt`]. + Opt, + + /// An option that takes a value, and can appear multiple times (e.g. `--emit`). + /// + /// Corresponds to [`getopts::Options::optmulti`]. + Multi, + + /// An option that does not take a value, and cannot appear more than once (e.g. `--help`). + /// + /// Corresponds to [`getopts::Options::optflag`]. + /// The `hint` string must be empty. + Flag, + + /// An option that does not take a value, and can appear multiple times (e.g. `-O`). + /// + /// Corresponds to [`getopts::Options::optflagmulti`]. + /// The `hint` string must be empty. + FlagMulti, +} + pub struct RustcOptGroup { apply: Box &mut getopts::Options>, pub name: &'static str, @@ -1402,58 +1427,37 @@ pub fn unstable(name: &'static str, f: F) -> RustcOptGroup } } -// The `opt` local module holds wrappers around the `getopts` API that -// adds extra rustc-specific metadata to each option; such metadata -// is exposed by . The public -// functions below ending with `_u` are the functions that return -// *unstable* options, i.e., options that are only enabled when the -// user also passes the `-Z unstable-options` debugging flag. -mod opt { - // The `fn flag*` etc below are written so that we can use them - // in the future; do not warn about them not being used right now. - #![allow(dead_code)] - - use super::RustcOptGroup; - - type R = RustcOptGroup; - type S = &'static str; - - fn stable(name: S, f: F) -> R - where - F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, - { - RustcOptGroup::stable(name, f) - } - - fn unstable(name: S, f: F) -> R - where - F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, - { - RustcOptGroup::unstable(name, f) - } - - fn longer(a: S, b: S) -> S { - if a.len() > b.len() { a } else { b } - } - - pub(crate) fn opt_s(a: S, b: S, c: S, d: S) -> R { - stable(longer(a, b), move |opts| opts.optopt(a, b, c, d)) - } - pub(crate) fn multi_s(a: S, b: S, c: S, d: S) -> R { - stable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) - } - pub(crate) fn flag_s(a: S, b: S, c: S) -> R { - stable(longer(a, b), move |opts| opts.optflag(a, b, c)) - } - pub(crate) fn flagmulti_s(a: S, b: S, c: S) -> R { - stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) - } - - fn opt(a: S, b: S, c: S, d: S) -> R { - unstable(longer(a, b), move |opts| opts.optopt(a, b, c, d)) - } - pub(crate) fn multi(a: S, b: S, c: S, d: S) -> R { - unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) +pub fn make_opt( + stability: OptionStability, + kind: OptionKind, + short_name: &'static str, + long_name: &'static str, + desc: &'static str, + hint: &'static str, +) -> RustcOptGroup { + RustcOptGroup { + name: cmp::max_by_key(short_name, long_name, |s| s.len()), + stability, + apply: match kind { + OptionKind::Opt => Box::new(move |opts: &mut getopts::Options| { + opts.optopt(short_name, long_name, desc, hint) + }), + OptionKind::Multi => Box::new(move |opts: &mut getopts::Options| { + opts.optmulti(short_name, long_name, desc, hint) + }), + OptionKind::Flag => { + assert_eq!(hint, ""); + Box::new(move |opts: &mut getopts::Options| { + opts.optflag(short_name, long_name, desc) + }) + } + OptionKind::FlagMulti => { + assert_eq!(hint, ""); + Box::new(move |opts: &mut getopts::Options| { + opts.optflagmulti(short_name, long_name, desc) + }) + } + }, } } @@ -1468,46 +1472,60 @@ pub(crate) fn multi(a: S, b: S, c: S, d: S) -> R { /// including metadata for each option, such as whether the option is /// part of the stable long-term interface for rustc. pub fn rustc_short_optgroups() -> Vec { + use OptionKind::{Flag, FlagMulti, Multi, Opt}; + use OptionStability::Stable; + + use self::make_opt as opt; + vec![ - opt::flag_s("h", "help", "Display this message"), - opt::multi_s("", "cfg", "Configure the compilation environment. - SPEC supports the syntax `NAME[=\"VALUE\"]`.", "SPEC"), - opt::multi_s("", "check-cfg", "Provide list of expected cfgs for checking", "SPEC"), - opt::multi_s( + opt(Stable, Flag, "h", "help", "Display this message", ""), + opt( + Stable, + Multi, + "", + "cfg", + "Configure the compilation environment.\n\ + SPEC supports the syntax `NAME[=\"VALUE\"]`.", + "SPEC", + ), + opt(Stable, Multi, "", "check-cfg", "Provide list of expected cfgs for checking", "SPEC"), + opt( + Stable, + Multi, "L", "", - "Add a directory to the library search path. The - optional KIND can be one of dependency, crate, native, - framework, or all (the default).", + "Add a directory to the library search path. \ + The optional KIND can be one of dependency, crate, native, framework, or all (the default).", "[KIND=]PATH", ), - opt::multi_s( + opt( + Stable, + Multi, "l", "", - "Link the generated crate(s) to the specified native - library NAME. The optional KIND can be one of - static, framework, or dylib (the default). - Optional comma separated MODIFIERS (bundle|verbatim|whole-archive|as-needed) - may be specified each with a prefix of either '+' to - enable or '-' to disable.", + "Link the generated crate(s) to the specified native\n\ + library NAME. The optional KIND can be one of\n\ + static, framework, or dylib (the default).\n\ + Optional comma separated MODIFIERS\n\ + (bundle|verbatim|whole-archive|as-needed)\n\ + may be specified each with a prefix of either '+' to\n\ + enable or '-' to disable.", "[KIND[:MODIFIERS]=]NAME[:RENAME]", ), make_crate_type_option(), - opt::opt_s("", "crate-name", "Specify the name of the crate being built", "NAME"), - opt::opt_s( - "", - "edition", - &EDITION_STRING, - EDITION_NAME_LIST, - ), - opt::multi_s( + opt(Stable, Opt, "", "crate-name", "Specify the name of the crate being built", "NAME"), + opt(Stable, Opt, "", "edition", &EDITION_STRING, EDITION_NAME_LIST), + opt( + Stable, + Multi, "", "emit", - "Comma separated list of types of output for \ - the compiler to emit", + "Comma separated list of types of output for the compiler to emit", "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]", ), - opt::multi_s( + opt( + Stable, + Multi, "", "print", "Compiler information to print on stdout", @@ -1516,41 +1534,36 @@ pub fn rustc_short_optgroups() -> Vec { tls-models|target-spec-json|all-target-specs-json|native-static-libs|\ stack-protector-strategies|link-args|deployment-target]", ), - opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), - opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), - opt::opt_s("o", "", "Write output to ", "FILENAME"), - opt::opt_s( - "", - "out-dir", - "Write output to compiler-chosen filename \ - in ", - "DIR", - ), - opt::opt_s( + opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""), + opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=2", ""), + opt(Stable, Opt, "o", "", "Write output to ", "FILENAME"), + opt(Stable, Opt, "", "out-dir", "Write output to compiler-chosen filename in ", "DIR"), + opt( + Stable, + Opt, "", "explain", - "Provide a detailed explanation of an error \ - message", + "Provide a detailed explanation of an error message", "OPT", ), - opt::flag_s("", "test", "Build a test harness"), - opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"), - opt::multi_s("A", "allow", "Set lint allowed", "LINT"), - opt::multi_s("W", "warn", "Set lint warnings", "LINT"), - opt::multi_s("", "force-warn", "Set lint force-warn", "LINT"), - opt::multi_s("D", "deny", "Set lint denied", "LINT"), - opt::multi_s("F", "forbid", "Set lint forbidden", "LINT"), - opt::multi_s( + opt(Stable, Flag, "", "test", "Build a test harness", ""), + opt(Stable, Opt, "", "target", "Target triple for which the code is compiled", "TARGET"), + opt(Stable, Multi, "A", "allow", "Set lint allowed", "LINT"), + opt(Stable, Multi, "W", "warn", "Set lint warnings", "LINT"), + opt(Stable, Multi, "", "force-warn", "Set lint force-warn", "LINT"), + opt(Stable, Multi, "D", "deny", "Set lint denied", "LINT"), + opt(Stable, Multi, "F", "forbid", "Set lint forbidden", "LINT"), + opt( + Stable, + Multi, "", "cap-lints", - "Set the most restrictive lint level. \ - More restrictive lints are capped at this \ - level", + "Set the most restrictive lint level. More restrictive lints are capped at this level", "LEVEL", ), - opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"), - opt::flag_s("V", "version", "Print version info and exit"), - opt::flag_s("v", "verbose", "Use verbose output"), + opt(Stable, Multi, "C", "codegen", "Set a codegen option", "OPT[=VALUE]"), + opt(Stable, Flag, "V", "version", "Print version info and exit", ""), + opt(Stable, Flag, "v", "verbose", "Use verbose output", ""), ] } @@ -1558,25 +1571,36 @@ pub fn rustc_short_optgroups() -> Vec { /// each option, such as whether the option is part of the stable /// long-term interface for rustc. pub fn rustc_optgroups() -> Vec { + use OptionKind::{Multi, Opt}; + use OptionStability::{Stable, Unstable}; + + use self::make_opt as opt; + let mut opts = rustc_short_optgroups(); // FIXME: none of these descriptions are actually used opts.extend(vec![ - opt::multi_s( + opt( + Stable, + Multi, "", "extern", "Specify where an external rust library is located", "NAME[=PATH]", ), - opt::opt_s("", "sysroot", "Override the system root", "PATH"), - opt::multi("Z", "", "Set unstable / perma-unstable options", "FLAG"), - opt::opt_s( + opt(Stable, Opt, "", "sysroot", "Override the system root", "PATH"), + opt(Unstable, Multi, "Z", "", "Set unstable / perma-unstable options", "FLAG"), + opt( + Stable, + Opt, "", "error-format", "How errors and other messages are produced", "human|json|short", ), - opt::multi_s("", "json", "Configure the JSON output of the compiler", "CONFIG"), - opt::opt_s( + opt(Stable, Multi, "", "json", "Configure the JSON output of the compiler", "CONFIG"), + opt( + Stable, + Opt, "", "color", "Configure coloring of output: @@ -1585,19 +1609,23 @@ pub fn rustc_optgroups() -> Vec { never = never colorize output", "auto|always|never", ), - opt::opt_s( + opt( + Stable, + Opt, "", "diagnostic-width", "Inform rustc of the width of the output so that diagnostics can be truncated to fit", "WIDTH", ), - opt::multi_s( + opt( + Stable, + Multi, "", "remap-path-prefix", "Remap source names in all output (compiler messages and output files)", "FROM=TO", ), - opt::multi("", "env-set", "Inject an environment variable", "VAR=VALUE"), + opt(Unstable, Multi, "", "env-set", "Inject an environment variable", "VAR=VALUE"), ]); opts } @@ -2760,7 +2788,9 @@ fn parse_pretty(early_dcx: &EarlyDiagCtxt, unstable_opts: &UnstableOptions) -> O } pub fn make_crate_type_option() -> RustcOptGroup { - opt::multi_s( + make_opt( + OptionStability::Stable, + OptionKind::Multi, "", "crate-type", "Comma separated list of types of crates From b8377e58445fe5488664bcbbedd04a686cfdad03 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 7 Nov 2024 23:27:20 +1100 Subject: [PATCH 20/54] Simplify command-line-argument declarations in librustdoc --- compiler/rustc_session/src/config.rs | 14 - src/librustdoc/lib.rs | 921 ++++++++++++++------------- 2 files changed, 463 insertions(+), 472 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 979db9424f3..fa2403db925 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1411,20 +1411,6 @@ pub fn is_stable(&self) -> bool { pub fn apply(&self, options: &mut getopts::Options) { (self.apply)(options); } - - pub fn stable(name: &'static str, f: F) -> RustcOptGroup - where - F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, - { - RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Stable } - } - - pub fn unstable(name: &'static str, f: F) -> RustcOptGroup - where - F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, - { - RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Unstable } - } } pub fn make_opt( diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 40e649915cf..78dc0b8e2f9 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -215,470 +215,475 @@ fn init_logging(early_dcx: &EarlyDiagCtxt) { } fn opts() -> Vec { - let stable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::stable; - let unstable: fn(_, fn(&mut getopts::Options) -> &mut _) -> _ = RustcOptGroup::unstable; + use rustc_session::config::OptionKind::{Flag, FlagMulti, Multi, Opt}; + use rustc_session::config::OptionStability::{Stable, Unstable}; + use rustc_session::config::make_opt as opt; + vec![ - stable("h", |o| o.optflagmulti("h", "help", "show this help message")), - stable("V", |o| o.optflagmulti("V", "version", "print rustdoc's version")), - stable("v", |o| o.optflagmulti("v", "verbose", "use verbose output")), - stable("w", |o| o.optopt("w", "output-format", "the output type to write", "[html]")), - stable("output", |o| { - o.optopt( - "", - "output", - "Which directory to place the output. \ - This option is deprecated, use --out-dir instead.", - "PATH", - ) - }), - stable("o", |o| o.optopt("o", "out-dir", "which directory to place the output", "PATH")), - stable("crate-name", |o| { - o.optopt("", "crate-name", "specify the name of this crate", "NAME") - }), + opt(Stable, FlagMulti, "h", "help", "show this help message", ""), + opt(Stable, FlagMulti, "V", "version", "print rustdoc's version", ""), + opt(Stable, FlagMulti, "v", "verbose", "use verbose output", ""), + opt(Stable, Opt, "w", "output-format", "the output type to write", "[html]"), + opt( + Stable, + Opt, + "", + "output", + "Which directory to place the output. This option is deprecated, use --out-dir instead.", + "PATH", + ), + opt(Stable, Opt, "o", "out-dir", "which directory to place the output", "PATH"), + opt(Stable, Opt, "", "crate-name", "specify the name of this crate", "NAME"), make_crate_type_option(), - stable("L", |o| { - o.optmulti("L", "library-path", "directory to add to crate search path", "DIR") - }), - stable("cfg", |o| o.optmulti("", "cfg", "pass a --cfg to rustc", "")), - stable("check-cfg", |o| o.optmulti("", "check-cfg", "pass a --check-cfg to rustc", "")), - stable("extern", |o| o.optmulti("", "extern", "pass an --extern to rustc", "NAME[=PATH]")), - unstable("extern-html-root-url", |o| { - o.optmulti( - "", - "extern-html-root-url", - "base URL to use for dependencies; for example, \ - \"std=/doc\" links std::vec::Vec to /doc/std/vec/struct.Vec.html", - "NAME=URL", - ) - }), - unstable("extern-html-root-takes-precedence", |o| { - o.optflagmulti( - "", - "extern-html-root-takes-precedence", - "give precedence to `--extern-html-root-url`, not `html_root_url`", - ) - }), - stable("C", |o| { - o.optmulti("C", "codegen", "pass a codegen option to rustc", "OPT[=VALUE]") - }), - stable("document-private-items", |o| { - o.optflagmulti("", "document-private-items", "document private items") - }), - unstable("document-hidden-items", |o| { - o.optflagmulti("", "document-hidden-items", "document items that have doc(hidden)") - }), - stable("test", |o| o.optflagmulti("", "test", "run code examples as tests")), - stable("test-args", |o| { - o.optmulti("", "test-args", "arguments to pass to the test runner", "ARGS") - }), - stable("test-run-directory", |o| { - o.optopt( - "", - "test-run-directory", - "The working directory in which to run tests", - "PATH", - ) - }), - stable("target", |o| o.optopt("", "target", "target triple to document", "TRIPLE")), - stable("markdown-css", |o| { - o.optmulti( - "", - "markdown-css", - "CSS files to include via in a rendered Markdown file", - "FILES", - ) - }), - stable("html-in-header", |o| { - o.optmulti( - "", - "html-in-header", - "files to include inline in the section of a rendered Markdown file \ - or generated documentation", - "FILES", - ) - }), - stable("html-before-content", |o| { - o.optmulti( - "", - "html-before-content", - "files to include inline between and the content of a rendered \ - Markdown file or generated documentation", - "FILES", - ) - }), - stable("html-after-content", |o| { - o.optmulti( - "", - "html-after-content", - "files to include inline between the content and of a rendered \ - Markdown file or generated documentation", - "FILES", - ) - }), - unstable("markdown-before-content", |o| { - o.optmulti( - "", - "markdown-before-content", - "files to include inline between and the content of a rendered \ - Markdown file or generated documentation", - "FILES", - ) - }), - unstable("markdown-after-content", |o| { - o.optmulti( - "", - "markdown-after-content", - "files to include inline between the content and of a rendered \ - Markdown file or generated documentation", - "FILES", - ) - }), - stable("markdown-playground-url", |o| { - o.optopt("", "markdown-playground-url", "URL to send code snippets to", "URL") - }), - stable("markdown-no-toc", |o| { - o.optflagmulti("", "markdown-no-toc", "don't include table of contents") - }), - stable("e", |o| { - o.optopt( - "e", - "extend-css", - "To add some CSS rules with a given file to generate doc with your \ - own theme. However, your theme might break if the rustdoc's generated HTML \ - changes, so be careful!", - "PATH", - ) - }), - unstable("Z", |o| { - o.optmulti("Z", "", "unstable / perma-unstable options (only on nightly build)", "FLAG") - }), - stable("sysroot", |o| o.optopt("", "sysroot", "Override the system root", "PATH")), - unstable("playground-url", |o| { - o.optopt( - "", - "playground-url", - "URL to send code snippets to, may be reset by --markdown-playground-url \ - or `#![doc(html_playground_url=...)]`", - "URL", - ) - }), - unstable("display-doctest-warnings", |o| { - o.optflagmulti( - "", - "display-doctest-warnings", - "show warnings that originate in doctests", - ) - }), - stable("crate-version", |o| { - o.optopt("", "crate-version", "crate version to print into documentation", "VERSION") - }), - unstable("sort-modules-by-appearance", |o| { - o.optflagmulti( - "", - "sort-modules-by-appearance", - "sort modules by where they appear in the program, rather than alphabetically", - ) - }), - stable("default-theme", |o| { - o.optopt( - "", - "default-theme", - "Set the default theme. THEME should be the theme name, generally lowercase. \ - If an unknown default theme is specified, the builtin default is used. \ - The set of themes, and the rustdoc built-in default, are not stable.", - "THEME", - ) - }), - unstable("default-setting", |o| { - o.optmulti( - "", - "default-setting", - "Default value for a rustdoc setting (used when \"rustdoc-SETTING\" is absent \ - from web browser Local Storage). If VALUE is not supplied, \"true\" is used. \ - Supported SETTINGs and VALUEs are not documented and not stable.", - "SETTING[=VALUE]", - ) - }), - stable("theme", |o| { - o.optmulti( - "", - "theme", - "additional themes which will be added to the generated docs", - "FILES", - ) - }), - stable("check-theme", |o| { - o.optmulti("", "check-theme", "check if given theme is valid", "FILES") - }), - unstable("resource-suffix", |o| { - o.optopt( - "", - "resource-suffix", - "suffix to add to CSS and JavaScript files, e.g., \"search-index.js\" will \ - become \"search-index-suffix.js\"", - "PATH", - ) - }), - stable("edition", |o| { - o.optopt( - "", - "edition", - "edition to use when compiling rust code (default: 2015)", - "EDITION", - ) - }), - stable("color", |o| { - o.optopt( - "", - "color", - "Configure coloring of output: + opt(Stable, Multi, "L", "library-path", "directory to add to crate search path", "DIR"), + opt(Stable, Multi, "", "cfg", "pass a --cfg to rustc", ""), + opt(Stable, Multi, "", "check-cfg", "pass a --check-cfg to rustc", ""), + opt(Stable, Multi, "", "extern", "pass an --extern to rustc", "NAME[=PATH]"), + opt( + Unstable, + Multi, + "", + "extern-html-root-url", + "base URL to use for dependencies; for example, \ + \"std=/doc\" links std::vec::Vec to /doc/std/vec/struct.Vec.html", + "NAME=URL", + ), + opt( + Unstable, + FlagMulti, + "", + "extern-html-root-takes-precedence", + "give precedence to `--extern-html-root-url`, not `html_root_url`", + "", + ), + opt(Stable, Multi, "C", "codegen", "pass a codegen option to rustc", "OPT[=VALUE]"), + opt(Stable, FlagMulti, "", "document-private-items", "document private items", ""), + opt( + Unstable, + FlagMulti, + "", + "document-hidden-items", + "document items that have doc(hidden)", + "", + ), + opt(Stable, FlagMulti, "", "test", "run code examples as tests", ""), + opt(Stable, Multi, "", "test-args", "arguments to pass to the test runner", "ARGS"), + opt( + Stable, + Opt, + "", + "test-run-directory", + "The working directory in which to run tests", + "PATH", + ), + opt(Stable, Opt, "", "target", "target triple to document", "TRIPLE"), + opt( + Stable, + Multi, + "", + "markdown-css", + "CSS files to include via in a rendered Markdown file", + "FILES", + ), + opt( + Stable, + Multi, + "", + "html-in-header", + "files to include inline in the section of a rendered Markdown file \ + or generated documentation", + "FILES", + ), + opt( + Stable, + Multi, + "", + "html-before-content", + "files to include inline between and the content of a rendered \ + Markdown file or generated documentation", + "FILES", + ), + opt( + Stable, + Multi, + "", + "html-after-content", + "files to include inline between the content and of a rendered \ + Markdown file or generated documentation", + "FILES", + ), + opt( + Unstable, + Multi, + "", + "markdown-before-content", + "files to include inline between and the content of a rendered \ + Markdown file or generated documentation", + "FILES", + ), + opt( + Unstable, + Multi, + "", + "markdown-after-content", + "files to include inline between the content and of a rendered \ + Markdown file or generated documentation", + "FILES", + ), + opt(Stable, Opt, "", "markdown-playground-url", "URL to send code snippets to", "URL"), + opt(Stable, FlagMulti, "", "markdown-no-toc", "don't include table of contents", ""), + opt( + Stable, + Opt, + "e", + "extend-css", + "To add some CSS rules with a given file to generate doc with your own theme. \ + However, your theme might break if the rustdoc's generated HTML changes, so be careful!", + "PATH", + ), + opt( + Unstable, + Multi, + "Z", + "", + "unstable / perma-unstable options (only on nightly build)", + "FLAG", + ), + opt(Stable, Opt, "", "sysroot", "Override the system root", "PATH"), + opt( + Unstable, + Opt, + "", + "playground-url", + "URL to send code snippets to, may be reset by --markdown-playground-url \ + or `#![doc(html_playground_url=...)]`", + "URL", + ), + opt( + Unstable, + FlagMulti, + "", + "display-doctest-warnings", + "show warnings that originate in doctests", + "", + ), + opt( + Stable, + Opt, + "", + "crate-version", + "crate version to print into documentation", + "VERSION", + ), + opt( + Unstable, + FlagMulti, + "", + "sort-modules-by-appearance", + "sort modules by where they appear in the program, rather than alphabetically", + "", + ), + opt( + Stable, + Opt, + "", + "default-theme", + "Set the default theme. THEME should be the theme name, generally lowercase. \ + If an unknown default theme is specified, the builtin default is used. \ + The set of themes, and the rustdoc built-in default, are not stable.", + "THEME", + ), + opt( + Unstable, + Multi, + "", + "default-setting", + "Default value for a rustdoc setting (used when \"rustdoc-SETTING\" is absent \ + from web browser Local Storage). If VALUE is not supplied, \"true\" is used. \ + Supported SETTINGs and VALUEs are not documented and not stable.", + "SETTING[=VALUE]", + ), + opt( + Stable, + Multi, + "", + "theme", + "additional themes which will be added to the generated docs", + "FILES", + ), + opt(Stable, Multi, "", "check-theme", "check if given theme is valid", "FILES"), + opt( + Unstable, + Opt, + "", + "resource-suffix", + "suffix to add to CSS and JavaScript files, \ + e.g., \"search-index.js\" will become \"search-index-suffix.js\"", + "PATH", + ), + opt( + Stable, + Opt, + "", + "edition", + "edition to use when compiling rust code (default: 2015)", + "EDITION", + ), + opt( + Stable, + Opt, + "", + "color", + "Configure coloring of output: auto = colorize, if output goes to a tty (default); always = always colorize output; never = never colorize output", - "auto|always|never", - ) - }), - stable("error-format", |o| { - o.optopt( - "", - "error-format", - "How errors and other messages are produced", - "human|json|short", - ) - }), - stable("diagnostic-width", |o| { - o.optopt( - "", - "diagnostic-width", - "Provide width of the output for truncated error messages", - "WIDTH", - ) - }), - stable("json", |o| { - o.optopt("", "json", "Configure the structure of JSON diagnostics", "CONFIG") - }), - stable("allow", |o| o.optmulti("A", "allow", "Set lint allowed", "LINT")), - stable("warn", |o| o.optmulti("W", "warn", "Set lint warnings", "LINT")), - stable("force-warn", |o| o.optmulti("", "force-warn", "Set lint force-warn", "LINT")), - stable("deny", |o| o.optmulti("D", "deny", "Set lint denied", "LINT")), - stable("forbid", |o| o.optmulti("F", "forbid", "Set lint forbidden", "LINT")), - stable("cap-lints", |o| { - o.optmulti( - "", - "cap-lints", - "Set the most restrictive lint level. \ - More restrictive lints are capped at this \ - level. By default, it is at `forbid` level.", - "LEVEL", - ) - }), - unstable("index-page", |o| { - o.optopt("", "index-page", "Markdown file to be used as index page", "PATH") - }), - unstable("enable-index-page", |o| { - o.optflagmulti("", "enable-index-page", "To enable generation of the index page") - }), - unstable("static-root-path", |o| { - o.optopt( - "", - "static-root-path", - "Path string to force loading static files from in output pages. \ - If not set, uses combinations of '../' to reach the documentation root.", - "PATH", - ) - }), - unstable("persist-doctests", |o| { - o.optopt( - "", - "persist-doctests", - "Directory to persist doctest executables into", - "PATH", - ) - }), - unstable("show-coverage", |o| { - o.optflagmulti( - "", - "show-coverage", - "calculate percentage of public items with documentation", - ) - }), - unstable("enable-per-target-ignores", |o| { - o.optflagmulti( - "", - "enable-per-target-ignores", - "parse ignore-foo for ignoring doctests on a per-target basis", - ) - }), - unstable("runtool", |o| { - o.optopt( - "", - "runtool", - "", - "The tool to run tests with when building for a different target than host", - ) - }), - unstable("runtool-arg", |o| { - o.optmulti( - "", - "runtool-arg", - "", - "One (of possibly many) arguments to pass to the runtool", - ) - }), - unstable("test-builder", |o| { - o.optopt("", "test-builder", "The rustc-like binary to use as the test builder", "PATH") - }), - unstable("test-builder-wrapper", |o| { - o.optmulti( - "", - "test-builder-wrapper", - "Wrapper program to pass test-builder and arguments", - "PATH", - ) - }), - unstable("check", |o| o.optflagmulti("", "check", "Run rustdoc checks")), - unstable("generate-redirect-map", |o| { - o.optflagmulti( - "", - "generate-redirect-map", - "Generate JSON file at the top level instead of generating HTML redirection files", - ) - }), - unstable("emit", |o| { - o.optmulti( - "", - "emit", - "Comma separated list of types of output for rustdoc to emit", - "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]", - ) - }), - unstable("no-run", |o| { - o.optflagmulti("", "no-run", "Compile doctests without running them") - }), - unstable("remap-path-prefix", |o| { - o.optmulti( - "", - "remap-path-prefix", - "Remap source names in compiler messages", - "FROM=TO", - ) - }), - unstable("show-type-layout", |o| { - o.optflagmulti("", "show-type-layout", "Include the memory layout of types in the docs") - }), - unstable("nocapture", |o| { - o.optflag("", "nocapture", "Don't capture stdout and stderr of tests") - }), - unstable("generate-link-to-definition", |o| { - o.optflag( - "", - "generate-link-to-definition", - "Make the identifiers in the HTML source code pages navigable", - ) - }), - unstable("scrape-examples-output-path", |o| { - o.optopt( - "", - "scrape-examples-output-path", - "", - "collect function call information and output at the given path", - ) - }), - unstable("scrape-examples-target-crate", |o| { - o.optmulti( - "", - "scrape-examples-target-crate", - "", - "collect function call information for functions from the target crate", - ) - }), - unstable("scrape-tests", |o| { - o.optflag("", "scrape-tests", "Include test code when scraping examples") - }), - unstable("with-examples", |o| { - o.optmulti( - "", - "with-examples", - "", - "path to function call information (for displaying examples in the documentation)", - ) - }), - unstable("merge", |o| { - o.optopt( - "", - "merge", - "Controls how rustdoc handles files from previously documented crates in the doc root - none = Do not write cross-crate information to the --out-dir - shared = Append current crate's info to files found in the --out-dir - finalize = Write current crate's info and --include-parts-dir info to the --out-dir, overwriting conflicting files", - "none|shared|finalize", - ) - }), - unstable("parts-out-dir", |o| { - o.optopt( - "", - "parts-out-dir", - "Writes trait implementations and other info for the current crate to provided path. Only use with --merge=none", - "path/to/doc.parts/", - ) - }), - unstable("include-parts-dir", |o| { - o.optmulti( - "", - "include-parts-dir", - "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize", - "path/to/doc.parts/", - ) - }), + "auto|always|never", + ), + opt( + Stable, + Opt, + "", + "error-format", + "How errors and other messages are produced", + "human|json|short", + ), + opt( + Stable, + Opt, + "", + "diagnostic-width", + "Provide width of the output for truncated error messages", + "WIDTH", + ), + opt(Stable, Opt, "", "json", "Configure the structure of JSON diagnostics", "CONFIG"), + opt(Stable, Multi, "A", "allow", "Set lint allowed", "LINT"), + opt(Stable, Multi, "W", "warn", "Set lint warnings", "LINT"), + opt(Stable, Multi, "", "force-warn", "Set lint force-warn", "LINT"), + opt(Stable, Multi, "D", "deny", "Set lint denied", "LINT"), + opt(Stable, Multi, "F", "forbid", "Set lint forbidden", "LINT"), + opt( + Stable, + Multi, + "", + "cap-lints", + "Set the most restrictive lint level. \ + More restrictive lints are capped at this level. \ + By default, it is at `forbid` level.", + "LEVEL", + ), + opt(Unstable, Opt, "", "index-page", "Markdown file to be used as index page", "PATH"), + opt( + Unstable, + FlagMulti, + "", + "enable-index-page", + "To enable generation of the index page", + "", + ), + opt( + Unstable, + Opt, + "", + "static-root-path", + "Path string to force loading static files from in output pages. \ + If not set, uses combinations of '../' to reach the documentation root.", + "PATH", + ), + opt( + Unstable, + Opt, + "", + "persist-doctests", + "Directory to persist doctest executables into", + "PATH", + ), + opt( + Unstable, + FlagMulti, + "", + "show-coverage", + "calculate percentage of public items with documentation", + "", + ), + opt( + Unstable, + FlagMulti, + "", + "enable-per-target-ignores", + "parse ignore-foo for ignoring doctests on a per-target basis", + "", + ), + opt( + Unstable, + Opt, + "", + "runtool", + "", + "The tool to run tests with when building for a different target than host", + ), + opt( + Unstable, + Multi, + "", + "runtool-arg", + "", + "One (of possibly many) arguments to pass to the runtool", + ), + opt( + Unstable, + Opt, + "", + "test-builder", + "The rustc-like binary to use as the test builder", + "PATH", + ), + opt( + Unstable, + Multi, + "", + "test-builder-wrapper", + "Wrapper program to pass test-builder and arguments", + "PATH", + ), + opt(Unstable, FlagMulti, "", "check", "Run rustdoc checks", ""), + opt( + Unstable, + FlagMulti, + "", + "generate-redirect-map", + "Generate JSON file at the top level instead of generating HTML redirection files", + "", + ), + opt( + Unstable, + Multi, + "", + "emit", + "Comma separated list of types of output for rustdoc to emit", + "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]", + ), + opt(Unstable, FlagMulti, "", "no-run", "Compile doctests without running them", ""), + opt( + Unstable, + Multi, + "", + "remap-path-prefix", + "Remap source names in compiler messages", + "FROM=TO", + ), + opt( + Unstable, + FlagMulti, + "", + "show-type-layout", + "Include the memory layout of types in the docs", + "", + ), + opt(Unstable, Flag, "", "nocapture", "Don't capture stdout and stderr of tests", ""), + opt( + Unstable, + Flag, + "", + "generate-link-to-definition", + "Make the identifiers in the HTML source code pages navigable", + "", + ), + opt( + Unstable, + Opt, + "", + "scrape-examples-output-path", + "", + "collect function call information and output at the given path", + ), + opt( + Unstable, + Multi, + "", + "scrape-examples-target-crate", + "", + "collect function call information for functions from the target crate", + ), + opt(Unstable, Flag, "", "scrape-tests", "Include test code when scraping examples", ""), + opt( + Unstable, + Multi, + "", + "with-examples", + "", + "path to function call information (for displaying examples in the documentation)", + ), + opt( + Unstable, + Opt, + "", + "merge", + "Controls how rustdoc handles files from previously documented crates in the doc root\n\ + none = Do not write cross-crate information to the --out-dir\n\ + shared = Append current crate's info to files found in the --out-dir\n\ + finalize = Write current crate's info and --include-parts-dir info to the --out-dir, overwriting conflicting files", + "none|shared|finalize", + ), + opt( + Unstable, + Opt, + "", + "parts-out-dir", + "Writes trait implementations and other info for the current crate to provided path. Only use with --merge=none", + "path/to/doc.parts/", + ), + opt( + Unstable, + Multi, + "", + "include-parts-dir", + "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize", + "path/to/doc.parts/", + ), // deprecated / removed options - unstable("disable-minification", |o| o.optflagmulti("", "disable-minification", "removed")), - stable("plugin-path", |o| { - o.optmulti( - "", - "plugin-path", - "removed, see issue #44136 \ - for more information", - "DIR", - ) - }), - stable("passes", |o| { - o.optmulti( - "", - "passes", - "removed, see issue #44136 \ - for more information", - "PASSES", - ) - }), - stable("plugins", |o| { - o.optmulti( - "", - "plugins", - "removed, see issue #44136 \ - for more information", - "PLUGINS", - ) - }), - stable("no-default", |o| { - o.optflagmulti( - "", - "no-defaults", - "removed, see issue #44136 \ - for more information", - ) - }), - stable("r", |o| { - o.optopt( - "r", - "input-format", - "removed, see issue #44136 \ - for more information", - "[rust]", - ) - }), - unstable("html-no-source", |o| { - o.optflag("", "html-no-source", "Disable HTML source code pages generation") - }), + opt(Unstable, FlagMulti, "", "disable-minification", "removed", ""), + opt( + Stable, + Multi, + "", + "plugin-path", + "removed, see issue #44136 for more information", + "DIR", + ), + opt( + Stable, + Multi, + "", + "passes", + "removed, see issue #44136 for more information", + "PASSES", + ), + opt( + Stable, + Multi, + "", + "plugins", + "removed, see issue #44136 for more information", + "PLUGINS", + ), + opt( + Stable, + FlagMulti, + "", + "no-defaults", + "removed, see issue #44136 for more information", + "", + ), + opt( + Stable, + Opt, + "r", + "input-format", + "removed, see issue #44136 for more information", + "[rust]", + ), + opt(Unstable, Flag, "", "html-no-source", "Disable HTML source code pages generation", ""), ] } From e4c1a0016c0bd1b6579123c785e38e63b4ccf143 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Nov 2024 03:46:23 +0000 Subject: [PATCH 21/54] Get rid of check_opaque_type_well_formed --- .../src/region_infer/opaque_types.rs | 90 +------------ .../rustc_hir_analysis/src/check/check.rs | 122 +++++++++++++++--- .../async-await/issue-70935-complex-spans.rs | 2 +- .../issue-70935-complex-spans.stderr | 16 ++- tests/ui/pattern/usefulness/impl-trait.stderr | 56 ++++---- .../closure_wf_outlives.rs | 6 +- .../closure_wf_outlives.stderr | 38 +++--- .../generic_duplicate_param_use3.rs | 3 +- .../generic_duplicate_param_use3.stderr | 29 ++--- .../generic_duplicate_param_use5.rs | 5 +- .../generic_duplicate_param_use5.stderr | 55 ++------ .../generic_duplicate_param_use6.rs | 4 +- .../generic_duplicate_param_use6.stderr | 43 ++---- .../generic_duplicate_param_use8.rs | 3 +- .../generic_duplicate_param_use8.stderr | 31 ++--- .../generic_duplicate_param_use9.rs | 6 +- .../generic_duplicate_param_use9.stderr | 64 ++------- .../implied_lifetime_wf_check4_static.rs | 2 +- .../implied_lifetime_wf_check4_static.stderr | 12 +- .../not_a_defining_use.rs | 4 +- .../not_a_defining_use.stderr | 42 ++---- .../underconstrained_lifetime.rs | 2 +- .../underconstrained_lifetime.stderr | 6 +- .../wf-in-associated-type.fail.stderr | 14 +- .../wf-in-associated-type.rs | 4 +- 25 files changed, 247 insertions(+), 412 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index f9dd649ab9f..d676ce59cfe 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -1,10 +1,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; -use rustc_hir::OpaqueTyOrigin; -use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, TyCtxtInferExt as _}; -use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_macros::extension; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ @@ -12,7 +9,6 @@ TypingMode, }; use rustc_span::Span; -use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::ObligationCtxt; use tracing::{debug, instrument}; @@ -303,91 +299,7 @@ fn infer_opaque_definition_from_instantiation( return Ty::new_error(self.tcx, e); } - // `definition_ty` does not live in of the current inference context, - // so lets make sure that we don't accidentally misuse our current `infcx`. - match check_opaque_type_well_formed( - self.tcx, - self.next_trait_solver(), - opaque_type_key.def_id, - instantiated_ty.span, - definition_ty, - ) { - Ok(hidden_ty) => hidden_ty, - Err(guar) => Ty::new_error(self.tcx, guar), - } - } -} - -/// This logic duplicates most of `check_opaque_meets_bounds`. -/// FIXME(oli-obk): Also do region checks here and then consider removing -/// `check_opaque_meets_bounds` entirely. -fn check_opaque_type_well_formed<'tcx>( - tcx: TyCtxt<'tcx>, - next_trait_solver: bool, - def_id: LocalDefId, - definition_span: Span, - definition_ty: Ty<'tcx>, -) -> Result, ErrorGuaranteed> { - // Only check this for TAIT. RPIT already supports `tests/ui/impl-trait/nested-return-type2.rs` - // on stable and we'd break that. - let opaque_ty_hir = tcx.hir().expect_opaque_ty(def_id); - let OpaqueTyOrigin::TyAlias { .. } = opaque_ty_hir.origin else { - return Ok(definition_ty); - }; - let param_env = tcx.param_env(def_id); - - let mut parent_def_id = def_id; - while tcx.def_kind(parent_def_id) == DefKind::OpaqueTy { - parent_def_id = tcx.local_parent(parent_def_id); - } - - // FIXME(#132279): This should eventually use the already defined hidden types - // instead. Alternatively we'll entirely remove this function given we also check - // the opaque in `check_opaque_meets_bounds` later. - let infcx = tcx - .infer_ctxt() - .with_next_trait_solver(next_trait_solver) - .build(TypingMode::analysis_in_body(tcx, parent_def_id)); - let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - let identity_args = GenericArgs::identity_for_item(tcx, def_id); - - // Require that the hidden type actually fulfills all the bounds of the opaque type, even without - // the bounds that the function supplies. - let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args); - ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty) - .map_err(|err| { - infcx - .err_ctxt() - .report_mismatched_types( - &ObligationCause::misc(definition_span, def_id), - param_env, - opaque_ty, - definition_ty, - err, - ) - .emit() - })?; - - // Require the hidden type to be well-formed with only the generics of the opaque type. - // Defining use functions may have more bounds than the opaque type, which is ok, as long as the - // hidden type is well formed even without those bounds. - let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( - definition_ty.into(), - ))); - ocx.register_obligation(Obligation::misc(tcx, definition_span, def_id, param_env, predicate)); - - // Check that all obligations are satisfied by the implementation's - // version. - let errors = ocx.select_all_or_error(); - - // This is fishy, but we check it again in `check_opaque_meets_bounds`. - // Remove once we can prepopulate with known hidden types. - let _ = infcx.take_opaque_types(); - - if errors.is_empty() { - Ok(definition_ty) - } else { - Err(infcx.err_ctxt().report_fulfillment_errors(errors)) + definition_ty } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 50ea8018e76..12b842e70b7 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -5,13 +5,14 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::MultiSpan; use rustc_errors::codes::*; -use rustc_hir::Node; use rustc_hir::def::{CtorKind, DefKind}; +use rustc_hir::{Node, intravisit}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; use rustc_lint_defs::builtin::{ REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, }; +use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; @@ -190,7 +191,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo` /// projections that would result in "inheriting lifetimes". fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) { - let hir::OpaqueTy { origin, .. } = tcx.hir().expect_opaque_ty(def_id); + let hir::OpaqueTy { origin, .. } = *tcx.hir().expect_opaque_ty(def_id); // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting // `async-std` (and `pub async fn` in general). @@ -200,23 +201,20 @@ fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) { return; } - let span = tcx.def_span(def_id); - if tcx.type_of(def_id).instantiate_identity().references_error() { return; } - if check_opaque_for_cycles(tcx, def_id, span).is_err() { + if check_opaque_for_cycles(tcx, def_id).is_err() { return; } - let _ = check_opaque_meets_bounds(tcx, def_id, span, origin); + let _ = check_opaque_meets_bounds(tcx, def_id, origin); } /// Checks that an opaque type does not contain cycles. pub(super) fn check_opaque_for_cycles<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, - span: Span, ) -> Result<(), ErrorGuaranteed> { let args = GenericArgs::identity_for_item(tcx, def_id); @@ -233,7 +231,7 @@ pub(super) fn check_opaque_for_cycles<'tcx>( .try_expand_impl_trait_type(def_id.to_def_id(), args, InspectCoroutineFields::No) .is_err() { - let reported = opaque_type_cycle_error(tcx, def_id, span); + let reported = opaque_type_cycle_error(tcx, def_id); return Err(reported); } @@ -267,10 +265,11 @@ pub(super) fn check_opaque_for_cycles<'tcx>( fn check_opaque_meets_bounds<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, - span: Span, - origin: &hir::OpaqueTyOrigin, + origin: hir::OpaqueTyOrigin, ) -> Result<(), ErrorGuaranteed> { - let defining_use_anchor = match *origin { + let span = span_of_opaque(tcx, def_id, origin).unwrap_or_else(|| tcx.def_span(def_id)); + + let defining_use_anchor = match origin { hir::OpaqueTyOrigin::FnReturn { parent, .. } | hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent, @@ -281,7 +280,7 @@ fn check_opaque_meets_bounds<'tcx>( let infcx = tcx.infer_ctxt().build(TypingMode::analysis_in_body(tcx, defining_use_anchor)); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - let args = match *origin { + let args = match origin { hir::OpaqueTyOrigin::FnReturn { parent, .. } | hir::OpaqueTyOrigin::AsyncFn { parent, .. } | hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item( @@ -308,6 +307,7 @@ fn check_opaque_meets_bounds<'tcx>( let misc_cause = traits::ObligationCause::misc(span, def_id); + // FIXME: We should just register the item bounds here, rather than equating. match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) { Ok(()) => {} Err(ty_err) => { @@ -364,6 +364,97 @@ fn check_opaque_meets_bounds<'tcx>( } } +fn span_of_opaque<'tcx>( + tcx: TyCtxt<'tcx>, + opaque_def_id: LocalDefId, + origin: hir::OpaqueTyOrigin, +) -> Option { + struct TaitConstraintLocator<'tcx> { + opaque_def_id: LocalDefId, + tcx: TyCtxt<'tcx>, + } + impl<'tcx> TaitConstraintLocator<'tcx> { + fn check(&self, item_def_id: LocalDefId) -> ControlFlow { + if !self.tcx.has_typeck_results(item_def_id) { + return ControlFlow::Continue(()); + } + + if let Some(hidden_ty) = + self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id) + { + ControlFlow::Break(hidden_ty.span) + } else { + ControlFlow::Continue(()) + } + } + } + impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { + type NestedFilter = nested_filter::All; + type Result = ControlFlow; + fn nested_visit_map(&mut self) -> Self::Map { + self.tcx.hir() + } + fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result { + if let hir::ExprKind::Closure(closure) = ex.kind { + self.check(closure.def_id)?; + } + intravisit::walk_expr(self, ex) + } + fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) -> Self::Result { + self.check(it.owner_id.def_id)?; + intravisit::walk_item(self, it) + } + fn visit_impl_item(&mut self, it: &'tcx hir::ImplItem<'tcx>) -> Self::Result { + self.check(it.owner_id.def_id)?; + intravisit::walk_impl_item(self, it) + } + fn visit_trait_item(&mut self, it: &'tcx hir::TraitItem<'tcx>) -> Self::Result { + self.check(it.owner_id.def_id)?; + intravisit::walk_trait_item(self, it) + } + fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) -> Self::Result { + intravisit::walk_foreign_item(self, it) + } + } + + let mut locator = TaitConstraintLocator { tcx, opaque_def_id }; + match origin { + hir::OpaqueTyOrigin::FnReturn { parent, .. } + | hir::OpaqueTyOrigin::AsyncFn { parent, .. } => locator.check(parent).break_value(), + hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty: true } => { + let impl_def_id = tcx.local_parent(parent); + for assoc in tcx.associated_items(impl_def_id).in_definition_order() { + match assoc.kind { + ty::AssocKind::Const | ty::AssocKind::Fn => { + if let ControlFlow::Break(span) = locator.check(assoc.def_id.expect_local()) + { + return Some(span); + } + } + ty::AssocKind::Type => {} + } + } + + None + } + hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => { + let scope = tcx.hir().get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id)); + let found = if scope == hir::CRATE_HIR_ID { + tcx.hir().walk_toplevel_module(&mut locator) + } else { + match tcx.hir_node(scope) { + Node::Item(it) => locator.visit_item(it), + Node::ImplItem(it) => locator.visit_impl_item(it), + Node::TraitItem(it) => locator.visit_trait_item(it), + Node::ForeignItem(it) => locator.visit_foreign_item(it), + other => bug!("{:?} is not a valid scope for an opaque type item", other), + } + }; + found.break_value() + } + } +} + fn sanity_check_found_hidden_type<'tcx>( tcx: TyCtxt<'tcx>, key: ty::OpaqueTypeKey<'tcx>, @@ -1535,11 +1626,8 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD /// /// If all the return expressions evaluate to `!`, then we explain that the error will go away /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder. -fn opaque_type_cycle_error( - tcx: TyCtxt<'_>, - opaque_def_id: LocalDefId, - span: Span, -) -> ErrorGuaranteed { +fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorGuaranteed { + let span = tcx.def_span(opaque_def_id); let mut err = struct_span_code_err!(tcx.dcx(), span, E0720, "cannot resolve opaque type"); let mut label = false; diff --git a/tests/ui/async-await/issue-70935-complex-spans.rs b/tests/ui/async-await/issue-70935-complex-spans.rs index a74bd9890ca..2851637ae78 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.rs +++ b/tests/ui/async-await/issue-70935-complex-spans.rs @@ -14,8 +14,8 @@ async fn baz(_c: impl FnMut() -> T) where T: Future { fn foo(x: NotSync) -> impl Future + Send { //~^ ERROR `*mut ()` cannot be shared between threads safely - //~| ERROR `*mut ()` cannot be shared between threads safely async move { + //~^ ERROR `*mut ()` cannot be shared between threads safely baz(|| async { foo(x.clone()); }).await; diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index c6b7e21b9dd..777eefe897b 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -1,8 +1,13 @@ error[E0277]: `*mut ()` cannot be shared between threads safely - --> $DIR/issue-70935-complex-spans.rs:15:23 + --> $DIR/issue-70935-complex-spans.rs:17:5 | -LL | fn foo(x: NotSync) -> impl Future + Send { - | ^^^^^^^^^^^^^^^^^^ `*mut ()` cannot be shared between threads safely +LL | / async move { +LL | | +LL | | baz(|| async { +LL | | foo(x.clone()); +LL | | }).await; +LL | | } + | |_____^ `*mut ()` cannot be shared between threads safely | = help: within `NotSync`, the trait `Sync` is not implemented for `*mut ()` note: required because it appears within the type `PhantomData<*mut ()>` @@ -26,7 +31,7 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { LL | | } | |_^ note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:18:5 + --> $DIR/issue-70935-complex-spans.rs:17:5 | LL | async move { | ^^^^^^^^^^ @@ -59,11 +64,10 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { LL | | } | |_^ note: required because it's used within this `async` block - --> $DIR/issue-70935-complex-spans.rs:18:5 + --> $DIR/issue-70935-complex-spans.rs:17:5 | LL | async move { | ^^^^^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr index 75cba4b5f02..34f8eb1e163 100644 --- a/tests/ui/pattern/usefulness/impl-trait.stderr +++ b/tests/ui/pattern/usefulness/impl-trait.stderr @@ -25,6 +25,20 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types +error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty + --> $DIR/impl-trait.rs:23:11 + | +LL | match return_never_rpit(x) {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `impl Copy` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match return_never_rpit(x) { +LL + _ => todo!(), +LL + } + | + error: unreachable pattern --> $DIR/impl-trait.rs:45:13 | @@ -93,6 +107,20 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types +error[E0004]: non-exhaustive patterns: type `T` is non-empty + --> $DIR/impl-trait.rs:37:11 + | +LL | match return_never_tait(x) {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: the matched value is of type `T` +help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown + | +LL ~ match return_never_tait(x) { +LL + _ => todo!(), +LL + } + | + error: unreachable pattern --> $DIR/impl-trait.rs:105:9 | @@ -131,34 +159,6 @@ LL | _ => {} | = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types -error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty - --> $DIR/impl-trait.rs:23:11 - | -LL | match return_never_rpit(x) {} - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: the matched value is of type `impl Copy` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match return_never_rpit(x) { -LL + _ => todo!(), -LL + } - | - -error[E0004]: non-exhaustive patterns: type `T` is non-empty - --> $DIR/impl-trait.rs:37:11 - | -LL | match return_never_tait(x) {} - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: the matched value is of type `T` -help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown - | -LL ~ match return_never_tait(x) { -LL + _ => todo!(), -LL + } - | - error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs index 430b444aae1..caa9b6d979a 100644 --- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs +++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs @@ -12,20 +12,19 @@ // requires `'a: 'b` bound mod test1 { type Opaque<'a, 'b> = impl Sized + 'a + 'b; - //~^ ERROR lifetime bound not satisfied fn define<'a, 'b>() -> Opaque<'a, 'b> where 'a: 'b, { || {} + //~^ ERROR lifetime bound not satisfied } } // Same as the above but through indirection `'x` mod test2 { type Opaque<'a, 'b> = impl Sized + 'a + 'b; - //~^ ERROR cannot infer an appropriate lifetime fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> where @@ -33,6 +32,7 @@ fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> 'x: 'b, { || {} + //~^ ERROR cannot infer an appropriate lifetime } } @@ -52,13 +52,13 @@ fn define<'a, 'b, 'x>() -> Opaque<'a, 'b> // requires `T: 'static` mod test3 { type Opaque = impl Sized; - //~^ ERROR the parameter type `T` may not live long enough fn define() -> Opaque where T: 'static, { || {} + //~^ ERROR the parameter type `T` may not live long enough } } diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr index 3484485e3fd..04288112fa8 100644 --- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr +++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr @@ -1,8 +1,8 @@ error[E0478]: lifetime bound not satisfied - --> $DIR/closure_wf_outlives.rs:14:27 + --> $DIR/closure_wf_outlives.rs:20:9 | -LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; - | ^^^^^^^^^^^^^^^^^^^^ +LL | || {} + | ^^^^^ | note: lifetime parameter instantiated with the lifetime `'a` as defined here --> $DIR/closure_wf_outlives.rs:14:17 @@ -16,10 +16,10 @@ LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; | ^^ error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/closure_wf_outlives.rs:27:27 + --> $DIR/closure_wf_outlives.rs:34:9 | -LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; - | ^^^^^^^^^^^^^^^^^^^^ +LL | || {} + | ^^^^^ | note: first, the lifetime cannot outlive the lifetime `'a` as defined here... --> $DIR/closure_wf_outlives.rs:27:17 @@ -27,32 +27,32 @@ note: first, the lifetime cannot outlive the lifetime `'a` as defined here... LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; | ^^ note: ...so that the declared lifetime parameter bounds are satisfied - --> $DIR/closure_wf_outlives.rs:27:27 + --> $DIR/closure_wf_outlives.rs:34:9 | -LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; - | ^^^^^^^^^^^^^^^^^^^^ +LL | || {} + | ^^^^^ note: but, the lifetime must be valid for the lifetime `'b` as defined here... --> $DIR/closure_wf_outlives.rs:27:21 | LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; | ^^ note: ...so that the declared lifetime parameter bounds are satisfied - --> $DIR/closure_wf_outlives.rs:27:27 + --> $DIR/closure_wf_outlives.rs:34:9 | -LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b; - | ^^^^^^^^^^^^^^^^^^^^ +LL | || {} + | ^^^^^ error[E0310]: the parameter type `T` may not live long enough - --> $DIR/closure_wf_outlives.rs:54:22 + --> $DIR/closure_wf_outlives.rs:60:9 | -LL | type Opaque = impl Sized; - | ^^^^^^^^^^ - | | - | the parameter type `T` must be valid for the static lifetime... - | ...so that the type `T` will meet its required lifetime bounds... +LL | || {} + | ^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the type `T` will meet its required lifetime bounds... | note: ...that is required by this bound - --> $DIR/closure_wf_outlives.rs:59:12 + --> $DIR/closure_wf_outlives.rs:58:12 | LL | T: 'static, | ^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs index e7a25fc7240..2074f12750f 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs @@ -9,10 +9,9 @@ fn main() {} fn two(t: T, _: U) -> Two { t - //~^ ERROR `T` doesn't implement `Debug` } fn three(_: T, u: U) -> Two { u - //~^ ERROR `U` doesn't implement `Debug` + //~^ ERROR concrete type differs } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr index 7bec3822071..9a10a4980d8 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr @@ -1,25 +1,14 @@ -error[E0277]: `T` doesn't implement `Debug` +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use3.rs:15:5 + | +LL | u + | ^ expected `T`, got `U` + | +note: previous use here --> $DIR/generic_duplicate_param_use3.rs:11:5 | LL | t - | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ + | ^ -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use3.rs:16:5 - | -LL | u - | ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++++++++++++++ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs index 3bd1dda6331..b3d6beaf848 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs @@ -9,12 +9,9 @@ fn main() {} fn two(t: T, u: U) -> Two { (t, u) - //~^ ERROR `T` doesn't implement `Debug` - //~| ERROR `U` doesn't implement `Debug` } fn three(t: T, u: U) -> Two { (u, t) - //~^ ERROR `T` doesn't implement `Debug` - //~| ERROR `U` doesn't implement `Debug` + //~^ ERROR concrete type differs } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr index 586ea82342a..b0027f8fa57 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr @@ -1,51 +1,14 @@ -error[E0277]: `T` doesn't implement `Debug` +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use5.rs:15:5 + | +LL | (u, t) + | ^^^^^^ expected `(T, U)`, got `(U, T)` + | +note: previous use here --> $DIR/generic_duplicate_param_use5.rs:11:5 | LL | (t, u) - | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, U)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ + | ^^^^^^ -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use5.rs:11:5 - | -LL | (t, u) - | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, U)` to implement `Debug` -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++++++++++++++ +error: aborting due to 1 previous error -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use5.rs:17:5 - | -LL | (u, t) - | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(U, T)` to implement `Debug` -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error[E0277]: `T` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use5.rs:17:5 - | -LL | (u, t) - | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(U, T)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs index 5120925e5a4..fa8b2a290b9 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs @@ -9,11 +9,9 @@ fn main() {} fn two(t: T, u: U) -> Two { (t, t) - //~^ ERROR `T` doesn't implement `Debug` } fn three(t: T, u: U) -> Two { (u, t) - //~^ ERROR `T` doesn't implement `Debug` - //~| ERROR `U` doesn't implement `Debug` + //~^ ERROR concrete type differs } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr index cb162d382b6..09c01932cef 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr @@ -1,39 +1,14 @@ -error[E0277]: `T` doesn't implement `Debug` +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use6.rs:15:5 + | +LL | (u, t) + | ^^^^^^ expected `(T, T)`, got `(U, T)` + | +note: previous use here --> $DIR/generic_duplicate_param_use6.rs:11:5 | LL | (t, t) - | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, T)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ + | ^^^^^^ -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use6.rs:16:5 - | -LL | (u, t) - | ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(U, T)` to implement `Debug` -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++++++++++++++ +error: aborting due to 1 previous error -error[E0277]: `T` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use6.rs:16:5 - | -LL | (u, t) - | ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(U, T)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs index 3a4b5047b41..76c13bb027b 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs @@ -8,10 +8,9 @@ fn main() {} fn two(t: T, _: U) -> Two { (t, 4u32) - //~^ ERROR `T` doesn't implement `Debug` } fn three(_: T, u: U) -> Two { (u, 4u32) - //~^ ERROR `U` doesn't implement `Debug` + //~^ concrete type differs } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr index 14cbfb3806f..09d2abe3663 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr @@ -1,27 +1,14 @@ -error[E0277]: `T` doesn't implement `Debug` +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use8.rs:14:5 + | +LL | (u, 4u32) + | ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)` + | +note: previous use here --> $DIR/generic_duplicate_param_use8.rs:10:5 | LL | (t, 4u32) - | ^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, u32)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ + | ^^^^^^^^^ -error[E0277]: `U` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use8.rs:15:5 - | -LL | (u, 4u32) - | ^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(U, u32)` to implement `Debug` -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++++++++++++++ +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs index 6afcdfe4d1c..5da7aab0da7 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs @@ -13,13 +13,9 @@ trait Foo { fn two(t: T, u: U) -> Two { (t, u, T::BAR) - //~^ ERROR the trait bound `A: Foo` is not satisfied - //~| ERROR `A` doesn't implement `Debug` - //~| ERROR `B` doesn't implement `Debug` } fn three(t: T, u: U) -> Two { (t, u, 42) - //~^ ERROR `A` doesn't implement `Debug` - //~| ERROR `B` doesn't implement `Debug` + //~^ ERROR concrete type differs } diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr index 722693e4266..6e1bb3dfa17 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr @@ -1,62 +1,14 @@ -error[E0277]: the trait bound `A: Foo` is not satisfied - --> $DIR/generic_duplicate_param_use9.rs:15:5 - | -LL | (t, u, T::BAR) - | ^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` - | -help: consider restricting type parameter `A` - | -LL | type Two = impl Debug; - | +++++ - -error[E0277]: `A` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use9.rs:15:5 - | -LL | (t, u, T::BAR) - | ^^^^^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(A, B, _)` to implement `Debug` -help: consider restricting type parameter `A` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error[E0277]: `B` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use9.rs:15:5 - | -LL | (t, u, T::BAR) - | ^^^^^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(A, B, _)` to implement `Debug` -help: consider restricting type parameter `B` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error[E0277]: `A` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use9.rs:22:5 +error: concrete type differs from previous defining opaque type use + --> $DIR/generic_duplicate_param_use9.rs:19:5 | LL | (t, u, 42) - | ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug` + | ^^^^^^^^^^ expected `(A, B, ::Bar)`, got `(A, B, i32)` | - = note: required for `(A, B, i32)` to implement `Debug` -help: consider restricting type parameter `A` +note: previous use here + --> $DIR/generic_duplicate_param_use9.rs:15:5 | -LL | type Two = impl Debug; - | +++++++++++++++++ +LL | (t, u, T::BAR) + | ^^^^^^^^^^^^^^ -error[E0277]: `B` doesn't implement `Debug` - --> $DIR/generic_duplicate_param_use9.rs:22:5 - | -LL | (t, u, 42) - | ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(A, B, i32)` to implement `Debug` -help: consider restricting type parameter `B` - | -LL | type Two = impl Debug; - | +++++++++++++++++ +error: aborting due to 1 previous error -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs index f8b09814caa..7b2bbc99530 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs @@ -2,9 +2,9 @@ mod test_type_param_static { pub type Ty = impl Sized + 'static; - //~^ ERROR: the parameter type `A` may not live long enough fn defining(s: A) -> Ty { s + //~^ ERROR: the parameter type `A` may not live long enough } pub fn assert_static() {} } diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index f2e5e95b96f..e5919be0532 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -1,11 +1,11 @@ error[E0310]: the parameter type `A` may not live long enough - --> $DIR/implied_lifetime_wf_check4_static.rs:4:22 + --> $DIR/implied_lifetime_wf_check4_static.rs:6:9 | -LL | pub type Ty = impl Sized + 'static; - | ^^^^^^^^^^^^^^^^^^^^ - | | - | the parameter type `A` must be valid for the static lifetime... - | ...so that the type `A` will meet its required lifetime bounds +LL | s + | ^ + | | + | the parameter type `A` must be valid for the static lifetime... + | ...so that the type `A` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound | diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs index fa47d13f516..b5ef1470629 100644 --- a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs +++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs @@ -8,7 +8,6 @@ fn main() {} fn three(t: T) -> Two { (t, 5i8) - //~^ ERROR `T` doesn't implement `Debug` } trait Bar { @@ -23,8 +22,7 @@ impl Bar for u32 { fn four(t: T) -> Two { (t, ::FOO) - //~^ ERROR `U: Bar` is not satisfied - //~| ERROR `T` doesn't implement `Debug` + //~^ ERROR concrete type differs } fn is_sync() {} diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr index b11198c584c..b59f9c49b07 100644 --- a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr +++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr @@ -1,38 +1,14 @@ -error[E0277]: `T` doesn't implement `Debug` +error: concrete type differs from previous defining opaque type use + --> $DIR/not_a_defining_use.rs:24:5 + | +LL | (t, ::FOO) + | ^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, ::Blub)` + | +note: previous use here --> $DIR/not_a_defining_use.rs:10:5 | LL | (t, 5i8) - | ^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, i8)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ + | ^^^^^^^^ -error[E0277]: the trait bound `U: Bar` is not satisfied - --> $DIR/not_a_defining_use.rs:25:5 - | -LL | (t, ::FOO) - | ^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `U` - | -help: consider restricting type parameter `U` - | -LL | type Two = impl Debug; - | +++++ +error: aborting due to 1 previous error -error[E0277]: `T` doesn't implement `Debug` - --> $DIR/not_a_defining_use.rs:25:5 - | -LL | (t, ::FOO) - | ^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` - | - = note: required for `(T, _)` to implement `Debug` -help: consider restricting type parameter `T` - | -LL | type Two = impl Debug; - | +++++++++++++++++ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs index c5b2e8a1c5e..e8e7dd0ea08 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs +++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs @@ -13,11 +13,11 @@ fn convert(_: PhantomData, r: &'a T) -> &'b T { } type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; -//~^ ERROR reference has a longer lifetime than the data it references // Even _defining_use with an explicit `'a: 'b` compiles fine, too. fn _defining_use<'a, 'b>(x: &'b &'a ()) -> Converter<'a, 'b> { x + //~^ ERROR reference has a longer lifetime than the data it references } fn extend_lifetime<'a, 'b, T: ?Sized>(x: &'a T) -> &'b T { diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr index 34b50fb1f05..7c07578d887 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr +++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr @@ -1,8 +1,8 @@ error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references - --> $DIR/underconstrained_lifetime.rs:15:26 + --> $DIR/underconstrained_lifetime.rs:19:5 | -LL | type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | x + | ^ | note: the pointer is valid for the lifetime `'b` as defined here --> $DIR/underconstrained_lifetime.rs:15:20 diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr index c4ad8434ed1..03ff2e3444b 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr @@ -1,10 +1,11 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/wf-in-associated-type.rs:38:23 + --> $DIR/wf-in-associated-type.rs:40:13 | LL | impl<'a, T> Trait<'a, T> for () { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... -LL | type Opaque = impl Sized + 'a; - | ^^^^^^^^^^^^^^^ ...so that the type `&'a T` will meet its required lifetime bounds +... +LL | req + | ^^^ ...so that the type `&'a T` will meet its required lifetime bounds | help: consider adding an explicit lifetime bound | @@ -12,12 +13,13 @@ LL | impl<'a, T: 'a> Trait<'a, T> for () { | ++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/wf-in-associated-type.rs:38:23 + --> $DIR/wf-in-associated-type.rs:40:13 | LL | impl<'a, T> Trait<'a, T> for () { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... -LL | type Opaque = impl Sized + 'a; - | ^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at +... +LL | req + | ^^^ ...so that the reference type `&'a T` does not outlive the data it points at | help: consider adding an explicit lifetime bound | diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs b/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs index c20be3125bc..e548609e89a 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs @@ -36,10 +36,10 @@ trait Trait<'a, T> { impl<'a, T> Trait<'a, T> for () { type Opaque = impl Sized + 'a; - //[fail]~^ ERROR the parameter type `T` may not live long enough - //[fail]~| ERROR the parameter type `T` may not live long enough fn constrain_opaque(req: &'a T) -> Self::Opaque { req + //[fail]~^ ERROR the parameter type `T` may not live long enough + //[fail]~| ERROR the parameter type `T` may not live long enough } } } From 97dfe8b87115c44d480b6282aae7754e7c4ab4fe Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Nov 2024 04:27:20 +0000 Subject: [PATCH 22/54] Manually register some bounds for a better span --- .../rustc_hir_analysis/src/check/check.rs | 45 +++++++++++++++---- .../src/infer/outlives/obligations.rs | 1 + compiler/rustc_middle/src/traits/mod.rs | 5 +++ .../src/error_reporting/traits/suggestions.rs | 16 +++++++ .../issue-70935-complex-spans.stderr | 5 +++ .../bounds-are-checked-2.stderr | 10 +++++ .../generic_duplicate_param_use2.stderr | 10 +++++ .../generic_duplicate_param_use4.stderr | 10 +++++ .../hidden_type_mismatch.stderr | 14 ++++++ .../implied_lifetime_wf_check4_static.stderr | 7 ++- .../type-alias-impl-trait/issue-52843.stderr | 10 +++++ .../issue-90400-2.stderr | 20 +++++++-- .../underconstrained_generic.stderr | 10 +++++ .../wf-in-associated-type.fail.stderr | 7 ++- 14 files changed, 156 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 12b842e70b7..3080d8b3510 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -8,7 +8,7 @@ use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::{Node, intravisit}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; -use rustc_infer::traits::Obligation; +use rustc_infer::traits::{Obligation, ObligationCauseCode}; use rustc_lint_defs::builtin::{ REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, }; @@ -267,7 +267,12 @@ fn check_opaque_meets_bounds<'tcx>( def_id: LocalDefId, origin: hir::OpaqueTyOrigin, ) -> Result<(), ErrorGuaranteed> { - let span = span_of_opaque(tcx, def_id, origin).unwrap_or_else(|| tcx.def_span(def_id)); + let (span, definition_def_id) = + if let Some((span, def_id)) = best_definition_site_of_opaque(tcx, def_id, origin) { + (span, Some(def_id)) + } else { + (tcx.def_span(def_id), None) + }; let defining_use_anchor = match origin { hir::OpaqueTyOrigin::FnReturn { parent, .. } @@ -305,8 +310,32 @@ fn check_opaque_meets_bounds<'tcx>( _ => re, }); - let misc_cause = traits::ObligationCause::misc(span, def_id); + // HACK: We eagerly instantiate some bounds to report better errors for them... + // This isn't necessary for correctness, since we register these bounds when + // equating the opaque below, but we should clean this up in the new solver. + for (predicate, pred_span) in + tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args) + { + let predicate = predicate.fold_with(&mut BottomUpFolder { + tcx, + ty_op: |ty| if ty == opaque_ty { hidden_ty } else { ty }, + lt_op: |lt| lt, + ct_op: |ct| ct, + }); + ocx.register_obligation(Obligation::new( + tcx, + ObligationCause::new( + span, + def_id, + ObligationCauseCode::OpaqueTypeBound(pred_span, definition_def_id), + ), + param_env, + predicate, + )); + } + + let misc_cause = ObligationCause::misc(span, def_id); // FIXME: We should just register the item bounds here, rather than equating. match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) { Ok(()) => {} @@ -364,17 +393,17 @@ fn check_opaque_meets_bounds<'tcx>( } } -fn span_of_opaque<'tcx>( +fn best_definition_site_of_opaque<'tcx>( tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId, origin: hir::OpaqueTyOrigin, -) -> Option { +) -> Option<(Span, LocalDefId)> { struct TaitConstraintLocator<'tcx> { opaque_def_id: LocalDefId, tcx: TyCtxt<'tcx>, } impl<'tcx> TaitConstraintLocator<'tcx> { - fn check(&self, item_def_id: LocalDefId) -> ControlFlow { + fn check(&self, item_def_id: LocalDefId) -> ControlFlow<(Span, LocalDefId)> { if !self.tcx.has_typeck_results(item_def_id) { return ControlFlow::Continue(()); } @@ -382,7 +411,7 @@ fn check(&self, item_def_id: LocalDefId) -> ControlFlow { if let Some(hidden_ty) = self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id) { - ControlFlow::Break(hidden_ty.span) + ControlFlow::Break((hidden_ty.span, item_def_id)) } else { ControlFlow::Continue(()) } @@ -390,7 +419,7 @@ fn check(&self, item_def_id: LocalDefId) -> ControlFlow { } impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> { type NestedFilter = nested_filter::All; - type Result = ControlFlow; + type Result = ControlFlow<(Span, LocalDefId)>; fn nested_visit_map(&mut self) -> Self::Map { self.tcx.hir() } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index e0e03a29220..b1d5d688295 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -104,6 +104,7 @@ pub fn register_region_obligation_with_cause( infer::RelateParamBound(cause.span, sup_type, match cause.code().peel_derives() { ObligationCauseCode::WhereClause(_, span) | ObligationCauseCode::WhereClauseInExpr(_, span, ..) + | ObligationCauseCode::OpaqueTypeBound(span, _) if !span.is_dummy() => { Some(*span) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 40e5ec45959..09731d565b6 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -193,6 +193,11 @@ pub enum ObligationCauseCode<'tcx> { /// The span corresponds to the clause. WhereClause(DefId, Span), + /// Represents a bound for an opaque we are checking the well-formedness of. + /// The def-id corresponds to a specific definition site that we found the + /// hidden type from, if any. + OpaqueTypeBound(Span, Option), + /// Like `WhereClause`, but also identifies the expression /// which requires the `where` clause to be proven, and also /// identifies the index of the predicate in the `predicates_of` diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 86fd4c230f6..a5e364d49f7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2953,6 +2953,22 @@ pub(super) fn note_obligation_cause_code( // We hold the `DefId` of the item introducing the obligation, but displaying it // doesn't add user usable information. It always point at an associated item. } + ObligationCauseCode::OpaqueTypeBound(span, definition_def_id) => { + err.span_note(span, "required by a bound in an opaque type"); + if let Some(definition_def_id) = definition_def_id + // If there are any stalled coroutine obligations, then this + // error may be due to that, and not because the body has more + // where-clauses. + && self.tcx.typeck(definition_def_id).coroutine_stalled_predicates.is_empty() + { + // FIXME(compiler-errors): We could probably point to something + // specific here if we tried hard enough... + err.span_note( + tcx.def_span(definition_def_id), + "this definition site has more where clauses than the opaque type", + ); + } + } ObligationCauseCode::Coercion { source, target } => { let source = tcx.short_ty_string(self.resolve_vars_if_possible(source), long_ty_file); diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index 777eefe897b..31d15c45921 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -35,6 +35,11 @@ note: required because it's used within this `async` block | LL | async move { | ^^^^^^^^^^ +note: required by a bound in an opaque type + --> $DIR/issue-70935-complex-spans.rs:15:37 + | +LL | fn foo(x: NotSync) -> impl Future + Send { + | ^^^^ error[E0277]: `*mut ()` cannot be shared between threads safely --> $DIR/issue-70935-complex-spans.rs:15:23 diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr index 0c937f92253..8f887a6ac68 100644 --- a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr +++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr @@ -4,6 +4,16 @@ error[E0277]: the trait bound `T: Clone` is not satisfied LL | t | ^ the trait `Clone` is not implemented for `T` | +note: required by a bound in an opaque type + --> $DIR/bounds-are-checked-2.rs:7:26 + | +LL | pub type X = impl Clone; + | ^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/bounds-are-checked-2.rs:9:5 + | +LL | fn f(t: T) -> X { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `T` | LL | pub type X = impl Clone; diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr index d2d6380b65a..af6e6e1e66e 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr @@ -4,6 +4,16 @@ error[E0277]: `T` doesn't implement `Debug` LL | t | ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug` | +note: required by a bound in an opaque type + --> $DIR/generic_duplicate_param_use2.rs:8:23 + | +LL | type Two = impl Debug; + | ^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/generic_duplicate_param_use2.rs:10:1 + | +LL | fn two(t: T, _: U) -> Two { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `T` | LL | type Two = impl Debug; diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr index 2338dbd522b..a847bed93da 100644 --- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr +++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr @@ -4,6 +4,16 @@ error[E0277]: `U` doesn't implement `Debug` LL | u | ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug` | +note: required by a bound in an opaque type + --> $DIR/generic_duplicate_param_use4.rs:8:23 + | +LL | type Two = impl Debug; + | ^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/generic_duplicate_param_use4.rs:10:1 + | +LL | fn three(_: T, u: U) -> Two { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `U` | LL | type Two = impl Debug; diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr index b05121a489e..be68bac5575 100644 --- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr +++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr @@ -21,6 +21,20 @@ LL | impl + Copy> Copy for Bar {} | ----------- ^^^^ ^^^^^^ | | | unsatisfied trait bound introduced here +note: required by a bound in an opaque type + --> $DIR/hidden_type_mismatch.rs:36:26 + | +LL | pub type Tait = impl Copy + From> + Into>; + | ^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/hidden_type_mismatch.rs:37:5 + | +LL | / pub fn define_tait() -> Tait +LL | | where +LL | | // this proves `Bar<()>: Copy`, but `define_tait` is +LL | | // now uncallable +LL | | (): Proj, + | |______________________________^ error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr index e5919be0532..f23b978d0b6 100644 --- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr +++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr @@ -5,8 +5,13 @@ LL | s | ^ | | | the parameter type `A` must be valid for the static lifetime... - | ...so that the type `A` will meet its required lifetime bounds + | ...so that the type `A` will meet its required lifetime bounds... | +note: ...that is required by this bound + --> $DIR/implied_lifetime_wf_check4_static.rs:4:35 + | +LL | pub type Ty = impl Sized + 'static; + | ^^^^^^^ help: consider adding an explicit lifetime bound | LL | pub type Ty = impl Sized + 'static; diff --git a/tests/ui/type-alias-impl-trait/issue-52843.stderr b/tests/ui/type-alias-impl-trait/issue-52843.stderr index ea4c5297ad5..a6bdddbc98c 100644 --- a/tests/ui/type-alias-impl-trait/issue-52843.stderr +++ b/tests/ui/type-alias-impl-trait/issue-52843.stderr @@ -4,6 +4,16 @@ error[E0277]: the trait bound `T: Default` is not satisfied LL | t | ^ the trait `Default` is not implemented for `T` | +note: required by a bound in an opaque type + --> $DIR/issue-52843.rs:3:20 + | +LL | type Foo = impl Default; + | ^^^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/issue-52843.rs:6:1 + | +LL | fn foo(t: T) -> Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `T` | LL | type Foo = impl Default; diff --git a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr index b4b78f8175f..4a6a62bdf96 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-2.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-2.stderr @@ -4,11 +4,23 @@ error[E0277]: the trait bound `B: Bar` is not satisfied LL | MyBaz(bar) | ^^^^^^^^^^ the trait `Bar` is not implemented for `B` | -note: required by a bound in `MyBaz` - --> $DIR/issue-90400-2.rs:29:17 +note: required for `MyBaz` to implement `Baz` + --> $DIR/issue-90400-2.rs:30:14 | -LL | struct MyBaz(B); - | ^^^ required by this bound in `MyBaz` +LL | impl Baz for MyBaz { + | --- ^^^ ^^^^^^^^ + | | + | unsatisfied trait bound introduced here +note: required by a bound in an opaque type + --> $DIR/issue-90400-2.rs:22:26 + | +LL | type FooFn = impl Baz; + | ^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/issue-90400-2.rs:24:5 + | +LL | fn foo(&self, bar: B) -> Self::FooFn { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `B` | LL | type FooFn = impl Baz; diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr index e4de9245951..48cef847fbb 100644 --- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr +++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr @@ -11,6 +11,16 @@ LL | impl ProofForConversion for () { | ----- ^^^^^^^^^^^^^^^^^^^^^ ^^ | | | unsatisfied trait bound introduced here +note: required by a bound in an opaque type + --> $DIR/underconstrained_generic.rs:19:26 + | +LL | type Converter = impl ProofForConversion; + | ^^^^^^^^^^^^^^^^^^^^^ +note: this definition site has more where clauses than the opaque type + --> $DIR/underconstrained_generic.rs:21:1 + | +LL | fn _defining_use() -> Converter { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider restricting type parameter `T` | LL | type Converter = impl ProofForConversion; diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr index 03ff2e3444b..34648a420ac 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr @@ -5,8 +5,13 @@ LL | impl<'a, T> Trait<'a, T> for () { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... ... LL | req - | ^^^ ...so that the type `&'a T` will meet its required lifetime bounds + | ^^^ ...so that the type `&'a T` will meet its required lifetime bounds... | +note: ...that is required by this bound + --> $DIR/wf-in-associated-type.rs:38:36 + | +LL | type Opaque = impl Sized + 'a; + | ^^ help: consider adding an explicit lifetime bound | LL | impl<'a, T: 'a> Trait<'a, T> for () { From 35a913b968eb9ad3a271f72fcc1bcd168bb572a4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 7 Nov 2024 21:44:28 +0100 Subject: [PATCH 23/54] pointee_info_at: fix logic for recursing into enums --- compiler/rustc_abi/src/lib.rs | 16 +++++++--- compiler/rustc_middle/src/ty/layout.rs | 38 ++++++++++++++++------- compiler/rustc_target/src/callconv/mod.rs | 3 +- tests/codegen/function-arguments.rs | 24 +++++++++++--- 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index ec758785173..7b6abdf1ea9 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1743,15 +1743,23 @@ pub enum PointerKind { Box { unpin: bool, global: bool }, } -/// Note that this information is advisory only, and backends are free to ignore it. -/// It can only be used to encode potential optimizations, but no critical information. +/// Encodes extra information we have about a pointer. +/// Note that this information is advisory only, and backends are free to ignore it: +/// if the information is wrong, that can cause UB, but if the information is absent, +/// that must always be okay. #[derive(Copy, Clone, Debug)] pub struct PointeeInfo { - pub size: Size, - pub align: Align, /// If this is `None`, then this is a raw pointer, so size and alignment are not guaranteed to /// be reliable. pub safe: Option, + /// If `safe` is `Some`, then the pointer is either null or dereferenceable for this many bytes. + /// On a function argument, "dereferenceable" here means "dereferenceable for the entire duration + /// of this function call", i.e. it is UB for the memory that this pointer points to to be freed + /// while this function is still running. + /// The size can be zero if the pointer is not dereferenceable. + pub size: Size, + /// If `safe` is `Some`, then the pointer is aligned as indicated. + pub align: Align, } impl LayoutData { diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 76e3183fcbb..a0eb9029319 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1011,25 +1011,41 @@ fn ty_and_layout_pointee_info_at( } _ => { - let mut data_variant = match this.variants { + let mut data_variant = match &this.variants { // Within the discriminant field, only the niche itself is // always initialized, so we only check for a pointer at its // offset. // - // If the niche is a pointer, it's either valid (according - // to its type), or null (which the niche field's scalar - // validity range encodes). This allows using - // `dereferenceable_or_null` for e.g., `Option<&T>`, and - // this will continue to work as long as we don't start - // using more niches than just null (e.g., the first page of - // the address space, or unaligned pointers). + // Our goal here is to check whether this represents a + // "dereferenceable or null" pointer, so we need to ensure + // that there is only one other variant, and it must be null. + // Below, we will then check whether the pointer is indeed + // dereferenceable. Variants::Multiple { - tag_encoding: TagEncoding::Niche { untagged_variant, .. }, + tag_encoding: + TagEncoding::Niche { untagged_variant, niche_variants, niche_start }, tag_field, + variants, .. - } if this.fields.offset(tag_field) == offset => { - Some(this.for_variant(cx, untagged_variant)) + } if variants.len() == 2 && this.fields.offset(*tag_field) == offset => { + let tagged_variant = if untagged_variant.as_u32() == 0 { + VariantIdx::from_u32(1) + } else { + VariantIdx::from_u32(0) + }; + assert_eq!(tagged_variant, *niche_variants.start()); + if *niche_start == 0 { + // The other variant is encoded as "null", so we can recurse searching for + // a pointer here. This relies on the fact that the codegen backend + // only adds "dereferenceable" if there's also a "nonnull" proof, + // and that null is aligned for all alignments so it's okay to forward + // the pointer's alignment. + Some(this.for_variant(cx, *untagged_variant)) + } else { + None + } } + Variants::Multiple { .. } => None, _ => Some(this), }; diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 8c3df9c426b..aa639f1624f 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -143,7 +143,8 @@ pub struct ArgAttributes { pub regular: ArgAttribute, pub arg_ext: ArgExtension, /// The minimum size of the pointee, guaranteed to be valid for the duration of the whole call - /// (corresponding to LLVM's dereferenceable and dereferenceable_or_null attributes). + /// (corresponding to LLVM's dereferenceable_or_null attributes, i.e., it is okay for this to be + /// set on a null pointer, but all non-null pointers must be dereferenceable). pub pointee_size: Size, pub pointee_align: Option, } diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs index 7fa1d659885..503799d3ed2 100644 --- a/tests/codegen/function-arguments.rs +++ b/tests/codegen/function-arguments.rs @@ -1,5 +1,6 @@ //@ compile-flags: -O -C no-prepopulate-passes #![crate_type = "lib"] +#![feature(rustc_attrs)] #![feature(dyn_star)] #![feature(allocator_api)] @@ -143,13 +144,28 @@ pub fn indirect_struct(_: S) {} #[no_mangle] pub fn borrowed_struct(_: &S) {} -// CHECK: @option_borrow(ptr noalias noundef readonly align 4 dereferenceable_or_null(4) %x) +// CHECK: @option_borrow(ptr noalias noundef readonly align 4 dereferenceable_or_null(4) %_x) #[no_mangle] -pub fn option_borrow(x: Option<&i32>) {} +pub fn option_borrow(_x: Option<&i32>) {} -// CHECK: @option_borrow_mut(ptr noalias noundef align 4 dereferenceable_or_null(4) %x) +// CHECK: @option_borrow_mut(ptr noalias noundef align 4 dereferenceable_or_null(4) %_x) #[no_mangle] -pub fn option_borrow_mut(x: Option<&mut i32>) {} +pub fn option_borrow_mut(_x: Option<&mut i32>) {} + +// Function that must NOT have `dereferenceable` or `align`. +#[rustc_layout_scalar_valid_range_start(16)] +pub struct RestrictedAddress(&'static i16); +enum E { + A(RestrictedAddress), + B, + C, +} +// If the `nonnull` ever goes missing, you might have to tweak the +// scalar_valid_range on `RestrictedAddress` to get it back. You +// might even have to add a `rustc_layout_scalar_valid_range_end`. +// CHECK: @nonnull_and_nondereferenceable(ptr noundef nonnull %_x) +#[no_mangle] +pub fn nonnull_and_nondereferenceable(_x: E) {} // CHECK: @raw_struct(ptr noundef %_1) #[no_mangle] From 00354ddaa69a9e4f67efa626cd1488efb03db1ba Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 7 Nov 2024 08:59:43 +0100 Subject: [PATCH 24/54] remove support for rustc_safe_intrinsic attribute; use rustc_intrinsic functions instead --- example/mini_core.rs | 83 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 19 deletions(-) diff --git a/example/mini_core.rs b/example/mini_core.rs index 42c7f5f0dc6..3da215fe6c0 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -616,25 +616,70 @@ pub union MaybeUninit { } pub mod intrinsics { - extern "rust-intrinsic" { - #[rustc_safe_intrinsic] - pub fn abort() -> !; - #[rustc_safe_intrinsic] - pub fn size_of() -> usize; - pub fn size_of_val(val: *const T) -> usize; - #[rustc_safe_intrinsic] - pub fn min_align_of() -> usize; - pub fn min_align_of_val(val: *const T) -> usize; - pub fn copy(src: *const T, dst: *mut T, count: usize); - pub fn transmute(e: T) -> U; - pub fn ctlz_nonzero(x: T) -> u32; - #[rustc_safe_intrinsic] - pub fn needs_drop() -> bool; - #[rustc_safe_intrinsic] - pub fn bitreverse(x: T) -> T; - #[rustc_safe_intrinsic] - pub fn bswap(x: T) -> T; - pub fn write_bytes(dst: *mut T, val: u8, count: usize); + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn abort() -> ! { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn size_of() -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn size_of_val(_val: *const T) -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn min_align_of() -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn min_align_of_val(_val: *const T) -> usize { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn copy(_src: *const T, _dst: *mut T, _count: usize) { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn transmute(_e: T) -> U { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn ctlz_nonzero(_x: T) -> u32 { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn needs_drop() -> bool { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn bitreverse(_x: T) -> T { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub fn bswap(_x: T) -> T { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn write_bytes(_dst: *mut T, _val: u8, _count: usize) { + loop {} + } + #[rustc_intrinsic] + #[rustc_intrinsic_must_be_overridden] + pub unsafe fn unreachable() -> ! { + loop {} } } From 730626dbd924d7fbf3873bcf1da783f486efd1d7 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 3 Nov 2024 18:23:59 +1100 Subject: [PATCH 25/54] Don't use `LLVMRustStringWriteImpl` outside of `RawRustStringOstream` --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 3 ++- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index eb99d560e57..6f47ee88add 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1624,5 +1624,6 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut, CfiFunctionDefs, CfiFunctionDecls); #endif - LLVMRustStringWriteImpl(KeyOut, Key.c_str(), Key.size()); + auto OS = RawRustStringOstream(KeyOut); + OS << Key.str(); } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index a68eed03e61..f739b010c30 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1510,8 +1510,8 @@ LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RustStringRef MessageOut, const SourceMgr &LSM = *D.getSourceMgr(); const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); - LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), - LBuf->getBufferSize()); + auto BufferOS = RawRustStringOstream(BufferOut); + BufferOS << LBuf->getBuffer(); *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart(); From 76b6090df593ee41c76e519649fba7acc930bd43 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 8 Nov 2024 16:23:07 +0300 Subject: [PATCH 26/54] read repository information configs at an earlier stage Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 39 ++++++++++++------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 8115aea033d..e222a11065a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1663,10 +1663,26 @@ fn get_table(option: &str) -> Result { let mut debuginfo_level_tools = None; let mut debuginfo_level_tests = None; let mut optimize = None; - let mut omit_git_hash = None; let mut lld_enabled = None; let mut std_features = None; + let default = config.channel == "dev"; + config.omit_git_hash = toml.rust.as_ref().and_then(|r| r.omit_git_hash).unwrap_or(default); + + config.rust_info = GitInfo::new(config.omit_git_hash, &config.src); + config.cargo_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/cargo")); + config.rust_analyzer_info = + GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rust-analyzer")); + config.clippy_info = + GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/clippy")); + config.miri_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/miri")); + config.rustfmt_info = + GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rustfmt")); + config.enzyme_info = + GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/enzyme")); + config.in_tree_llvm_info = GitInfo::new(false, &config.src.join("src/llvm-project")); + config.in_tree_gcc_info = GitInfo::new(false, &config.src.join("src/gcc")); + let mut is_user_configured_rust_channel = false; if let Some(rust) = toml.rust { @@ -1697,7 +1713,7 @@ fn get_table(option: &str) -> Result { verbose_tests, optimize_tests, codegen_tests, - omit_git_hash: omit_git_hash_toml, + omit_git_hash: _, // already handled above dist_src, save_toolstates, codegen_backends, @@ -1748,7 +1764,6 @@ fn get_table(option: &str) -> Result { std_features = std_features_toml; optimize = optimize_toml; - omit_git_hash = omit_git_hash_toml; config.rust_new_symbol_mangling = new_symbol_mangling; set(&mut config.rust_optimize_tests, optimize_tests); set(&mut config.codegen_tests, codegen_tests); @@ -1824,24 +1839,6 @@ fn get_table(option: &str) -> Result { config.reproducible_artifacts = flags.reproducible_artifact; - // rust_info must be set before is_ci_llvm_available() is called. - let default = config.channel == "dev"; - config.omit_git_hash = omit_git_hash.unwrap_or(default); - config.rust_info = GitInfo::new(config.omit_git_hash, &config.src); - - config.cargo_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/cargo")); - config.rust_analyzer_info = - GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rust-analyzer")); - config.clippy_info = - GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/clippy")); - config.miri_info = GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/miri")); - config.rustfmt_info = - GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/rustfmt")); - config.enzyme_info = - GitInfo::new(config.omit_git_hash, &config.src.join("src/tools/enzyme")); - config.in_tree_llvm_info = GitInfo::new(false, &config.src.join("src/llvm-project")); - config.in_tree_gcc_info = GitInfo::new(false, &config.src.join("src/gcc")); - // We need to override `rust.channel` if it's manually specified when using the CI rustc. // This is because if the compiler uses a different channel than the one specified in config.toml, // tests may fail due to using a different channel than the one used by the compiler during tests. From cce6f03754f096f8a2bdfb357e3739b855e29366 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 8 Nov 2024 16:23:59 +0300 Subject: [PATCH 27/54] use `download-rustc="if-unchanged"` as default whenever possible "whenever possible" means applying it if `download-rustc` isn't explicitly set and the source is Git-managed. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index e222a11065a..b1fa7da0712 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2756,9 +2756,19 @@ fn download_ci_rustc_commit( // If `download-rustc` is not set, default to rebuilding. let if_unchanged = match download_rustc { - None | Some(StringOrBool::Bool(false)) => return None, + None => self.rust_info.is_managed_git_subrepository(), + Some(StringOrBool::Bool(false)) => return None, Some(StringOrBool::Bool(true)) => false, - Some(StringOrBool::String(s)) if s == "if-unchanged" => true, + Some(StringOrBool::String(s)) if s == "if-unchanged" => { + if !self.rust_info.is_managed_git_subrepository() { + println!( + "ERROR: `download-rustc=if-unchanged` is only compatible with Git managed sources." + ); + crate::exit!(1); + } + + true + } Some(StringOrBool::String(other)) => { panic!("unrecognized option for download-rustc: {other}") } @@ -2785,7 +2795,7 @@ fn download_ci_rustc_commit( } println!("ERROR: could not find commit hash for downloading rustc"); println!("HELP: maybe your repository history is too shallow?"); - println!("HELP: consider disabling `download-rustc`"); + println!("HELP: consider setting `rust.download-rustc=false` in config.toml"); println!("HELP: or fetch enough history to include one upstream commit"); crate::exit!(1); } From 2e0afc8b71d9908911f424ff9893b52b3c642ab4 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 8 Nov 2024 16:26:00 +0300 Subject: [PATCH 28/54] respect to global `download-rustc` default in non-dist profiles Signed-off-by: onur-ozkan --- src/bootstrap/defaults/config.dist.toml | 1 + src/bootstrap/defaults/config.library.toml | 3 --- src/bootstrap/defaults/config.tools.toml | 5 ----- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/bootstrap/defaults/config.dist.toml b/src/bootstrap/defaults/config.dist.toml index d4feffe0227..4346a9c2dd1 100644 --- a/src/bootstrap/defaults/config.dist.toml +++ b/src/bootstrap/defaults/config.dist.toml @@ -11,6 +11,7 @@ extended = true # Most users installing from source want to build all parts of the project from source. [llvm] download-ci-llvm = false + [rust] # We have several defaults in bootstrap that depend on whether the channel is `dev` (e.g. `omit-git-hash` and `download-ci-llvm`). # Make sure they don't get set when installing from source. diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml index 3d697be8156..5447565a4b0 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/config.library.toml @@ -8,9 +8,6 @@ bench-stage = 0 [rust] # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. incremental = true -# Download rustc from CI instead of building it from source. -# For stage > 1 builds, this cuts compile times significantly when there are no changes on "compiler" tree. -download-rustc = "if-unchanged" # Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown. lto = "off" diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml index 27c1d1cf26d..76b47a841b3 100644 --- a/src/bootstrap/defaults/config.tools.toml +++ b/src/bootstrap/defaults/config.tools.toml @@ -3,11 +3,6 @@ [rust] # This greatly increases the speed of rebuilds, especially when there are only minor changes. However, it makes the initial build slightly slower. incremental = true -# Download rustc from CI instead of building it from source. -# For stage > 1 builds, this cuts compile times significantly when there are no changes on "compiler" tree. -# Using these defaults will download the stage2 compiler (see `download-rustc` -# setting) and the stage2 toolchain should therefore be used for these defaults. -download-rustc = "if-unchanged" [build] # Document with the in-tree rustdoc by default, since `download-rustc` makes it quick to compile. From 6ffab47e553f6fcd5590a3c86c646860bace5823 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 8 Nov 2024 15:16:37 +0100 Subject: [PATCH 29/54] Use lld with non-LLVM backends On arm64, Cranelift used to produce object files that don't work with lld. This has since been fixed. The GCC backend should always produce object files that work with lld unless lld for whatever reason drops GCC support. Most of the other more niche backends don't use cg_ssa's linker code at all. If they do and don't work with lld, they can always disable lld usage using a cli argument. Without this commit using cg_clif is by default in a non-trivial amount of cases a perf regression on Linux due to ld.bfd being a fair bit slower than lld. It is possible to explicitly enable it without this commit, but most users are unlikely to do this. --- compiler/rustc_codegen_ssa/src/back/link.rs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 8f754debaf0..3120b5bf0af 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -3305,23 +3305,6 @@ fn add_lld_args( let self_contained_cli = sess.opts.cg.link_self_contained.is_linker_enabled(); let self_contained_target = self_contained_components.is_linker_enabled(); - // FIXME: in the future, codegen backends may need to have more control over this process: they - // don't always support all the features the linker expects here, and vice versa. For example, - // at the time of writing this, lld expects a newer style of aarch64 TLS relocations that - // cranelift doesn't implement yet. That in turn can impact whether linking would succeed on - // such a target when using the `cg_clif` backend and lld. - // - // Until interactions between backends and linker features are expressible, we limit target - // specs to opt-in to lld only when we're on the llvm backend, where it's expected to work and - // tested on CI. As usual, the CLI still has precedence over this, so that users and developers - // can still override this default when needed (e.g. for tests). - let uses_llvm_backend = - matches!(sess.opts.unstable_opts.codegen_backend.as_deref(), None | Some("llvm")); - if !uses_llvm_backend && !self_contained_cli && sess.opts.cg.linker_flavor.is_none() { - // We bail if we're not using llvm and lld was not explicitly requested on the CLI. - return; - } - let self_contained_linker = self_contained_cli || self_contained_target; if self_contained_linker && !sess.opts.cg.link_self_contained.is_linker_disabled() { let mut linker_path_exists = false; From c637a84ad4f4446e6f6bbb1129632b20b42c6e3a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 8 Nov 2024 16:14:02 +0100 Subject: [PATCH 30/54] Add finish_ongoing_codegen timer in join_codegen to match cg_llvm --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index aba0c28f6b8..19a1de53d1d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -241,6 +241,8 @@ fn join_codegen( sess: &Session, outputs: &OutputFilenames, ) -> (CodegenResults, FxIndexMap) { + let _timer = sess.timer("finish_ongoing_codegen"); + ongoing_codegen.downcast::().unwrap().join( sess, outputs, From 8fcc020a0c84d316509a48bf3fc97d08e790e83a Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Fri, 8 Nov 2024 10:41:16 -0500 Subject: [PATCH 31/54] try_question_mark_nop: update test for LLVM 20 llvm/llvm-project@dd116369f646d023a2e7e5c145a1bed5dcf9a45c changes the IR of this test in a way that I don't think is bad, but needs adjusting. r? @nikic @rustbot label: +llvm-main --- tests/codegen/try_question_mark_nop.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/codegen/try_question_mark_nop.rs b/tests/codegen/try_question_mark_nop.rs index bbab0d9eb1d..b68ecce869e 100644 --- a/tests/codegen/try_question_mark_nop.rs +++ b/tests/codegen/try_question_mark_nop.rs @@ -1,6 +1,10 @@ //@ compile-flags: -O -Z merge-functions=disabled --edition=2021 //@ only-x86_64 // FIXME: Remove the `min-llvm-version`. +//@ revisions: NINETEEN TWENTY +//@[NINETEEN] min-llvm-version: 19 +//@[NINETEEN] ignore-llvm-version: 20-99 +//@[TWENTY] min-llvm-version: 20 //@ min-llvm-version: 19 #![crate_type = "lib"] @@ -13,8 +17,11 @@ #[no_mangle] pub fn option_nop_match_32(x: Option) -> Option { // CHECK: start: + // TWENTY-NEXT: %trunc = trunc nuw i32 %0 to i1 + // TWENTY-NEXT: %.2 = select i1 %trunc, i32 %1, i32 undef // CHECK-NEXT: [[REG1:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0 - // CHECK-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %1, 1 + // NINETEEN-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %1, 1 + // TWENTY-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } [[REG1]], i32 %.2, 1 // CHECK-NEXT: ret { i32, i32 } [[REG2]] match x { Some(x) => Some(x), @@ -26,6 +33,8 @@ pub fn option_nop_match_32(x: Option) -> Option { #[no_mangle] pub fn option_nop_traits_32(x: Option) -> Option { // CHECK: start: + // TWENTY-NEXT: %trunc = trunc nuw i32 %0 to i1 + // TWENTY-NEXT: %.1 = select i1 %trunc, i32 %1, i32 undef // CHECK-NEXT: insertvalue { i32, i32 } // CHECK-NEXT: insertvalue { i32, i32 } // CHECK-NEXT: ret { i32, i32 } From 8a0053e9e16586e060612db44578038d3edb107e Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 8 Nov 2024 16:16:03 +0100 Subject: [PATCH 32/54] Use a BufWriter in emit_module to reduce syscall overhead For the coercions rustc-perf benchmark without this commit reduces the total amount of time it takes to emit the object file from 270ms to 27ms. --- src/driver/aot.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 419efa90600..8eab73ad5f9 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -2,6 +2,7 @@ //! standalone executable. use std::fs::{self, File}; +use std::io::BufWriter; use std::path::{Path, PathBuf}; use std::sync::Arc; use std::thread::JoinHandle; @@ -397,14 +398,19 @@ fn emit_module( } let tmp_file = output_filenames.temp_path(OutputType::Object, Some(&name)); - let mut file = match File::create(&tmp_file) { + let file = match File::create(&tmp_file) { Ok(file) => file, Err(err) => return Err(format!("error creating object file: {}", err)), }; + let mut file = BufWriter::new(file); if let Err(err) = object.write_stream(&mut file) { return Err(format!("error writing object file: {}", err)); } + let file = match file.into_inner() { + Ok(file) => file, + Err(err) => return Err(format!("error writing object file: {}", err)), + }; prof.artifact_size("object_file", &*name, file.metadata().unwrap().len()); From b004cac72ef9e0b4ab2d47a6bbb1a543659b1e2b Mon Sep 17 00:00:00 2001 From: binarycat Date: Fri, 8 Nov 2024 09:51:46 -0600 Subject: [PATCH 33/54] update io::Error::into_inner to acknowlage io::Error::other --- library/std/src/io/error.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index adf103e9430..5d7adcace52 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -818,10 +818,12 @@ pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'stat /// Consumes the `Error`, returning its inner error (if any). /// - /// If this [`Error`] was constructed via [`new`] then this function will - /// return [`Some`], otherwise it will return [`None`]. + /// If this [`Error`] was constructed via [`new`] or [`other`], + /// then this function will return [`Some`], + /// otherwise it will return [`None`]. /// /// [`new`]: Error::new + /// [`other`]: Error::other /// /// # Examples /// From 0e481b44f5d851e9b7b3b3ed1b576d92437c7684 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 8 Nov 2024 16:57:53 +0000 Subject: [PATCH 34/54] use verbose for path separator suggestion --- .../rustc_resolve/src/late/diagnostics.rs | 2 +- tests/ui/resolve/issue-100365.stderr | 27 +++++++++++-- tests/ui/resolve/issue-22692.stderr | 33 ++++++++++++--- .../suggest-path-for-tuple-struct.stderr | 14 ++++++- ...uggest-path-instead-of-mod-dot-item.stderr | 40 ++++++++++++++++--- .../suggestions/assoc-const-as-field.stderr | 7 +++- 6 files changed, 104 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 42455983575..09f5a8e96d3 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1472,7 +1472,7 @@ fn smart_resolve_context_dependent_help( }; if lhs_span.eq_ctxt(rhs_span) { - err.span_suggestion( + err.span_suggestion_verbose( lhs_span.between(rhs_span), MESSAGE, "::", diff --git a/tests/ui/resolve/issue-100365.stderr b/tests/ui/resolve/issue-100365.stderr index 372d7726668..2d9bab4304d 100644 --- a/tests/ui/resolve/issue-100365.stderr +++ b/tests/ui/resolve/issue-100365.stderr @@ -2,19 +2,34 @@ error[E0423]: expected value, found trait `Into` --> $DIR/issue-100365.rs:2:16 | LL | let addr = Into::.into([127, 0, 0, 1]); - | ^^^^^^^^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let addr = Into::::into([127, 0, 0, 1]); + | ~~ error[E0423]: expected value, found trait `Into` --> $DIR/issue-100365.rs:6:13 | LL | let _ = Into.into(()); - | ^^^^- help: use the path separator to refer to an item: `::` + | ^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = Into::into(()); + | ~~ error[E0423]: expected value, found trait `Into` --> $DIR/issue-100365.rs:10:13 | LL | let _ = Into::<()>.into; - | ^^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = Into::<()>::into; + | ~~ error[E0423]: expected value, found trait `std::iter::Iterator` --> $DIR/issue-100365.rs:17:9 @@ -42,12 +57,16 @@ error[E0423]: expected value, found trait `Into` --> $DIR/issue-100365.rs:25:9 | LL | Into::.into("") - | ^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^^^^^^ ... LL | let _ = create!(); | --------- in this macro invocation | = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | Into::::into("") + | ~~ error: aborting due to 6 previous errors diff --git a/tests/ui/resolve/issue-22692.stderr b/tests/ui/resolve/issue-22692.stderr index 6962aa161e9..be0634ebffc 100644 --- a/tests/ui/resolve/issue-22692.stderr +++ b/tests/ui/resolve/issue-22692.stderr @@ -2,19 +2,34 @@ error[E0423]: expected value, found struct `String` --> $DIR/issue-22692.rs:2:13 | LL | let _ = String.new(); - | ^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = String::new(); + | ~~ error[E0423]: expected value, found struct `String` --> $DIR/issue-22692.rs:6:13 | LL | let _ = String.default; - | ^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = String::default; + | ~~ error[E0423]: expected value, found struct `Vec` --> $DIR/issue-22692.rs:10:13 | LL | let _ = Vec::<()>.with_capacity(1); - | ^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = Vec::<()>::with_capacity(1); + | ~~ error[E0423]: expected value, found struct `std::cell::Cell` --> $DIR/issue-22692.rs:17:9 @@ -50,23 +65,31 @@ error[E0423]: expected value, found struct `Vec` --> $DIR/issue-22692.rs:26:9 | LL | Vec.new() - | ^^^- help: use the path separator to refer to an item: `::` + | ^^^ ... LL | let _ = create!(type method); | -------------------- in this macro invocation | = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | Vec::new() + | ~~ error[E0423]: expected value, found struct `Vec` --> $DIR/issue-22692.rs:31:9 | LL | Vec.new - | ^^^- help: use the path separator to refer to an item: `::` + | ^^^ ... LL | let _ = create!(type field); | ------------------- in this macro invocation | = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | Vec::new + | ~~ error[E0423]: expected value, found struct `std::cell::Cell` --> $DIR/issue-22692.rs:17:9 diff --git a/tests/ui/resolve/suggest-path-for-tuple-struct.stderr b/tests/ui/resolve/suggest-path-for-tuple-struct.stderr index 4764cf2db20..12c631f5a83 100644 --- a/tests/ui/resolve/suggest-path-for-tuple-struct.stderr +++ b/tests/ui/resolve/suggest-path-for-tuple-struct.stderr @@ -2,13 +2,23 @@ error[E0423]: expected value, found struct `SomeTupleStruct` --> $DIR/suggest-path-for-tuple-struct.rs:22:13 | LL | let _ = SomeTupleStruct.new(); - | ^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = SomeTupleStruct::new(); + | ~~ error[E0423]: expected value, found struct `SomeRegularStruct` --> $DIR/suggest-path-for-tuple-struct.rs:24:13 | LL | let _ = SomeRegularStruct.new(); - | ^^^^^^^^^^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^^^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | let _ = SomeRegularStruct::new(); + | ~~ error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr index a4ce0deeb70..9c12fd2644c 100644 --- a/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr +++ b/tests/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr @@ -2,19 +2,34 @@ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:17:5 | LL | a.I - | ^- help: use the path separator to refer to an item: `::` + | ^ + | +help: use the path separator to refer to an item + | +LL | a::I + | ~~ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:23:5 | LL | a.g() - | ^- help: use the path separator to refer to an item: `::` + | ^ + | +help: use the path separator to refer to an item + | +LL | a::g() + | ~~ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:29:5 | LL | a.b.J - | ^- help: use the path separator to refer to an item: `::` + | ^ + | +help: use the path separator to refer to an item + | +LL | a::b.J + | ~~ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:35:5 @@ -38,7 +53,12 @@ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:42:5 | LL | a.b.f(); - | ^- help: use the path separator to refer to an item: `::` + | ^ + | +help: use the path separator to refer to an item + | +LL | a::b.f(); + | ~~ error[E0423]: expected value, found module `a::b` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:46:12 @@ -117,23 +137,31 @@ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:80:9 | LL | a.f() - | ^- help: use the path separator to refer to an item: `::` + | ^ ... LL | let _ = create!(method); | --------------- in this macro invocation | = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | a::f() + | ~~ error[E0423]: expected value, found module `a` --> $DIR/suggest-path-instead-of-mod-dot-item.rs:85:9 | LL | a.f - | ^- help: use the path separator to refer to an item: `::` + | ^ ... LL | let _ = create!(field); | -------------- in this macro invocation | = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the path separator to refer to an item + | +LL | a::f + | ~~ error: aborting due to 13 previous errors diff --git a/tests/ui/suggestions/assoc-const-as-field.stderr b/tests/ui/suggestions/assoc-const-as-field.stderr index 0f58ce65049..6c095e52ac9 100644 --- a/tests/ui/suggestions/assoc-const-as-field.stderr +++ b/tests/ui/suggestions/assoc-const-as-field.stderr @@ -2,7 +2,12 @@ error[E0423]: expected value, found struct `Mod::Foo` --> $DIR/assoc-const-as-field.rs:11:9 | LL | foo(Mod::Foo.Bar); - | ^^^^^^^^- help: use the path separator to refer to an item: `::` + | ^^^^^^^^ + | +help: use the path separator to refer to an item + | +LL | foo(Mod::Foo::Bar); + | ~~ error: aborting due to 1 previous error From 2a381086bbaf2ba29bbac33be0805d8a1d20f9fb Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Fri, 8 Nov 2024 20:25:54 +0300 Subject: [PATCH 35/54] fix `core::config::tests::override_toml` Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/tests.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 1f02757682c..b6523a458e2 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -135,6 +135,7 @@ fn override_toml() { [rust] lto = "off" deny-warnings = true +download-rustc=false [build] gdb = "foo" @@ -200,6 +201,8 @@ fn override_toml() { .collect(), "setting dictionary value" ); + assert!(!config.llvm_from_ci); + assert!(!config.download_rustc()); } #[test] From 400a690b5f99cd345b679014fe0c821d3847bcd3 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 9 Nov 2024 03:17:24 +0900 Subject: [PATCH 36/54] Add v9 and leoncasa target feature to sparc --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 3 +++ compiler/rustc_feature/src/unstable.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/target_features.rs | 9 +++++++++ tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- tests/ui/target-feature/gate.rs | 1 + tests/ui/target-feature/gate.stderr | 2 +- 8 files changed, 18 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 6f2d86cc601..b5bd5dbde81 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -228,6 +228,8 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option(sess: &Session, s: &'a str) -> Option None, + ("sparc", "leoncasa") => Some(LLVMFeature::new("hasleoncasa")), (_, s) => Some(LLVMFeature::new(s)), } } diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 5f83c211b38..8326d0031ea 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -336,6 +336,7 @@ pub fn internal(&self, feature: Symbol) -> bool { (unstable, riscv_target_feature, "1.45.0", Some(44839)), (unstable, rtm_target_feature, "1.35.0", Some(44839)), (unstable, s390x_target_feature, "1.82.0", Some(44839)), + (unstable, sparc_target_feature, "CURRENT_RUSTC_VERSION", Some(132783)), (unstable, sse4a_target_feature, "1.27.0", Some(44839)), (unstable, tbm_target_feature, "1.27.0", Some(44839)), (unstable, wasm_target_feature, "1.30.0", Some(44839)), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 21a74bd4020..e18e0a31c66 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1868,6 +1868,7 @@ slice_patterns, slicing_syntax, soft, + sparc_target_feature, specialization, speed, spotlight, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 96f1e257bb5..b649c0353a4 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -545,6 +545,13 @@ pub fn is_supported(self) -> bool { // tidy-alphabetical-end ]; +const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + // tidy-alphabetical-start + ("leoncasa", Unstable(sym::sparc_target_feature), &[]), + ("v9", Unstable(sym::sparc_target_feature), &[]), + // tidy-alphabetical-end +]; + /// When rustdoc is running, provide a list of all known features so that all their respective /// primitives may be documented. /// @@ -563,6 +570,7 @@ pub fn all_rust_features() -> impl Iterator { .chain(CSKY_FEATURES) .chain(LOONGARCH_FEATURES) .chain(IBMZ_FEATURES) + .chain(SPARC_FEATURES) .cloned() .map(|(f, s, _)| (f, s)) } @@ -582,6 +590,7 @@ pub fn rust_target_features(&self) -> &'static [(&'static str, Stability, Implie "csky" => CSKY_FEATURES, "loongarch64" => LOONGARCH_FEATURES, "s390x" => IBMZ_FEATURES, + "sparc" | "sparc64" => SPARC_FEATURES, _ => &[], } } diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 43766788de7..3818609ff1c 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 247 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 249 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 224313c6c8d..e4c75dcfb13 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -174,7 +174,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `leoncasa`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 5c4fb847932..f35fbd11155 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -23,6 +23,7 @@ // gate-test-lahfsahf_target_feature // gate-test-prfchw_target_feature // gate-test-s390x_target_feature +// gate-test-sparc_target_feature #[target_feature(enable = "avx512bw")] //~^ ERROR: currently unstable diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index 37c5ed01688..b84bab370be 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:27:18 + --> $DIR/gate.rs:28:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From c059eb77504b638bc53b486ef7151cedb7a7ef03 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 9 Nov 2024 03:22:09 +0900 Subject: [PATCH 37/54] Add v8plus target feature to sparc and use it in create_object_file --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 8 ++++ .../rustc_codegen_ssa/src/back/metadata.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../spec/targets/sparc_unknown_linux_gnu.rs | 1 + compiler/rustc_target/src/target_features.rs | 1 + tests/ui/abi/sparcv8plus.rs | 43 +++++++++++++++++++ tests/ui/abi/sparcv8plus.sparc.stderr | 8 ++++ tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr | 8 ++++ ...cv8plus.sparc_cpu_v9_feature_v8plus.stderr | 8 ++++ .../sparcv8plus.sparc_feature_v8plus.stderr | 8 ++++ tests/ui/abi/sparcv8plus.sparcv8plus.stderr | 8 ++++ tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 13 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 tests/ui/abi/sparcv8plus.rs create mode 100644 tests/ui/abi/sparcv8plus.sparc.stderr create mode 100644 tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr create mode 100644 tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr create mode 100644 tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr create mode 100644 tests/ui/abi/sparcv8plus.sparcv8plus.stderr diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index b5bd5dbde81..c382242d8d0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -283,6 +283,12 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option None, ("sparc", "leoncasa") => Some(LLVMFeature::new("hasleoncasa")), + // In LLVM 19, there is no `v8plus` feature and `v9` means "SPARC-V9 instruction available and SPARC-V8+ ABI used". + // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L27-L28 + // Before LLVM 19, there is no `v8plus` feature and `v9` means "SPARC-V9 instruction available". + // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L26 + ("sparc", "v8plus") if get_version().0 == 19 => Some(LLVMFeature::new("v9")), + ("sparc", "v8plus") if get_version().0 < 19 => None, (_, s) => Some(LLVMFeature::new(s)), } } @@ -622,6 +628,8 @@ pub(crate) fn global_llvm_features( .features .split(',') .filter(|v| !v.is_empty() && backend_feature_name(sess, v).is_some()) + // Drop +v8plus feature introduced in LLVM 20. + .filter(|v| *v != "+v8plus" || get_version() >= (20, 0, 0)) .map(String::from), ); diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 3f3cb8b4073..bdf7030f946 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -212,7 +212,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option (Architecture::Riscv32, None), "riscv64" => (Architecture::Riscv64, None), "sparc" => { - if sess.target.options.cpu == "v9" { + if sess.unstable_target_features.contains(&sym::v8plus) { // Target uses V8+, aka EM_SPARC32PLUS, aka 64-bit V9 but in 32-bit mode (Architecture::Sparc32Plus, None) } else { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e18e0a31c66..bc9ebbc1c21 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2111,6 +2111,7 @@ usize_legacy_fn_max_value, usize_legacy_fn_min_value, usize_legacy_mod, + v8plus, va_arg, va_copy, va_end, diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs index 2777395757f..45941cd7c01 100644 --- a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs @@ -14,6 +14,7 @@ pub(crate) fn target() -> Target { data_layout: "E-m:e-p:32:32-i64:64-i128:128-f128:64-n32-S64".into(), arch: "sparc".into(), options: TargetOptions { + features: "+v8plus".into(), cpu: "v9".into(), endian: Endian::Big, late_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[ diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index b649c0353a4..dc5de413e4b 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -548,6 +548,7 @@ pub fn is_supported(self) -> bool { const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-start ("leoncasa", Unstable(sym::sparc_target_feature), &[]), + ("v8plus", Unstable(sym::sparc_target_feature), &[]), ("v9", Unstable(sym::sparc_target_feature), &[]), // tidy-alphabetical-end ]; diff --git a/tests/ui/abi/sparcv8plus.rs b/tests/ui/abi/sparcv8plus.rs new file mode 100644 index 00000000000..108279b3494 --- /dev/null +++ b/tests/ui/abi/sparcv8plus.rs @@ -0,0 +1,43 @@ +//@ revisions: sparc sparcv8plus sparc_cpu_v9 sparc_feature_v8plus sparc_cpu_v9_feature_v8plus +//@[sparc] compile-flags: --target sparc-unknown-none-elf +//@[sparc] needs-llvm-components: sparc +//@[sparcv8plus] compile-flags: --target sparc-unknown-linux-gnu +//@[sparcv8plus] needs-llvm-components: sparc +//@[sparc_cpu_v9] compile-flags: --target sparc-unknown-none-elf -C target-cpu=v9 +//@[sparc_cpu_v9] needs-llvm-components: sparc +//@[sparc_feature_v8plus] compile-flags: --target sparc-unknown-none-elf -C target-feature=+v8plus +//@[sparc_feature_v8plus] needs-llvm-components: sparc +//@[sparc_cpu_v9_feature_v8plus] compile-flags: --target sparc-unknown-none-elf -C target-cpu=v9 -C target-feature=+v8plus +//@[sparc_cpu_v9_feature_v8plus] needs-llvm-components: sparc +//@ min-llvm-version: 19 + +#![crate_type = "rlib"] +#![feature(no_core, rustc_attrs, lang_items)] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[rustc_builtin_macro] +macro_rules! compile_error { + () => {}; +} + +#[cfg(all(not(target_feature = "v8plus"), not(target_feature = "v9")))] +compile_error!("-v8plus,-v9"); +//[sparc]~^ ERROR -v8plus,-v9 + +// FIXME: sparc_cpu_v9 should be in "-v8plus,+v9" group (fixed in LLVM 20) +#[cfg(all(target_feature = "v8plus", target_feature = "v9"))] +compile_error!("+v8plus,+v9"); +//[sparcv8plus,sparc_cpu_v9_feature_v8plus,sparc_cpu_v9]~^ ERROR +v8plus,+v9 + +// FIXME: should be rejected +#[cfg(all(target_feature = "v8plus", not(target_feature = "v9")))] +compile_error!("+v8plus,-v9 (FIXME)"); +//[sparc_feature_v8plus]~^ ERROR +v8plus,-v9 (FIXME) + +#[cfg(all(not(target_feature = "v8plus"), target_feature = "v9"))] +compile_error!("-v8plus,+v9"); diff --git a/tests/ui/abi/sparcv8plus.sparc.stderr b/tests/ui/abi/sparcv8plus.sparc.stderr new file mode 100644 index 00000000000..6d14ff53ab9 --- /dev/null +++ b/tests/ui/abi/sparcv8plus.sparc.stderr @@ -0,0 +1,8 @@ +error: -v8plus,-v9 + --> $DIR/sparcv8plus.rs:29:1 + | +LL | compile_error!("-v8plus,-v9"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr b/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr new file mode 100644 index 00000000000..5e1e1fa5c79 --- /dev/null +++ b/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr @@ -0,0 +1,8 @@ +error: +v8plus,+v9 + --> $DIR/sparcv8plus.rs:34:1 + | +LL | compile_error!("+v8plus,+v9"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr new file mode 100644 index 00000000000..5e1e1fa5c79 --- /dev/null +++ b/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr @@ -0,0 +1,8 @@ +error: +v8plus,+v9 + --> $DIR/sparcv8plus.rs:34:1 + | +LL | compile_error!("+v8plus,+v9"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr new file mode 100644 index 00000000000..8a5375a46bc --- /dev/null +++ b/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr @@ -0,0 +1,8 @@ +error: +v8plus,-v9 (FIXME) + --> $DIR/sparcv8plus.rs:39:1 + | +LL | compile_error!("+v8plus,-v9 (FIXME)"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/abi/sparcv8plus.sparcv8plus.stderr b/tests/ui/abi/sparcv8plus.sparcv8plus.stderr new file mode 100644 index 00000000000..5e1e1fa5c79 --- /dev/null +++ b/tests/ui/abi/sparcv8plus.sparcv8plus.stderr @@ -0,0 +1,8 @@ +error: +v8plus,+v9 + --> $DIR/sparcv8plus.rs:34:1 + | +LL | compile_error!("+v8plus,+v9"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index 3818609ff1c..ab212dda015 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -251,7 +251,7 @@ warning: unexpected `cfg` condition value: `zebra` LL | cfg!(target_feature = "zebra"); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 249 more + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, and `avx512vpopcntdq` and 250 more = note: see for more information about checking conditional configuration warning: 27 warnings emitted diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index e4c75dcfb13..f51271dc3de 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -174,7 +174,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_feature = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `leoncasa`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v9`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` + = note: expected values for `target_feature` are: `10e60`, `2e3`, `3e3r1`, `3e3r2`, `3e3r3`, `3e7`, `7e10`, `a`, `aclass`, `adx`, `aes`, `altivec`, `alu32`, `amx-bf16`, `amx-complex`, `amx-fp16`, `amx-int8`, `amx-tile`, `atomics`, `avx`, `avx2`, `avx512bf16`, `avx512bitalg`, `avx512bw`, `avx512cd`, `avx512dq`, `avx512f`, `avx512fp16`, `avx512ifma`, `avx512vbmi`, `avx512vbmi2`, `avx512vl`, `avx512vnni`, `avx512vp2intersect`, `avx512vpopcntdq`, `avxifma`, `avxneconvert`, `avxvnni`, `avxvnniint16`, `avxvnniint8`, `backchain`, `bf16`, `bmi1`, `bmi2`, `bti`, `bulk-memory`, `c`, `cache`, `cmpxchg16b`, `crc`, `crt-static`, `cssc`, `d`, `d32`, `dit`, `doloop`, `dotprod`, `dpb`, `dpb2`, `dsp`, `dsp1e2`, `dspe60`, `e`, `e1`, `e2`, `ecv`, `edsp`, `elrw`, `ermsb`, `exception-handling`, `extended-const`, `f`, `f16c`, `f32mm`, `f64mm`, `faminmax`, `fcma`, `fdivdu`, `fhm`, `flagm`, `flagm2`, `float1e2`, `float1e3`, `float3e4`, `float7e60`, `floate1`, `fma`, `fp-armv8`, `fp16`, `fp64`, `fp8`, `fp8dot2`, `fp8dot4`, `fp8fma`, `fpuv2_df`, `fpuv2_sf`, `fpuv3_df`, `fpuv3_hf`, `fpuv3_hi`, `fpuv3_sf`, `frecipe`, `frintts`, `fxsr`, `gfni`, `hard-float`, `hard-float-abi`, `hard-tp`, `hbc`, `high-registers`, `hvx`, `hvx-length128b`, `hwdiv`, `i8mm`, `jsconv`, `lahfsahf`, `lasx`, `lbt`, `leoncasa`, `lor`, `lse`, `lse128`, `lse2`, `lsx`, `lut`, `lvz`, `lzcnt`, `m`, `mclass`, `mops`, `movbe`, `mp`, `mp1e2`, `msa`, `mte`, `multivalue`, `mutable-globals`, `neon`, `nontrapping-fptoint`, `nvic`, `paca`, `pacg`, `pan`, `partword-atomics`, `pauth-lr`, `pclmulqdq`, `pmuv3`, `popcnt`, `power10-vector`, `power8-altivec`, `power8-vector`, `power9-altivec`, `power9-vector`, `prfchw`, `quadword-atomics`, `rand`, `ras`, `rclass`, `rcpc`, `rcpc2`, `rcpc3`, `rdm`, `rdrand`, `rdseed`, `reference-types`, `relax`, `relaxed-simd`, `rtm`, `sb`, `sha`, `sha2`, `sha3`, `sha512`, `sign-ext`, `simd128`, `sm3`, `sm4`, `sme`, `sme-b16b16`, `sme-f16f16`, `sme-f64f64`, `sme-f8f16`, `sme-f8f32`, `sme-fa64`, `sme-i16i64`, `sme-lutv2`, `sme2`, `sme2p1`, `spe`, `ssbs`, `sse`, `sse2`, `sse3`, `sse4.1`, `sse4.2`, `sse4a`, `ssse3`, `ssve-fp8dot2`, `ssve-fp8dot4`, `ssve-fp8fma`, `sve`, `sve-b16b16`, `sve2`, `sve2-aes`, `sve2-bitperm`, `sve2-sha3`, `sve2-sm4`, `sve2p1`, `tbm`, `thumb-mode`, `thumb2`, `tme`, `trust`, `trustzone`, `ual`, `unaligned-scalar-mem`, `v`, `v5te`, `v6`, `v6k`, `v6t2`, `v7`, `v8`, `v8.1a`, `v8.2a`, `v8.3a`, `v8.4a`, `v8.5a`, `v8.6a`, `v8.7a`, `v8.8a`, `v8.9a`, `v8plus`, `v9`, `v9.1a`, `v9.2a`, `v9.3a`, `v9.4a`, `v9.5a`, `v9a`, `vaes`, `vdsp2e60f`, `vdspv1`, `vdspv2`, `vector`, `vfp2`, `vfp3`, `vfp4`, `vh`, `virt`, `virtualization`, `vpclmulqdq`, `vsx`, `wfxt`, `wide-arithmetic`, `xop`, `xsave`, `xsavec`, `xsaveopt`, `xsaves`, `zaamo`, `zabha`, `zalrsc`, `zba`, `zbb`, `zbc`, `zbkb`, `zbkc`, `zbkx`, `zbs`, `zdinx`, `zfh`, `zfhmin`, `zfinx`, `zhinx`, `zhinxmin`, `zk`, `zkn`, `zknd`, `zkne`, `zknh`, `zkr`, `zks`, `zksed`, `zksh`, and `zkt` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From a10e744fafa7eb3afef9a938097509bf4b225f84 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Fri, 8 Nov 2024 13:38:09 -0500 Subject: [PATCH 38/54] rustc_target: more target string fixes for LLVM 20 LLVM continues to clean these up, and we continue to make this consistent. This is similar to 9caced7badc337ced7ad89eb614621c39bd996e9 and e9853961452b56997cc127b51308879b9cd09482. @rustbot label: +llvm-main --- .../src/spec/targets/aarch64_be_unknown_linux_gnu.rs | 2 +- .../src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs | 2 +- .../rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs | 2 +- .../src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs index f1854353abd..1511c0ccaad 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { features: "+v8a,+outline-atomics".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs index 0dc51aaa73d..e7070778794 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs @@ -14,7 +14,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 32, - data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "E-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { abi: "ilp32".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs index f99e7fe84f5..f0f6e49eedd 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs @@ -11,7 +11,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 64, - data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { mcount: "__mcount".into(), diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs index f33a5873c09..7b0df7d1130 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs @@ -10,7 +10,7 @@ pub(crate) fn target() -> Target { std: Some(true), }, pointer_width: 32, - data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), arch: "aarch64".into(), options: TargetOptions { abi: "ilp32".into(), From 89d7efaf8f5ed8c1c15faea21824ae479656bdc1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 3 Nov 2024 12:40:26 +1100 Subject: [PATCH 39/54] Make `RustString` an extern type to avoid `improper_ctypes` warnings --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 17 ----- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 9 +-- .../rustc_llvm/llvm-wrapper/LLVMWrapper.h | 5 +- compiler/rustc_llvm/src/lib.rs | 73 ++++++++++++++----- 4 files changed, 58 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 8508f87c8d3..0fc1988e861 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1766,11 +1766,9 @@ pub fn LLVMRustBuildAtomicStore<'a>( pub fn LLVMRustGetLastError() -> *const c_char; /// Prints the timing information collected by `-Ztime-llvm-passes`. - #[expect(improper_ctypes)] pub(crate) fn LLVMRustPrintPassTimings(OutStr: &RustString); /// Prints the statistics collected by `-Zprint-codegen-stats`. - #[expect(improper_ctypes)] pub(crate) fn LLVMRustPrintStatistics(OutStr: &RustString); /// Prepares inline assembly. @@ -1791,7 +1789,6 @@ pub fn LLVMRustInlineAsmVerify( ConstraintsLen: size_t, ) -> bool; - #[allow(improper_ctypes)] pub(crate) fn LLVMRustCoverageWriteFilenamesToBuffer( Filenames: *const *const c_char, FilenamesLen: size_t, @@ -1800,7 +1797,6 @@ pub(crate) fn LLVMRustCoverageWriteFilenamesToBuffer( BufferOut: &RustString, ); - #[allow(improper_ctypes)] pub(crate) fn LLVMRustCoverageWriteFunctionMappingsToBuffer( VirtualFileMappingIDs: *const c_uint, NumVirtualFileMappingIDs: size_t, @@ -1824,13 +1820,10 @@ pub(crate) fn LLVMRustCoverageCreatePGOFuncNameVar( ) -> &Value; pub(crate) fn LLVMRustCoverageHashBytes(Bytes: *const c_char, NumBytes: size_t) -> u64; - #[allow(improper_ctypes)] pub(crate) fn LLVMRustCoverageWriteCovmapSectionNameToString(M: &Module, OutStr: &RustString); - #[allow(improper_ctypes)] pub(crate) fn LLVMRustCoverageWriteCovfunSectionNameToString(M: &Module, OutStr: &RustString); - #[allow(improper_ctypes)] pub(crate) fn LLVMRustCoverageWriteCovmapVarNameToString(OutStr: &RustString); pub(crate) fn LLVMRustCoverageMappingVersion() -> u32; @@ -2185,14 +2178,11 @@ pub fn LLVMRustDIBuilderCreateDebugLocation<'a>( pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> u64; pub fn LLVMRustDIBuilderCreateOpLLVMFragment() -> u64; - #[allow(improper_ctypes)] pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString); - #[allow(improper_ctypes)] pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; - #[allow(improper_ctypes)] pub(crate) fn LLVMRustPrintTargetCPUs(TM: &TargetMachine, OutStr: &RustString); pub fn LLVMRustGetTargetFeaturesCount(T: &TargetMachine) -> size_t; pub fn LLVMRustGetTargetFeature( @@ -2297,10 +2287,8 @@ pub fn LLVMRustArchiveIteratorNext<'a>( pub fn LLVMRustArchiveIteratorFree<'a>(AIR: &'a mut ArchiveIterator<'a>); pub fn LLVMRustDestroyArchive(AR: &'static mut Archive); - #[allow(improper_ctypes)] pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString); - #[allow(improper_ctypes)] pub fn LLVMRustUnpackOptimizationDiagnostic<'a>( DI: &'a DiagnosticInfo, pass_name_out: &RustString, @@ -2318,7 +2306,6 @@ pub fn LLVMRustUnpackInlineAsmDiagnostic<'a>( message_out: &mut Option<&'a Twine>, ); - #[allow(improper_ctypes)] pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString); pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind; @@ -2327,7 +2314,6 @@ pub fn LLVMRustGetSMDiagnostic<'a>( cookie_out: &mut c_uint, ) -> &'a SMDiagnostic; - #[allow(improper_ctypes)] pub fn LLVMRustUnpackSMDiagnostic( d: &SMDiagnostic, message_out: &RustString, @@ -2374,7 +2360,6 @@ pub fn LLVMRustWriteImportLibrary( pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize; pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer); pub fn LLVMRustModuleCost(M: &Module) -> u64; - #[allow(improper_ctypes)] pub fn LLVMRustModuleInstructionStats(M: &Module, Str: &RustString); pub fn LLVMRustThinLTOBufferCreate( @@ -2427,7 +2412,6 @@ pub fn LLVMRustLinkerAdd( bytecode_len: usize, ) -> bool; pub fn LLVMRustLinkerFree<'a>(linker: &'a mut Linker<'a>); - #[allow(improper_ctypes)] pub fn LLVMRustComputeLTOCacheKey( key_out: &RustString, mod_id: *const c_char, @@ -2450,7 +2434,6 @@ pub fn LLVMRustContextConfigureDiagnosticHandler( pgo_available: bool, ); - #[allow(improper_ctypes)] pub fn LLVMRustGetMangledName(V: &Value, out: &RustString); pub fn LLVMRustGetElementTypeArgIndex(CallSite: &Value) -> i32; diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 3b0bf47366e..909afe35a17 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -1,6 +1,5 @@ #![allow(non_snake_case)] -use std::cell::RefCell; use std::ffi::{CStr, CString}; use std::ops::Deref; use std::ptr; @@ -301,15 +300,11 @@ pub fn set_value_name(value: &Value, name: &[u8]) { } pub fn build_string(f: impl FnOnce(&RustString)) -> Result { - let sr = RustString { bytes: RefCell::new(Vec::new()) }; - f(&sr); - String::from_utf8(sr.bytes.into_inner()) + String::from_utf8(RustString::build_byte_buffer(f)) } pub fn build_byte_buffer(f: impl FnOnce(&RustString)) -> Vec { - let sr = RustString { bytes: RefCell::new(Vec::new()) }; - f(&sr); - sr.bytes.into_inner() + RustString::build_byte_buffer(f) } pub fn twine_to_string(tr: &Twine) -> String { diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index 73bbc9de855..76f7d054040 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -104,8 +104,9 @@ typedef struct OpaqueRustString *RustStringRef; typedef struct LLVMOpaqueTwine *LLVMTwineRef; typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef; -extern "C" void LLVMRustStringWriteImpl(RustStringRef Str, const char *Ptr, - size_t Size); +extern "C" void LLVMRustStringWriteImpl(RustStringRef buf, + const char *slice_ptr, + size_t slice_len); class RawRustStringOstream : public llvm::raw_ostream { RustStringRef Str; diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs index 055d2bd5bc9..eda9b2b1fc0 100644 --- a/compiler/rustc_llvm/src/lib.rs +++ b/compiler/rustc_llvm/src/lib.rs @@ -2,42 +2,75 @@ #![allow(internal_features)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(rust_logo)] +#![feature(extern_types)] #![feature(rustdoc_internals)] #![warn(unreachable_pub)] // tidy-alphabetical-end -// NOTE: This crate only exists to allow linking on mingw targets. - use std::cell::RefCell; -use std::slice; +use std::{ptr, slice}; -use libc::{c_char, size_t}; +use libc::size_t; -#[repr(C)] -pub struct RustString { - pub bytes: RefCell>, +unsafe extern "C" { + /// Opaque type that allows C++ code to write bytes to a Rust-side buffer, + /// in conjunction with `RawRustStringOstream`. Use this as `&RustString` + /// (Rust) and `RustStringRef` (C++) in FFI signatures. + pub type RustString; } impl RustString { - pub fn len(&self) -> usize { - self.bytes.borrow().len() - } - - pub fn is_empty(&self) -> bool { - self.bytes.borrow().is_empty() + pub fn build_byte_buffer(closure: impl FnOnce(&Self)) -> Vec { + let buf = RustStringInner::default(); + closure(buf.as_opaque()); + buf.into_inner() } } -/// Appending to a Rust string -- used by RawRustStringOstream. +/// Underlying implementation of [`RustString`]. +/// +/// Having two separate types makes it possible to use the opaque [`RustString`] +/// in FFI signatures without `improper_ctypes` warnings. This is a workaround +/// for the fact that there is no way to opt out of `improper_ctypes` when +/// _declaring_ a type (as opposed to using that type). +#[derive(Default)] +struct RustStringInner { + bytes: RefCell>, +} + +impl RustStringInner { + fn as_opaque(&self) -> &RustString { + let ptr: *const RustStringInner = ptr::from_ref(self); + // We can't use `ptr::cast` here because extern types are `!Sized`. + let ptr = ptr as *const RustString; + unsafe { &*ptr } + } + + fn from_opaque(opaque: &RustString) -> &Self { + // SAFETY: A valid `&RustString` must have been created via `as_opaque`. + let ptr: *const RustString = ptr::from_ref(opaque); + let ptr: *const RustStringInner = ptr.cast(); + unsafe { &*ptr } + } + + fn into_inner(self) -> Vec { + self.bytes.into_inner() + } +} + +/// Appends the contents of a byte slice to a [`RustString`]. +/// +/// This function is implemented in `rustc_llvm` so that the C++ code in this +/// crate can link to it directly, without an implied link-time dependency on +/// `rustc_codegen_llvm`. #[unsafe(no_mangle)] pub unsafe extern "C" fn LLVMRustStringWriteImpl( - sr: &RustString, - ptr: *const c_char, - size: size_t, + buf: &RustString, + slice_ptr: *const u8, // Same ABI as `*const c_char` + slice_len: size_t, ) { - let slice = unsafe { slice::from_raw_parts(ptr as *const u8, size) }; - - sr.bytes.borrow_mut().extend_from_slice(slice); + let slice = unsafe { slice::from_raw_parts(slice_ptr, slice_len) }; + RustStringInner::from_opaque(buf).bytes.borrow_mut().extend_from_slice(slice); } /// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`. From 22069682ed634066efb6dd9e8af0956d1704ab05 Mon Sep 17 00:00:00 2001 From: Maybe Lapkin Date: Sat, 9 Nov 2024 00:37:29 +0100 Subject: [PATCH 40/54] Use a separate dir for r-a builds consistently in helix config --- src/etc/rust_analyzer_helix.toml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/etc/rust_analyzer_helix.toml b/src/etc/rust_analyzer_helix.toml index 9998ebcc03c..afddd089eb1 100644 --- a/src/etc/rust_analyzer_helix.toml +++ b/src/etc/rust_analyzer_helix.toml @@ -1,3 +1,12 @@ +# This config uses a separate build directory for rust-analyzer, +# so that r-a's checks don't block user `x` commands and vice-verse. +# R-a's build directory is located in `build/rust-analyzer`. +# +# To build rustfmt and proc macro server for r-a run the following command: +# ``` +# x b proc-macro-srv-cli rustfmt --stage 0 --build-dir build/rust-analyzer +# ``` + [language-server.rust-analyzer.config] linkedProjects = [ "Cargo.toml", @@ -17,16 +26,18 @@ overrideCommand = [ "x.py", "check", "--json-output", + "--build-dir", + "build/rust-analyzer", ] [language-server.rust-analyzer.config.rustfmt] overrideCommand = [ - "build-rust-analyzer/host/rustfmt/bin/rustfmt", + "build/rust-analyzer/host/rustfmt/bin/rustfmt", "--edition=2021" ] [language-server.rust-analyzer.config.procMacro] -server = "build-rust-analyzer/host/stage0/libexec/rust-analyzer-proc-macro-srv" +server = "build/rust-analyzer/host/stage0/libexec/rust-analyzer-proc-macro-srv" enable = true [language-server.rust-analyzer.config.rustc] @@ -47,4 +58,6 @@ overrideCommand = [ "x.py", "check", "--json-output", + "--build-dir", + "build/rust-analyzer", ] From cea82ed1626f00930845ea48e3485eae8d44b422 Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 8 Nov 2024 13:47:36 -0800 Subject: [PATCH 41/54] Don't suggest `.into_iter()` on iterators --- .../rustc_hir_typeck/src/method/suggest.rs | 18 ++++++------ .../iterator-does-not-need-into-iter.rs | 18 ++++++++++++ .../iterator-does-not-need-into-iter.stderr | 28 +++++++++++++++++++ 3 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 tests/ui/iterators/iterator-does-not-need-into-iter.rs create mode 100644 tests/ui/iterators/iterator-does-not-need-into-iter.stderr diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index eaf40a193a6..cb20a1d7c7b 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -100,9 +100,9 @@ fn impl_into_iterator_should_be_iterator( ty: Ty<'tcx>, span: Span, unsatisfied_predicates: &Vec<( - ty::Predicate<'_>, - Option>, - Option>, + ty::Predicate<'tcx>, + Option>, + Option>, )>, ) -> bool { fn predicate_bounds_generic_param<'tcx>( @@ -131,15 +131,17 @@ fn predicate_bounds_generic_param<'tcx>( } } - fn is_iterator_predicate(predicate: ty::Predicate<'_>, tcx: TyCtxt<'_>) -> bool { + let is_iterator_predicate = |predicate: ty::Predicate<'tcx>| -> bool { if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = predicate.kind().as_ref().skip_binder() { - tcx.is_diagnostic_item(sym::Iterator, trait_pred.trait_ref.def_id) + self.tcx.is_diagnostic_item(sym::Iterator, trait_pred.trait_ref.def_id) + // ignore unsatisfied predicates generated from trying to auto-ref ty (#127511) + && trait_pred.trait_ref.self_ty() == ty } else { false } - } + }; // Does the `ty` implement `IntoIterator`? let Some(into_iterator_trait) = self.tcx.get_diagnostic_item(sym::IntoIterator) else { @@ -164,7 +166,7 @@ fn is_iterator_predicate(predicate: ty::Predicate<'_>, tcx: TyCtxt<'_>) -> bool generics, generic_param, self.tcx, - ) && is_iterator_predicate(unsatisfied.0, self.tcx) + ) && is_iterator_predicate(unsatisfied.0) { return true; } @@ -172,7 +174,7 @@ fn is_iterator_predicate(predicate: ty::Predicate<'_>, tcx: TyCtxt<'_>) -> bool } ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::Opaque, _) => { for unsatisfied in unsatisfied_predicates.iter() { - if is_iterator_predicate(unsatisfied.0, self.tcx) { + if is_iterator_predicate(unsatisfied.0) { return true; } } diff --git a/tests/ui/iterators/iterator-does-not-need-into-iter.rs b/tests/ui/iterators/iterator-does-not-need-into-iter.rs new file mode 100644 index 00000000000..29196449e30 --- /dev/null +++ b/tests/ui/iterators/iterator-does-not-need-into-iter.rs @@ -0,0 +1,18 @@ +//! regression test for #127511: don't suggest `.into_iter()` on iterators + +trait Missing {} +trait HasMethod { + fn foo(self); +} +impl HasMethod for T { + fn foo(self) {} +} + +fn get_iter() -> impl Iterator { + core::iter::once(()) +} + +fn main() { + get_iter().foo(); + //~^ ERROR the method `foo` exists for opaque type `impl Iterator`, but its trait bounds were not satisfied [E0599] +} diff --git a/tests/ui/iterators/iterator-does-not-need-into-iter.stderr b/tests/ui/iterators/iterator-does-not-need-into-iter.stderr new file mode 100644 index 00000000000..3d3861e959f --- /dev/null +++ b/tests/ui/iterators/iterator-does-not-need-into-iter.stderr @@ -0,0 +1,28 @@ +error[E0599]: the method `foo` exists for opaque type `impl Iterator`, but its trait bounds were not satisfied + --> $DIR/iterator-does-not-need-into-iter.rs:16:16 + | +LL | get_iter().foo(); + | ^^^ method cannot be called on `impl Iterator` due to unsatisfied trait bounds + | +note: the following trait bounds were not satisfied: + `&impl Iterator: Iterator` + `&impl Iterator: Missing` + `&mut impl Iterator: Missing` + `impl Iterator: Missing` + --> $DIR/iterator-does-not-need-into-iter.rs:7:9 + | +LL | impl HasMethod for T { + | ^^^^^^^^ ^^^^^^^ --------- - + | | | + | | unsatisfied trait bound introduced here + | unsatisfied trait bound introduced here + = help: items from traits can only be used if the trait is implemented and in scope +note: `HasMethod` defines an item `foo`, perhaps you need to implement it + --> $DIR/iterator-does-not-need-into-iter.rs:4:1 + | +LL | trait HasMethod { + | ^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From 13ab08d7dc353d1d30ad055eea4c7ec4e5310237 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 9 Nov 2024 03:54:08 +0000 Subject: [PATCH 42/54] Do not reveal opaques in the param-env, we got lazy norm instead --- compiler/rustc_middle/src/ty/mod.rs | 11 ++++++----- compiler/rustc_middle/src/ty/util.rs | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6d9ba3d60e3..1a3128ed936 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1076,11 +1076,6 @@ pub fn new(caller_bounds: Clauses<'tcx>, reveal: Reveal) -> Self { ty::ParamEnv { packed: CopyTaggedPtr::new(caller_bounds, ParamTag { reveal }) } } - pub fn with_user_facing(mut self) -> Self { - self.packed.set_tag(ParamTag { reveal: Reveal::UserFacing, ..self.packed.tag() }); - self - } - /// Returns a new parameter environment with the same clauses, but /// which "reveals" the true results of projections in all cases /// (even for associated types that are specializable). This is @@ -1095,6 +1090,12 @@ pub fn with_reveal_all_normalized(self, tcx: TyCtxt<'tcx>) -> Self { return self; } + // No need to reveal opaques with the new solver enabled, + // since we have lazy norm. + if tcx.next_trait_solver_globally() { + return ParamEnv::new(self.caller_bounds(), Reveal::All); + } + ParamEnv::new(tcx.reveal_opaque_types_in_bounds(self.caller_bounds()), Reveal::All) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index fc5a3b762e5..3c6e34160f4 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1751,6 +1751,7 @@ pub fn reveal_opaque_types_in_bounds<'tcx>( tcx: TyCtxt<'tcx>, val: ty::Clauses<'tcx>, ) -> ty::Clauses<'tcx> { + assert!(!tcx.next_trait_solver_globally()); let mut visitor = OpaqueTypeExpander { seen_opaque_tys: FxHashSet::default(), expanded_cache: FxHashMap::default(), From d37e6dfee8afcf0482dd12dbe82d2caf26606675 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 9 Nov 2024 00:18:47 -0600 Subject: [PATCH 43/54] Add str to "expected primitive, found type" diagnostic --- compiler/rustc_middle/src/ty/sty.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e27bb2fd135..142db8a17f0 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1933,6 +1933,7 @@ pub fn primitive_symbol(self) -> Option { ty::UintTy::U64 => Some(sym::u64), ty::UintTy::U128 => Some(sym::u128), }, + ty::Str => Some(sym::str), _ => None, } } From 5f6645dc51e0e8dbb57bf815e19e59007f25d762 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 9 Nov 2024 00:23:53 -0600 Subject: [PATCH 44/54] Add test for str for "expected primitive, found type" --- .../similar_paths_primitive.rs | 4 +++ .../similar_paths_primitive.stderr | 27 ++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/tests/ui/mismatched_types/similar_paths_primitive.rs b/tests/ui/mismatched_types/similar_paths_primitive.rs index 8f5b7cce469..98890a15d98 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.rs +++ b/tests/ui/mismatched_types/similar_paths_primitive.rs @@ -1,10 +1,14 @@ #![allow(non_camel_case_types)] struct bool; +struct str; fn foo(_: bool) {} +fn bar(_: &str) {} fn main() { foo(true); //~^ ERROR mismatched types [E0308] + bar("hello"); + //~^ ERROR mismatched types [E0308] } diff --git a/tests/ui/mismatched_types/similar_paths_primitive.stderr b/tests/ui/mismatched_types/similar_paths_primitive.stderr index c9881891319..0530bf5863e 100644 --- a/tests/ui/mismatched_types/similar_paths_primitive.stderr +++ b/tests/ui/mismatched_types/similar_paths_primitive.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/similar_paths_primitive.rs:8:9 + --> $DIR/similar_paths_primitive.rs:10:9 | LL | foo(true); | --- ^^^^ expected `bool`, found a different `bool` @@ -14,11 +14,32 @@ note: `bool` is defined in the current crate LL | struct bool; | ^^^^^^^^^^^ note: function defined here - --> $DIR/similar_paths_primitive.rs:5:4 + --> $DIR/similar_paths_primitive.rs:6:4 | LL | fn foo(_: bool) {} | ^^^ ------- -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/similar_paths_primitive.rs:12:9 + | +LL | bar("hello"); + | --- ^^^^^^^ expected `str`, found a different `str` + | | + | arguments to this function are incorrect + | + = note: str and `str` have similar names, but are actually distinct types + = note: str is a primitive defined by the language +note: `str` is defined in the current crate + --> $DIR/similar_paths_primitive.rs:4:1 + | +LL | struct str; + | ^^^^^^^^^^ +note: function defined here + --> $DIR/similar_paths_primitive.rs:7:4 + | +LL | fn bar(_: &str) {} + | ^^^ ------- + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. From 30a2ae6f05ff9e0abbaa9cd308bbceb6ddeede32 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Nov 2024 11:13:44 +0100 Subject: [PATCH 45/54] interpret: get_alloc_info: also return mutability --- .../src/const_eval/eval_queries.rs | 2 +- .../rustc_const_eval/src/interpret/memory.rs | 39 ++++++++++++------- .../src/interpret/validity.rs | 2 +- src/tools/miri/src/alloc_addresses/mod.rs | 2 +- src/tools/miri/src/borrow_tracker/mod.rs | 2 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 4 +- .../src/borrow_tracker/tree_borrows/mod.rs | 2 +- src/tools/miri/src/machine.rs | 2 +- src/tools/miri/src/shims/foreign_items.rs | 2 +- 9 files changed, 34 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 81b9d73b952..4055e3f0d50 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -472,7 +472,7 @@ fn report_validation_error<'tcx>( backtrace.print_backtrace(); let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id); - let (size, align, _) = ecx.get_alloc_info(alloc_id); + let (size, align, ..) = ecx.get_alloc_info(alloc_id); let raw_bytes = errors::RawBytesNote { size: size.bytes(), align: align.bytes(), bytes }; crate::const_eval::report( diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 1ad8ffa4b53..cc7ce1df923 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -524,7 +524,7 @@ fn is_offset_misaligned(offset: u64, align: Align) -> Option { match self.ptr_try_get_alloc_id(ptr, 0) { Err(addr) => is_offset_misaligned(addr, align), Ok((alloc_id, offset, _prov)) => { - let (_size, alloc_align, kind) = self.get_alloc_info(alloc_id); + let (_size, alloc_align, kind, _mutbl) = self.get_alloc_info(alloc_id); if let Some(misalign) = M::alignment_check(self, alloc_id, alloc_align, kind, offset, align) { @@ -818,19 +818,19 @@ pub fn is_alloc_live(&self, id: AllocId) -> bool { /// Obtain the size and alignment of an allocation, even if that allocation has /// been deallocated. - pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) { + pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind, Mutability) { // # Regular allocations // Don't use `self.get_raw` here as that will // a) cause cycles in case `id` refers to a static // b) duplicate a global's allocation in miri if let Some((_, alloc)) = self.memory.alloc_map.get(id) { - return (alloc.size(), alloc.align, AllocKind::LiveData); + return (alloc.size(), alloc.align, AllocKind::LiveData, alloc.mutability); } // # Function pointers // (both global from `alloc_map` and local from `extra_fn_ptr_map`) if self.get_fn_alloc(id).is_some() { - return (Size::ZERO, Align::ONE, AllocKind::Function); + return (Size::ZERO, Align::ONE, AllocKind::Function, Mutability::Not); } // # Statics @@ -842,17 +842,17 @@ pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) { // `ThreadLocalRef`; we can never have a pointer to them as a regular constant value. assert!(!self.tcx.is_thread_local_static(def_id)); - let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { + let DefKind::Static { nested, mutability, .. } = self.tcx.def_kind(def_id) else { bug!("GlobalAlloc::Static is not a static") }; - let (size, align) = if nested { + let (size, align, mutability) = if nested { // Nested anonymous statics are untyped, so let's get their // size and alignment from the allocation itself. This always // succeeds, as the query is fed at DefId creation time, so no // evaluation actually occurs. let alloc = self.tcx.eval_static_initializer(def_id).unwrap(); - (alloc.0.size(), alloc.0.align) + (alloc.0.size(), alloc.0.align, alloc.0.mutability) } else { // Use size and align of the type for everything else. We need // to do that to @@ -865,22 +865,33 @@ pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) { .expect("statics should not have generic parameters"); let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); assert!(layout.is_sized()); - (layout.size, layout.align.abi) + let mutability = match mutability { + Mutability::Not if !ty.is_freeze(*self.tcx, ParamEnv::empty()) => { + Mutability::Not + } + _ => Mutability::Mut, + }; + (layout.size, layout.align.abi, mutability) }; - (size, align, AllocKind::LiveData) + (size, align, AllocKind::LiveData, mutability) } Some(GlobalAlloc::Memory(alloc)) => { // Need to duplicate the logic here, because the global allocations have // different associated types than the interpreter-local ones. let alloc = alloc.inner(); - (alloc.size(), alloc.align, AllocKind::LiveData) + (alloc.size(), alloc.align, AllocKind::LiveData, alloc.mutability) } Some(GlobalAlloc::Function { .. }) => { bug!("We already checked function pointers above") } Some(GlobalAlloc::VTable(..)) => { // No data to be accessed here. But vtables are pointer-aligned. - return (Size::ZERO, self.tcx.data_layout.pointer_align.abi, AllocKind::VTable); + return ( + Size::ZERO, + self.tcx.data_layout.pointer_align.abi, + AllocKind::VTable, + Mutability::Not, + ); } // The rest must be dead. None => { @@ -891,7 +902,7 @@ pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind) { .dead_alloc_map .get(&id) .expect("deallocated pointers should all be recorded in `dead_alloc_map`"); - (size, align, AllocKind::Dead) + (size, align, AllocKind::Dead, Mutability::Not) } } } @@ -902,7 +913,7 @@ fn get_live_alloc_size_and_align( id: AllocId, msg: CheckInAllocMsg, ) -> InterpResult<'tcx, (Size, Align)> { - let (size, align, kind) = self.get_alloc_info(id); + let (size, align, kind, _mutbl) = self.get_alloc_info(id); if matches!(kind, AllocKind::Dead) { throw_ub!(PointerUseAfterFree(id, msg)) } @@ -1458,7 +1469,7 @@ pub fn scalar_may_be_null(&self, scalar: Scalar) -> InterpResult< let ptr = scalar.to_pointer(self)?; match self.ptr_try_get_alloc_id(ptr, 0) { Ok((alloc_id, offset, _)) => { - let (size, _align, _kind) = self.get_alloc_info(alloc_id); + let (size, _align, _kind, _mutbl) = self.get_alloc_info(alloc_id); // If the pointer is out-of-bounds, it may be null. // Note that one-past-the-end (offset == size) is still inbounds, and never null. offset > size diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index cd2c1ef3613..d7532c6e01a 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -594,7 +594,7 @@ fn check_safe_pointer( } // Dangling and Mutability check. - let (size, _align, alloc_kind) = self.ecx.get_alloc_info(alloc_id); + let (size, _align, alloc_kind, _mutbl) = self.ecx.get_alloc_info(alloc_id); if alloc_kind == AllocKind::Dead { // This can happen for zero-sized references. We can't have *any* references to // non-existing allocations in const-eval though, interning rejects them all as diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 7b377a1c4cd..8b59ca63a43 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -157,7 +157,7 @@ fn addr_from_alloc_id_uncached( ) -> InterpResult<'tcx, u64> { let ecx = self.eval_context_ref(); let mut rng = ecx.machine.rng.borrow_mut(); - let (size, align, kind) = ecx.get_alloc_info(alloc_id); + let (size, align, kind, _mutbl) = ecx.get_alloc_info(alloc_id); // This is either called immediately after allocation (and then cached), or when // adjusting `tcx` pointers (which never get freed). So assert that we are looking // at a live allocation. This also ensures that we never re-assign an address to an diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 72319decb94..3ee00a1dcf4 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -363,7 +363,7 @@ fn on_stack_pop( // If it does exist, then we have the guarantee that the // pointer is readable, and the implicit read access inserted // will never cause UB on the pointer itself. - let (_, _, kind) = this.get_alloc_info(*alloc_id); + let (_, _, kind, _mutbl) = this.get_alloc_info(*alloc_id); if matches!(kind, AllocKind::LiveData) { let alloc_extra = this.get_alloc_extra(*alloc_id)?; // can still fail for `extern static` let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap(); diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index 47fe41d9ecd..b42b70b4d2f 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -626,7 +626,7 @@ fn sb_reborrow( return interp_ok(()) }; - let (_size, _align, alloc_kind) = this.get_alloc_info(alloc_id); + let (_size, _align, alloc_kind, _mutbl) = this.get_alloc_info(alloc_id); match alloc_kind { AllocKind::LiveData => { // This should have alloc_extra data, but `get_alloc_extra` can still fail @@ -1017,7 +1017,7 @@ fn sb_expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx // Function pointers and dead objects don't have an alloc_extra so we ignore them. // This is okay because accessing them is UB anyway, no need for any Stacked Borrows checks. // NOT using `get_alloc_extra_mut` since this might be a read-only allocation! - let (_size, _align, kind) = this.get_alloc_info(alloc_id); + let (_size, _align, kind, _mutbl) = this.get_alloc_info(alloc_id); match kind { AllocKind::LiveData => { // This should have alloc_extra data, but `get_alloc_extra` can still fail diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 40467aa4bc1..799950e4c94 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -538,7 +538,7 @@ fn tb_expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx // Function pointers and dead objects don't have an alloc_extra so we ignore them. // This is okay because accessing them is UB anyway, no need for any Tree Borrows checks. // NOT using `get_alloc_extra_mut` since this might be a read-only allocation! - let (_size, _align, kind) = this.get_alloc_info(alloc_id); + let (_size, _align, kind, _mutbl) = this.get_alloc_info(alloc_id); match kind { AllocKind::LiveData => { // This should have alloc_extra data, but `get_alloc_extra` can still fail diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 72e8952c543..c8c9070f290 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1125,7 +1125,7 @@ fn extern_static_pointer( let Provenance::Concrete { alloc_id, .. } = ptr.provenance else { panic!("extern_statics cannot contain wildcards") }; - let (shim_size, shim_align, _kind) = ecx.get_alloc_info(alloc_id); + let (shim_size, shim_align, _kind, _mutbl) = ecx.get_alloc_info(alloc_id); let def_ty = ecx.tcx.type_of(def_id).instantiate_identity(); let extern_decl_layout = ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap(); if extern_decl_layout.size != shim_size || extern_decl_layout.align.abi != shim_align { diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 18578c7acc9..a6733af9faa 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -409,7 +409,7 @@ fn emulate_foreign_item_inner( ); } if let Ok((alloc_id, offset, ..)) = this.ptr_try_get_alloc_id(ptr, 0) { - let (_size, alloc_align, _kind) = this.get_alloc_info(alloc_id); + let (_size, alloc_align, _kind, _mutbl) = this.get_alloc_info(alloc_id); // If the newly promised alignment is bigger than the native alignment of this // allocation, and bigger than the previously promised alignment, then set it. if align > alloc_align From 1fa693ca4462fc1f790693464cf765ad693616af Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 9 Nov 2024 13:28:28 +0000 Subject: [PATCH 46/54] Rustup to rustc 1.84.0-nightly (59cec72a5 2024-11-08) --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index af89725b72c..a223cd7dbb8 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-11-07" +channel = "nightly-2024-11-09" components = ["rust-src", "rustc-dev", "llvm-tools"] profile = "minimal" From 4a54ec8c18be3e1b66b9efc627e356904201a348 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Nov 2024 13:13:31 +0100 Subject: [PATCH 47/54] make return type of get_alloc_info a struct, and reduce some code duplication with validity checking --- .../src/const_eval/eval_queries.rs | 5 +- .../rustc_const_eval/src/interpret/memory.rs | 143 +++++++----------- .../rustc_const_eval/src/interpret/mod.rs | 2 +- .../src/interpret/validity.rs | 91 ++++------- .../rustc_middle/src/mir/interpret/mod.rs | 86 ++++++++++- src/tools/miri/src/alloc_addresses/mod.rs | 18 +-- src/tools/miri/src/borrow_tracker/mod.rs | 2 +- .../src/borrow_tracker/stacked_borrows/mod.rs | 4 +- .../src/borrow_tracker/tree_borrows/mod.rs | 4 +- src/tools/miri/src/machine.rs | 8 +- src/tools/miri/src/shims/foreign_items.rs | 4 +- 11 files changed, 190 insertions(+), 177 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 4055e3f0d50..a430d9dc797 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -472,8 +472,9 @@ fn report_validation_error<'tcx>( backtrace.print_backtrace(); let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id); - let (size, align, ..) = ecx.get_alloc_info(alloc_id); - let raw_bytes = errors::RawBytesNote { size: size.bytes(), align: align.bytes(), bytes }; + let info = ecx.get_alloc_info(alloc_id); + let raw_bytes = + errors::RawBytesNote { size: info.size.bytes(), align: info.align.bytes(), bytes }; crate::const_eval::report( *ecx.tcx, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index cc7ce1df923..09635c96e57 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -14,10 +14,9 @@ use rustc_abi::{Align, HasDataLayout, Size}; use rustc_ast::Mutability; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; -use rustc_hir::def::DefKind; use rustc_middle::bug; use rustc_middle::mir::display_allocation; -use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use tracing::{debug, instrument, trace}; use super::{ @@ -72,6 +71,21 @@ pub enum AllocKind { Dead, } +/// Metadata about an `AllocId`. +#[derive(Copy, Clone, PartialEq, Debug)] +pub struct AllocInfo { + pub size: Size, + pub align: Align, + pub kind: AllocKind, + pub mutbl: Mutability, +} + +impl AllocInfo { + fn new(size: Size, align: Align, kind: AllocKind, mutbl: Mutability) -> Self { + Self { size, align, kind, mutbl } + } +} + /// The value of a function pointer. #[derive(Debug, Copy, Clone)] pub enum FnVal<'tcx, Other> { @@ -524,17 +538,22 @@ fn is_offset_misaligned(offset: u64, align: Align) -> Option { match self.ptr_try_get_alloc_id(ptr, 0) { Err(addr) => is_offset_misaligned(addr, align), Ok((alloc_id, offset, _prov)) => { - let (_size, alloc_align, kind, _mutbl) = self.get_alloc_info(alloc_id); - if let Some(misalign) = - M::alignment_check(self, alloc_id, alloc_align, kind, offset, align) - { + let alloc_info = self.get_alloc_info(alloc_id); + if let Some(misalign) = M::alignment_check( + self, + alloc_id, + alloc_info.align, + alloc_info.kind, + offset, + align, + ) { Some(misalign) } else if M::Provenance::OFFSET_IS_ADDR { is_offset_misaligned(ptr.addr().bytes(), align) } else { // Check allocation alignment and offset alignment. - if alloc_align.bytes() < align.bytes() { - Some(Misalignment { has: alloc_align, required: align }) + if alloc_info.align.bytes() < align.bytes() { + Some(Misalignment { has: alloc_info.align, required: align }) } else { is_offset_misaligned(offset.bytes(), align) } @@ -818,93 +837,45 @@ pub fn is_alloc_live(&self, id: AllocId) -> bool { /// Obtain the size and alignment of an allocation, even if that allocation has /// been deallocated. - pub fn get_alloc_info(&self, id: AllocId) -> (Size, Align, AllocKind, Mutability) { + pub fn get_alloc_info(&self, id: AllocId) -> AllocInfo { // # Regular allocations // Don't use `self.get_raw` here as that will // a) cause cycles in case `id` refers to a static // b) duplicate a global's allocation in miri if let Some((_, alloc)) = self.memory.alloc_map.get(id) { - return (alloc.size(), alloc.align, AllocKind::LiveData, alloc.mutability); + return AllocInfo::new( + alloc.size(), + alloc.align, + AllocKind::LiveData, + alloc.mutability, + ); } // # Function pointers // (both global from `alloc_map` and local from `extra_fn_ptr_map`) if self.get_fn_alloc(id).is_some() { - return (Size::ZERO, Align::ONE, AllocKind::Function, Mutability::Not); + return AllocInfo::new(Size::ZERO, Align::ONE, AllocKind::Function, Mutability::Not); } - // # Statics - // Can't do this in the match argument, we may get cycle errors since the lock would - // be held throughout the match. - match self.tcx.try_get_global_alloc(id) { - Some(GlobalAlloc::Static(def_id)) => { - // Thread-local statics do not have a constant address. They *must* be accessed via - // `ThreadLocalRef`; we can never have a pointer to them as a regular constant value. - assert!(!self.tcx.is_thread_local_static(def_id)); - - let DefKind::Static { nested, mutability, .. } = self.tcx.def_kind(def_id) else { - bug!("GlobalAlloc::Static is not a static") - }; - - let (size, align, mutability) = if nested { - // Nested anonymous statics are untyped, so let's get their - // size and alignment from the allocation itself. This always - // succeeds, as the query is fed at DefId creation time, so no - // evaluation actually occurs. - let alloc = self.tcx.eval_static_initializer(def_id).unwrap(); - (alloc.0.size(), alloc.0.align, alloc.0.mutability) - } else { - // Use size and align of the type for everything else. We need - // to do that to - // * avoid cycle errors in case of self-referential statics, - // * be able to get information on extern statics. - let ty = self - .tcx - .type_of(def_id) - .no_bound_vars() - .expect("statics should not have generic parameters"); - let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap(); - assert!(layout.is_sized()); - let mutability = match mutability { - Mutability::Not if !ty.is_freeze(*self.tcx, ParamEnv::empty()) => { - Mutability::Not - } - _ => Mutability::Mut, - }; - (layout.size, layout.align.abi, mutability) - }; - (size, align, AllocKind::LiveData, mutability) - } - Some(GlobalAlloc::Memory(alloc)) => { - // Need to duplicate the logic here, because the global allocations have - // different associated types than the interpreter-local ones. - let alloc = alloc.inner(); - (alloc.size(), alloc.align, AllocKind::LiveData, alloc.mutability) - } - Some(GlobalAlloc::Function { .. }) => { - bug!("We already checked function pointers above") - } - Some(GlobalAlloc::VTable(..)) => { - // No data to be accessed here. But vtables are pointer-aligned. - return ( - Size::ZERO, - self.tcx.data_layout.pointer_align.abi, - AllocKind::VTable, - Mutability::Not, - ); - } - // The rest must be dead. - None => { - // Deallocated pointers are allowed, we should be able to find - // them in the map. - let (size, align) = *self - .memory - .dead_alloc_map - .get(&id) - .expect("deallocated pointers should all be recorded in `dead_alloc_map`"); - (size, align, AllocKind::Dead, Mutability::Not) - } + // # Global allocations + if let Some(global_alloc) = self.tcx.try_get_global_alloc(id) { + let (size, align) = global_alloc.size_and_align(*self.tcx, self.param_env); + let mutbl = global_alloc.mutability(*self.tcx, self.param_env); + let kind = match global_alloc { + GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData, + GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"), + GlobalAlloc::VTable { .. } => AllocKind::VTable, + }; + return AllocInfo::new(size, align, kind, mutbl); } + + // # Dead pointers + let (size, align) = *self + .memory + .dead_alloc_map + .get(&id) + .expect("deallocated pointers should all be recorded in `dead_alloc_map`"); + AllocInfo::new(size, align, AllocKind::Dead, Mutability::Not) } /// Obtain the size and alignment of a *live* allocation. @@ -913,11 +884,11 @@ fn get_live_alloc_size_and_align( id: AllocId, msg: CheckInAllocMsg, ) -> InterpResult<'tcx, (Size, Align)> { - let (size, align, kind, _mutbl) = self.get_alloc_info(id); - if matches!(kind, AllocKind::Dead) { + let info = self.get_alloc_info(id); + if matches!(info.kind, AllocKind::Dead) { throw_ub!(PointerUseAfterFree(id, msg)) } - interp_ok((size, align)) + interp_ok((info.size, info.align)) } fn get_fn_alloc(&self, id: AllocId) -> Option> { @@ -1469,7 +1440,7 @@ pub fn scalar_may_be_null(&self, scalar: Scalar) -> InterpResult< let ptr = scalar.to_pointer(self)?; match self.ptr_try_get_alloc_id(ptr, 0) { Ok((alloc_id, offset, _)) => { - let (size, _align, _kind, _mutbl) = self.get_alloc_info(alloc_id); + let size = self.get_alloc_info(alloc_id).size; // If the pointer is out-of-bounds, it may be null. // Note that one-past-the-end (offset == size) is still inbounds, and never null. offset > size diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs index 5e84626f77e..f5792aba207 100644 --- a/compiler/rustc_const_eval/src/interpret/mod.rs +++ b/compiler/rustc_const_eval/src/interpret/mod.rs @@ -31,7 +31,7 @@ }; pub(crate) use self::intrinsics::eval_nullary_intrinsic; pub use self::machine::{AllocMap, Machine, MayLeak, ReturnAction, compile_time_machine}; -pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; +pub use self::memory::{AllocInfo, AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind}; use self::operand::Operand; pub use self::operand::{ImmTy, Immediate, OpTy}; pub use self::place::{MPlaceTy, MemPlaceMeta, PlaceTy, Writeable}; diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index d7532c6e01a..3a68db9f7f7 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -31,8 +31,8 @@ use super::machine::AllocMap; use super::{ - AllocId, AllocKind, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, - MPlaceTy, Machine, MemPlaceMeta, PlaceTy, Pointer, Projectable, Scalar, ValueVisitor, err_ub, + AllocId, CheckInAllocMsg, GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, + Machine, MemPlaceMeta, PlaceTy, Pointer, Projectable, Scalar, ValueVisitor, err_ub, format_interp_error, }; @@ -557,9 +557,20 @@ fn check_safe_pointer( if let Ok((alloc_id, _offset, _prov)) = self.ecx.ptr_try_get_alloc_id(place.ptr(), 0) { - if let Some(GlobalAlloc::Static(did)) = - self.ecx.tcx.try_get_global_alloc(alloc_id) - { + // Everything should be already interned. + let Some(global_alloc) = self.ecx.tcx.try_get_global_alloc(alloc_id) else { + assert!(self.ecx.memory.alloc_map.get(alloc_id).is_none()); + // We can't have *any* references to non-existing allocations in const-eval + // as the rest of rustc isn't happy with them... so we throw an error, even + // though for zero-sized references this isn't really UB. + // A potential future alternative would be to resurrect this as a zero-sized allocation + // (which codegen will then compile to an aligned dummy pointer anyway). + throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); + }; + let (size, _align) = + global_alloc.size_and_align(*self.ecx.tcx, self.ecx.param_env); + + if let GlobalAlloc::Static(did) = global_alloc { let DefKind::Static { nested, .. } = self.ecx.tcx.def_kind(did) else { bug!() }; @@ -593,17 +604,6 @@ fn check_safe_pointer( } } - // Dangling and Mutability check. - let (size, _align, alloc_kind, _mutbl) = self.ecx.get_alloc_info(alloc_id); - if alloc_kind == AllocKind::Dead { - // This can happen for zero-sized references. We can't have *any* references to - // non-existing allocations in const-eval though, interning rejects them all as - // the rest of rustc isn't happy with them... so we throw an error, even though - // this isn't really UB. - // A potential future alternative would be to resurrect this as a zero-sized allocation - // (which codegen will then compile to an aligned dummy pointer anyway). - throw_validation_failure!(self.path, DanglingPtrUseAfterFree { ptr_kind }); - } // If this allocation has size zero, there is no actual mutability here. if size != Size::ZERO { // Determine whether this pointer expects to be pointing to something mutable. @@ -618,7 +618,8 @@ fn check_safe_pointer( } }; // Determine what it actually points to. - let alloc_actual_mutbl = mutability(self.ecx, alloc_id); + let alloc_actual_mutbl = + global_alloc.mutability(*self.ecx.tcx, self.ecx.param_env); // Mutable pointer to immutable memory is no good. if ptr_expected_mutbl == Mutability::Mut && alloc_actual_mutbl == Mutability::Not @@ -842,9 +843,16 @@ fn visit_scalar( } fn in_mutable_memory(&self, val: &PlaceTy<'tcx, M::Provenance>) -> bool { + debug_assert!(self.ctfe_mode.is_some()); if let Some(mplace) = val.as_mplace_or_local().left() { if let Some(alloc_id) = mplace.ptr().provenance.and_then(|p| p.get_alloc_id()) { - mutability(self.ecx, alloc_id).is_mut() + let tcx = *self.ecx.tcx; + // Everything must be already interned. + let mutbl = tcx.global_alloc(alloc_id).mutability(tcx, self.ecx.param_env); + if let Some((_, alloc)) = self.ecx.memory.alloc_map.get(alloc_id) { + assert_eq!(alloc.mutability, mutbl); + } + mutbl.is_mut() } else { // No memory at all. false @@ -1016,53 +1024,6 @@ fn union_data_range_uncached<'tcx>( } } -/// Returns whether the allocation is mutable, and whether it's actually a static. -/// For "root" statics we look at the type to account for interior -/// mutability; for nested statics we have no type and directly use the annotated mutability. -fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId) -> Mutability { - // Let's see what kind of memory this points to. - // We're not using `try_global_alloc` since dangling pointers have already been handled. - match ecx.tcx.global_alloc(alloc_id) { - GlobalAlloc::Static(did) => { - let DefKind::Static { safety: _, mutability, nested } = ecx.tcx.def_kind(did) else { - bug!() - }; - if nested { - assert!( - ecx.memory.alloc_map.get(alloc_id).is_none(), - "allocations of nested statics are already interned: {alloc_id:?}, {did:?}" - ); - // Nested statics in a `static` are never interior mutable, - // so just use the declared mutability. - mutability - } else { - let mutability = match mutability { - Mutability::Not - if !ecx - .tcx - .type_of(did) - .no_bound_vars() - .expect("statics should not have generic parameters") - .is_freeze(*ecx.tcx, ty::ParamEnv::reveal_all()) => - { - Mutability::Mut - } - _ => mutability, - }; - if let Some((_, alloc)) = ecx.memory.alloc_map.get(alloc_id) { - assert_eq!(alloc.mutability, mutability); - } - mutability - } - } - GlobalAlloc::Memory(alloc) => alloc.inner().mutability, - GlobalAlloc::Function { .. } | GlobalAlloc::VTable(..) => { - // These are immutable, we better don't allow mutable pointers here. - Mutability::Not - } - } -} - impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, 'tcx, M> { type V = PlaceTy<'tcx, M::Provenance>; diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index b0c0e1be500..f225ad94aa7 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -12,11 +12,12 @@ use std::num::NonZero; use std::{fmt, io}; -use rustc_abi::{AddressSpace, Endian, HasDataLayout}; -use rustc_ast::LitKind; +use rustc_abi::{AddressSpace, Align, Endian, HasDataLayout, Size}; +use rustc_ast::{LitKind, Mutability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lock; use rustc_errors::ErrorGuaranteed; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -45,7 +46,7 @@ pub use self::value::Scalar; use crate::mir; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::{self, Instance, Ty, TyCtxt}; +use crate::ty::{self, Instance, ParamEnv, Ty, TyCtxt}; /// Uniquely identifies one of the following: /// - A constant @@ -310,6 +311,85 @@ pub fn address_space(&self, cx: &impl HasDataLayout) -> AddressSpace { } } } + + pub fn mutability(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Mutability { + // Let's see what kind of memory we are. + match self { + GlobalAlloc::Static(did) => { + let DefKind::Static { safety: _, mutability, nested } = tcx.def_kind(did) else { + bug!() + }; + if nested { + // Nested statics in a `static` are never interior mutable, + // so just use the declared mutability. + if cfg!(debug_assertions) { + let alloc = tcx.eval_static_initializer(did).unwrap(); + assert_eq!(alloc.0.mutability, mutability); + } + mutability + } else { + let mutability = match mutability { + Mutability::Not + if !tcx + .type_of(did) + .no_bound_vars() + .expect("statics should not have generic parameters") + .is_freeze(tcx, param_env) => + { + Mutability::Mut + } + _ => mutability, + }; + mutability + } + } + GlobalAlloc::Memory(alloc) => alloc.inner().mutability, + GlobalAlloc::Function { .. } | GlobalAlloc::VTable(..) => { + // These are immutable. + Mutability::Not + } + } + } + + pub fn size_and_align(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> (Size, Align) { + match self { + GlobalAlloc::Static(def_id) => { + let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { + bug!("GlobalAlloc::Static is not a static") + }; + + if nested { + // Nested anonymous statics are untyped, so let's get their + // size and alignment from the allocation itself. This always + // succeeds, as the query is fed at DefId creation time, so no + // evaluation actually occurs. + let alloc = tcx.eval_static_initializer(def_id).unwrap(); + (alloc.0.size(), alloc.0.align) + } else { + // Use size and align of the type for everything else. We need + // to do that to + // * avoid cycle errors in case of self-referential statics, + // * be able to get information on extern statics. + let ty = tcx + .type_of(def_id) + .no_bound_vars() + .expect("statics should not have generic parameters"); + let layout = tcx.layout_of(param_env.and(ty)).unwrap(); + assert!(layout.is_sized()); + (layout.size, layout.align.abi) + } + } + GlobalAlloc::Memory(alloc) => { + let alloc = alloc.inner(); + (alloc.size(), alloc.align) + } + GlobalAlloc::Function { .. } => (Size::ZERO, Align::ONE), + GlobalAlloc::VTable(..) => { + // No data to be accessed here. But vtables are pointer-aligned. + return (Size::ZERO, tcx.data_layout.pointer_align.abi); + } + } + } } pub const CTFE_ALLOC_SALT: usize = 0; diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs index 8b59ca63a43..b9d82a08620 100644 --- a/src/tools/miri/src/alloc_addresses/mod.rs +++ b/src/tools/miri/src/alloc_addresses/mod.rs @@ -134,7 +134,7 @@ fn alloc_id_from_addr(&self, addr: u64, size: i64) -> Option { // entered for addresses that are not the base address, so even zero-sized // allocations will get recognized at their base address -- but all other // allocations will *not* be recognized at their "end" address. - let size = ecx.get_alloc_info(alloc_id).0; + let size = ecx.get_alloc_info(alloc_id).size; if offset < size.bytes() { Some(alloc_id) } else { None } } }?; @@ -157,25 +157,25 @@ fn addr_from_alloc_id_uncached( ) -> InterpResult<'tcx, u64> { let ecx = self.eval_context_ref(); let mut rng = ecx.machine.rng.borrow_mut(); - let (size, align, kind, _mutbl) = ecx.get_alloc_info(alloc_id); + let info = ecx.get_alloc_info(alloc_id); // This is either called immediately after allocation (and then cached), or when // adjusting `tcx` pointers (which never get freed). So assert that we are looking // at a live allocation. This also ensures that we never re-assign an address to an // allocation that previously had an address, but then was freed and the address // information was removed. - assert!(!matches!(kind, AllocKind::Dead)); + assert!(!matches!(info.kind, AllocKind::Dead)); // This allocation does not have a base address yet, pick or reuse one. if ecx.machine.native_lib.is_some() { // In native lib mode, we use the "real" address of the bytes for this allocation. // This ensures the interpreted program and native code have the same view of memory. - let base_ptr = match kind { + let base_ptr = match info.kind { AllocKind::LiveData => { if ecx.tcx.try_get_global_alloc(alloc_id).is_some() { // For new global allocations, we always pre-allocate the memory to be able use the machine address directly. - let prepared_bytes = MiriAllocBytes::zeroed(size, align) + let prepared_bytes = MiriAllocBytes::zeroed(info.size, info.align) .unwrap_or_else(|| { - panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes") + panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes", size = info.size) }); let ptr = prepared_bytes.as_ptr(); // Store prepared allocation space to be picked up for use later. @@ -204,7 +204,7 @@ fn addr_from_alloc_id_uncached( } // We are not in native lib mode, so we control the addresses ourselves. if let Some((reuse_addr, clock)) = - global_state.reuse.take_addr(&mut *rng, size, align, memory_kind, ecx.active_thread()) + global_state.reuse.take_addr(&mut *rng, info.size, info.align, memory_kind, ecx.active_thread()) { if let Some(clock) = clock { ecx.acquire_clock(&clock); @@ -220,14 +220,14 @@ fn addr_from_alloc_id_uncached( .next_base_addr .checked_add(slack) .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; - let base_addr = align_addr(base_addr, align.bytes()); + let base_addr = align_addr(base_addr, info.align.bytes()); // Remember next base address. If this allocation is zero-sized, leave a gap of at // least 1 to avoid two allocations having the same base address. (The logic in // `alloc_id_from_addr` assumes unique addresses, and different function/vtable pointers // need to be distinguishable!) global_state.next_base_addr = base_addr - .checked_add(max(size.bytes(), 1)) + .checked_add(max(info.size.bytes(), 1)) .ok_or_else(|| err_exhaust!(AddressSpaceFull))?; // Even if `Size` didn't overflow, we might still have filled up the address space. if global_state.next_base_addr > ecx.target_usize_max() { diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs index 3ee00a1dcf4..4883613dea5 100644 --- a/src/tools/miri/src/borrow_tracker/mod.rs +++ b/src/tools/miri/src/borrow_tracker/mod.rs @@ -363,7 +363,7 @@ fn on_stack_pop( // If it does exist, then we have the guarantee that the // pointer is readable, and the implicit read access inserted // will never cause UB on the pointer itself. - let (_, _, kind, _mutbl) = this.get_alloc_info(*alloc_id); + let kind = this.get_alloc_info(*alloc_id).kind; if matches!(kind, AllocKind::LiveData) { let alloc_extra = this.get_alloc_extra(*alloc_id)?; // can still fail for `extern static` let alloc_borrow_tracker = &alloc_extra.borrow_tracker.as_ref().unwrap(); diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs index b42b70b4d2f..16fcc26be33 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs @@ -626,7 +626,7 @@ fn sb_reborrow( return interp_ok(()) }; - let (_size, _align, alloc_kind, _mutbl) = this.get_alloc_info(alloc_id); + let alloc_kind = this.get_alloc_info(alloc_id).kind; match alloc_kind { AllocKind::LiveData => { // This should have alloc_extra data, but `get_alloc_extra` can still fail @@ -1017,7 +1017,7 @@ fn sb_expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx // Function pointers and dead objects don't have an alloc_extra so we ignore them. // This is okay because accessing them is UB anyway, no need for any Stacked Borrows checks. // NOT using `get_alloc_extra_mut` since this might be a read-only allocation! - let (_size, _align, kind, _mutbl) = this.get_alloc_info(alloc_id); + let kind = this.get_alloc_info(alloc_id).kind; match kind { AllocKind::LiveData => { // This should have alloc_extra data, but `get_alloc_extra` can still fail diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index 799950e4c94..f92150758dc 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -274,7 +274,7 @@ fn tb_reborrow( .insert(new_tag, protect); } - let alloc_kind = this.get_alloc_info(alloc_id).2; + let alloc_kind = this.get_alloc_info(alloc_id).kind; if !matches!(alloc_kind, AllocKind::LiveData) { assert_eq!(ptr_size, Size::ZERO); // we did the deref check above, size has to be 0 here // There's not actually any bytes here where accesses could even be tracked. @@ -538,7 +538,7 @@ fn tb_expose_tag(&mut self, alloc_id: AllocId, tag: BorTag) -> InterpResult<'tcx // Function pointers and dead objects don't have an alloc_extra so we ignore them. // This is okay because accessing them is UB anyway, no need for any Tree Borrows checks. // NOT using `get_alloc_extra_mut` since this might be a read-only allocation! - let (_size, _align, kind, _mutbl) = this.get_alloc_info(alloc_id); + let kind = this.get_alloc_info(alloc_id).kind; match kind { AllocKind::LiveData => { // This should have alloc_extra data, but `get_alloc_extra` can still fail diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index c8c9070f290..9668998aaa3 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -1125,10 +1125,10 @@ fn extern_static_pointer( let Provenance::Concrete { alloc_id, .. } = ptr.provenance else { panic!("extern_statics cannot contain wildcards") }; - let (shim_size, shim_align, _kind, _mutbl) = ecx.get_alloc_info(alloc_id); + let info = ecx.get_alloc_info(alloc_id); let def_ty = ecx.tcx.type_of(def_id).instantiate_identity(); let extern_decl_layout = ecx.tcx.layout_of(ty::ParamEnv::empty().and(def_ty)).unwrap(); - if extern_decl_layout.size != shim_size || extern_decl_layout.align.abi != shim_align { + if extern_decl_layout.size != info.size || extern_decl_layout.align.abi != info.align { throw_unsup_format!( "extern static `{link_name}` has been declared as `{krate}::{name}` \ with a size of {decl_size} bytes and alignment of {decl_align} bytes, \ @@ -1138,8 +1138,8 @@ fn extern_static_pointer( krate = ecx.tcx.crate_name(def_id.krate), decl_size = extern_decl_layout.size.bytes(), decl_align = extern_decl_layout.align.abi.bytes(), - shim_size = shim_size.bytes(), - shim_align = shim_align.bytes(), + shim_size = info.size.bytes(), + shim_align = info.align.bytes(), ) } interp_ok(ptr) diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index a6733af9faa..b9034336924 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -300,7 +300,7 @@ fn emulate_foreign_item_inner( let id = this.read_scalar(id)?.to_u64()?; let show_unnamed = this.read_scalar(show_unnamed)?.to_bool()?; if let Some(id) = std::num::NonZero::new(id).map(AllocId) - && this.get_alloc_info(id).2 == AllocKind::LiveData + && this.get_alloc_info(id).kind == AllocKind::LiveData { this.print_borrow_state(id, show_unnamed)?; } else { @@ -409,7 +409,7 @@ fn emulate_foreign_item_inner( ); } if let Ok((alloc_id, offset, ..)) = this.ptr_try_get_alloc_id(ptr, 0) { - let (_size, alloc_align, _kind, _mutbl) = this.get_alloc_info(alloc_id); + let alloc_align = this.get_alloc_info(alloc_id).align; // If the newly promised alignment is bigger than the native alignment of this // allocation, and bigger than the previously promised alignment, then set it. if align > alloc_align From 1dc106121b62562ead6e7d612fa136dc4b35cd5d Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Mon, 4 Nov 2024 11:38:14 -0800 Subject: [PATCH 48/54] Add discriminators to DILocations when multiple functions are inlined into a single point. LLVM does not expect to ever see multiple dbg_declares for the same variable at the same location with different values. proc-macros make it possible for arbitrary code, including multiple calls that get inlined, to happen at any given location in the source code. Add discriminators when that happens so these locations are different to LLVM. This may interfere with the AddDiscriminators pass in LLVM, which is added by the unstable flag -Zdebug-info-for-profiling. Fixes #131944 --- .../src/debuginfo/create_scope_map.rs | 60 ++++++++++++++++++- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 4 ++ .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 8 +++ .../auxiliary/macro_def.rs | 11 ++++ .../mir_inlined_twice_var_locs.rs | 53 ++++++++++++++++ 5 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs create mode 100644 tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index ac6c2fb1b83..0f1909486ec 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -1,11 +1,15 @@ +use std::collections::hash_map::Entry; + use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; use rustc_codegen_ssa::traits::*; +use rustc_data_structures::fx::FxHashMap; use rustc_index::Idx; use rustc_index::bit_set::BitSet; use rustc_middle::mir::{Body, SourceScope}; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::{self, Instance}; use rustc_session::config::DebugInfo; +use rustc_span::BytePos; use super::metadata::file_metadata; use super::utils::DIB; @@ -37,10 +41,20 @@ pub(crate) fn compute_mir_scopes<'ll, 'tcx>( None }; let mut instantiated = BitSet::new_empty(mir.source_scopes.len()); + let mut discriminators = FxHashMap::default(); // Instantiate all scopes. for idx in 0..mir.source_scopes.len() { let scope = SourceScope::new(idx); - make_mir_scope(cx, instance, mir, &variables, debug_context, &mut instantiated, scope); + make_mir_scope( + cx, + instance, + mir, + &variables, + debug_context, + &mut instantiated, + &mut discriminators, + scope, + ); } assert!(instantiated.count() == mir.source_scopes.len()); } @@ -52,6 +66,7 @@ fn make_mir_scope<'ll, 'tcx>( variables: &Option>, debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>, instantiated: &mut BitSet, + discriminators: &mut FxHashMap, scope: SourceScope, ) { if instantiated.contains(scope) { @@ -60,7 +75,16 @@ fn make_mir_scope<'ll, 'tcx>( let scope_data = &mir.source_scopes[scope]; let parent_scope = if let Some(parent) = scope_data.parent_scope { - make_mir_scope(cx, instance, mir, variables, debug_context, instantiated, parent); + make_mir_scope( + cx, + instance, + mir, + variables, + debug_context, + instantiated, + discriminators, + parent, + ); debug_context.scopes[parent] } else { // The root is the function itself. @@ -117,7 +141,37 @@ fn make_mir_scope<'ll, 'tcx>( // FIXME(eddyb) this doesn't account for the macro-related // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does. let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); - cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span) + let loc = cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span); + + // NB: In order to produce proper debug info for variables (particularly + // arguments) in multiply-inline functions, LLVM expects to see a single + // DILocalVariable with multiple different DILocations in the IR. While + // the source information for each DILocation would be identical, their + // inlinedAt attributes will be unique to the particular callsite. + // + // We generate DILocations here based on the callsite's location in the + // source code. A single location in the source code usually can't + // produce multiple distinct calls so this mostly works, until + // proc-macros get involved. A proc-macro can generate multiple calls + // at the same span, which breaks the assumption that we're going to + // produce a unique DILocation for every scope we process here. We + // have to explicitly add discriminators if we see inlines into the + // same source code location. + // + // Note further that we can't key this hashtable on the span itself, + // because these spans could have distinct SyntaxContexts. We have + // to key on exactly what we're giving to LLVM. + match discriminators.entry(callsite_span.lo()) { + Entry::Occupied(mut o) => { + *o.get_mut() += 1; + unsafe { llvm::LLVMRustDILocationCloneWithBaseDiscriminator(loc, *o.get()) } + .expect("Failed to encode discriminator in DILocation") + } + Entry::Vacant(v) => { + v.insert(0); + loc + } + } }); debug_context.scopes[scope] = DebugScope { diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3d2e270a386..75a5ec44c22 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2174,6 +2174,10 @@ pub fn LLVMRustDIBuilderCreateDebugLocation<'a>( Scope: &'a DIScope, InlinedAt: Option<&'a DILocation>, ) -> &'a DILocation; + pub fn LLVMRustDILocationCloneWithBaseDiscriminator<'a>( + Location: &'a DILocation, + BD: c_uint, + ) -> Option<&'a DILocation>; pub fn LLVMRustDIBuilderCreateOpDeref() -> u64; pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> u64; pub fn LLVMRustDIBuilderCreateOpLLVMFragment() -> u64; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 9330c83b7f2..cd70c3f2669 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1305,6 +1305,14 @@ LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column, return wrap(Loc); } +extern "C" LLVMMetadataRef +LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location, + unsigned BD) { + DILocation *Loc = unwrapDIPtr(Location); + auto NewLoc = Loc->cloneWithBaseDiscriminator(BD); + return wrap(NewLoc.has_value() ? NewLoc.value() : nullptr); +} + extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() { return dwarf::DW_OP_deref; } diff --git a/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs b/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs new file mode 100644 index 00000000000..159ecfd0974 --- /dev/null +++ b/tests/codegen/debuginfo-proc-macro/auxiliary/macro_def.rs @@ -0,0 +1,11 @@ +//@ force-host +//@ no-prefer-dynamic +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn square_twice(_item: TokenStream) -> TokenStream { + "(square(env::vars().count() as i32), square(env::vars().count() as i32))".parse().unwrap() +} diff --git a/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs b/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs new file mode 100644 index 00000000000..c3858044c0c --- /dev/null +++ b/tests/codegen/debuginfo-proc-macro/mir_inlined_twice_var_locs.rs @@ -0,0 +1,53 @@ +//@ min-llvm-version: 19 +//@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -Zmir-enable-passes=+Inline +// MSVC is different because of the individual allocas. +//@ ignore-msvc + +//@ aux-build:macro_def.rs + +// Find the variable. +// CHECK-DAG: ![[#var_dbg:]] = !DILocalVariable(name: "n",{{( arg: 1,)?}} scope: ![[#var_scope:]] + +// Find both dbg_declares. These will proceed the variable metadata, of course, so we're looking +// backwards. +// CHECK-DAG: dbg_declare(ptr %n.dbg.spill{{[0-9]}}, ![[#var_dbg]], !DIExpression(), ![[#var_loc2:]]) +// CHECK-DAG: dbg_declare(ptr %n.dbg.spill, ![[#var_dbg]], !DIExpression(), ![[#var_loc1:]]) + +// Find the first location definition, looking forwards again. +// CHECK: ![[#var_loc1]] = !DILocation +// CHECK-SAME: scope: ![[#var_scope:]], inlinedAt: ![[#var_inlinedAt1:]] + +// Find the first location's inlinedAt +// NB: If we fail here it's *probably* because we failed to produce two +// different locations and ended up reusing an earlier one. +// CHECK: ![[#var_inlinedAt1]] = !DILocation +// CHECK-SAME: scope: ![[var_inlinedAt1_scope:]] + +// Find the second location definition, still looking forwards. +// NB: If we failed to produce two different locations, the test will +// definitely fail by this point (if it hasn't already) because we won't +// be able to find the same line again. +// CHECK: ![[#var_loc2]] = !DILocation +// CHECK-SAME: scope: ![[#var_scope]], inlinedAt: ![[#var_inlinedAt2:]] + +// Find the second location's inlinedAt. +// CHECK: ![[#var_inlinedAt2]] = !DILocation +// CHECK-SAME: scope: ![[#var_inlinedAt2_scope:]] + +// Finally, check that a discriminator was emitted for the second scope. +// FIXMEkhuey ideally we would check that *either* scope has a discriminator +// but I don't know that it's possible to check that with FileCheck. +// CHECK: ![[#var_inlinedAt2_scope]] = !DILexicalBlockFile +// CHECK-SAME: discriminator: [[#]] +extern crate macro_def; + +use std::env; + +fn square(n: i32) -> i32 { + n * n +} + +fn main() { + let (z1, z2) = macro_def::square_twice!(); + println!("{z1} == {z2}"); +} From 2b469607b4337e2c8996e755570202feb33124fe Mon Sep 17 00:00:00 2001 From: nora <48135649+Noratrieb@users.noreply.github.com> Date: Sat, 9 Nov 2024 22:45:17 +0100 Subject: [PATCH 49/54] Exclude relnotes-tracking-issue from needs-triage --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 5d80b9e656e..a7ae754aefd 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -395,6 +395,7 @@ new_issue = true exclude_labels = [ "C-tracking-issue", "A-diagnostics", + "relnotes-tracking-issue", ] [autolabel."WG-trait-system-refactor"] From 822762c966b0c8e85c0a552929a5a9c53bf93a97 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Nov 2024 22:19:35 +0100 Subject: [PATCH 50/54] require const_impl_trait gate for all conditional and trait const calls --- compiler/rustc_const_eval/messages.ftl | 4 + .../src/check_consts/check.rs | 87 ++++------- .../rustc_const_eval/src/check_consts/ops.rs | 39 +++-- compiler/rustc_const_eval/src/errors.rs | 10 ++ tests/ui/traits/const-traits/cross-crate.rs | 4 +- .../const-traits/cross-crate.stock.stderr | 28 +--- .../const-traits/cross-crate.stocknc.stderr | 53 +------ .../const-traits/staged-api-user-crate.rs | 3 +- .../const-traits/staged-api-user-crate.stderr | 24 +-- tests/ui/traits/const-traits/staged-api.rs | 50 +++---- .../const-traits/staged-api.stable.stderr | 89 ----------- .../ui/traits/const-traits/staged-api.stderr | 139 ++++++++++++++++++ .../const-traits/staged-api.unstable.stderr | 108 -------------- 13 files changed, 249 insertions(+), 389 deletions(-) delete mode 100644 tests/ui/traits/const-traits/staged-api.stable.stderr create mode 100644 tests/ui/traits/const-traits/staged-api.stderr delete mode 100644 tests/ui/traits/const-traits/staged-api.unstable.stderr diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 826e34930ea..15027ae0c18 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -25,6 +25,10 @@ const_eval_closure_fndef_not_const = function defined here, but it is not `const` const_eval_closure_non_const = cannot call non-const closure in {const_eval_const_context}s + +const_eval_conditionally_const_call = + cannot call conditionally-const {$def_descr} `{$def_path_str}` in {const_eval_const_context}s + const_eval_consider_dereferencing = consider dereferencing here diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index aea3d5bd3e7..8cd0ecb3e4e 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -15,7 +15,7 @@ use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_mir_dataflow::Analysis; use rustc_mir_dataflow::impls::MaybeStorageLive; use rustc_mir_dataflow::storage::always_storage_live_locals; @@ -361,31 +361,21 @@ fn place_may_escape(&mut self, place: &Place<'_>) -> bool { !is_transient } + /// Returns whether there are const-conditions. fn revalidate_conditional_constness( &mut self, callee: DefId, callee_args: ty::GenericArgsRef<'tcx>, - call_source: CallSource, call_span: Span, - ) { + ) -> bool { let tcx = self.tcx; if !tcx.is_conditionally_const(callee) { - return; + return false; } let const_conditions = tcx.const_conditions(callee).instantiate(tcx, callee_args); - // If there are any const conditions on this fn and `const_trait_impl` - // is not enabled, simply bail. We shouldn't be able to call conditionally - // const functions on stable. - if !const_conditions.is_empty() && !tcx.features().const_trait_impl() { - self.check_op(ops::FnCallNonConst { - callee, - args: callee_args, - span: call_span, - call_source, - feature: Some(sym::const_trait_impl), - }); - return; + if const_conditions.is_empty() { + return false; } let infcx = tcx.infer_ctxt().build(self.body.typing_mode(tcx)); @@ -421,6 +411,8 @@ fn revalidate_conditional_constness( tcx.dcx() .span_delayed_bug(call_span, "this should have reported a ~const error in HIR"); } + + true } } @@ -627,11 +619,11 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location _ => unreachable!(), }; - let ConstCx { tcx, body, param_env, .. } = *self.ccx; + let ConstCx { tcx, body, .. } = *self.ccx; let fn_ty = func.ty(body, tcx); - let (mut callee, mut fn_args) = match *fn_ty.kind() { + let (callee, fn_args) = match *fn_ty.kind() { ty::FnDef(def_id, fn_args) => (def_id, fn_args), ty::FnPtr(..) => { @@ -645,57 +637,38 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location } }; - self.revalidate_conditional_constness(callee, fn_args, call_source, *fn_span); + let has_const_conditions = + self.revalidate_conditional_constness(callee, fn_args, *fn_span); - let mut is_trait = false; // Attempting to call a trait method? if let Some(trait_did) = tcx.trait_of_item(callee) { + // We can't determine the actual callee here, so we have to do different checks + // than usual. + trace!("attempting to call a trait method"); - let trait_is_const = tcx.is_const_trait(trait_did); - // trait method calls are only permitted when `effects` is enabled. - // typeck ensures the conditions for calling a const trait method are met, - // so we only error if the trait isn't const. We try to resolve the trait - // into the concrete method, and uses that for const stability checks. - // FIXME(const_trait_impl) we might consider moving const stability checks - // to typeck as well. - if tcx.features().const_trait_impl() && trait_is_const { - // This skips the check below that ensures we only call `const fn`. - is_trait = true; - if let Ok(Some(instance)) = - Instance::try_resolve(tcx, param_env, callee, fn_args) - && let InstanceKind::Item(def) = instance.def - { - // Resolve a trait method call to its concrete implementation, which may be in a - // `const` trait impl. This is only used for the const stability check below, since - // we want to look at the concrete impl's stability. - fn_args = instance.args; - callee = def; - } + if trait_is_const { + // Trait calls are always conditionally-const. + self.check_op(ops::ConditionallyConstCall { callee, args: fn_args }); + // FIXME(const_trait_impl): do a more fine-grained check whether this + // particular trait can be const-stably called. } else { - // if the trait is const but the user has not enabled the feature(s), - // suggest them. - let feature = if trait_is_const { - Some(if tcx.features().const_trait_impl() { - sym::effects - } else { - sym::const_trait_impl - }) - } else { - None - }; + // Not even a const trait. self.check_op(ops::FnCallNonConst { callee, args: fn_args, span: *fn_span, call_source, - feature, }); - // If we allowed this, we're in miri-unleashed mode, so we might - // as well skip the remaining checks. - return; } + // That's all we can check here. + return; + } + + // Even if we know the callee, ensure we can use conditionally-const calls. + if has_const_conditions { + self.check_op(ops::ConditionallyConstCall { callee, args: fn_args }); } // At this point, we are calling a function, `callee`, whose `DefId` is known... @@ -783,14 +756,12 @@ fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location return; } - // Trait functions are not `const fn` so we have to skip them here. - if !tcx.is_const_fn(callee) && !is_trait { + if !tcx.is_const_fn(callee) { self.check_op(ops::FnCallNonConst { callee, args: fn_args, span: *fn_span, call_source, - feature: None, }); // If we allowed this, we're in miri-unleashed mode, so we might // as well skip the remaining checks. diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 2931159842f..5b745e6dffd 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -70,6 +70,34 @@ fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { } } +/// A call to a function that is in a trait, or has trait bounds that make it conditionally-const. +#[derive(Debug)] +pub(crate) struct ConditionallyConstCall<'tcx> { + pub callee: DefId, + pub args: GenericArgsRef<'tcx>, +} + +impl<'tcx> NonConstOp<'tcx> for ConditionallyConstCall<'tcx> { + fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status { + // We use the `const_trait_impl` gate for all conditionally-const calls. + Status::Unstable { + gate: sym::const_trait_impl, + safe_to_expose_on_stable: false, + // We don't want the "mark the callee as `#[rustc_const_stable_indirect]`" hint + is_function_call: false, + } + } + + fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { + ccx.dcx().create_err(errors::ConditionallyConstCall { + span, + def_path_str: ccx.tcx.def_path_str_with_args(self.callee, self.args), + def_descr: ccx.tcx.def_descr(self.callee), + kind: ccx.const_kind(), + }) + } +} + /// A function call where the callee is not marked as `const`. #[derive(Debug, Clone, Copy)] pub(crate) struct FnCallNonConst<'tcx> { @@ -77,7 +105,6 @@ pub(crate) struct FnCallNonConst<'tcx> { pub args: GenericArgsRef<'tcx>, pub span: Span, pub call_source: CallSource, - pub feature: Option, } impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { @@ -85,7 +112,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { #[allow(rustc::diagnostic_outside_of_impl)] #[allow(rustc::untranslatable_diagnostic)] fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, _: Span) -> Diag<'tcx> { - let FnCallNonConst { callee, args, span, call_source, feature } = *self; + let FnCallNonConst { callee, args, span, call_source } = *self; let ConstCx { tcx, param_env, .. } = *ccx; let caller = ccx.def_id(); @@ -285,14 +312,6 @@ macro_rules! error { ccx.const_kind(), )); - if let Some(feature) = feature { - ccx.tcx.disabled_nightly_features( - &mut err, - Some(ccx.tcx.local_def_id_to_hir_id(caller)), - [(String::new(), feature)], - ); - } - if let ConstContext::Static(_) = ccx.const_kind() { err.note(fluent_generated::const_eval_lazy_lock); } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 14e8bebbb18..604e5ed61a3 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -176,6 +176,16 @@ pub(crate) struct NonConstFmtMacroCall { pub kind: ConstContext, } +#[derive(Diagnostic)] +#[diag(const_eval_conditionally_const_call)] +pub(crate) struct ConditionallyConstCall { + #[primary_span] + pub span: Span, + pub def_path_str: String, + pub def_descr: &'static str, + pub kind: ConstContext, +} + #[derive(Diagnostic)] #[diag(const_eval_non_const_fn_call, code = E0015)] pub(crate) struct NonConstFnCall { diff --git a/tests/ui/traits/const-traits/cross-crate.rs b/tests/ui/traits/const-traits/cross-crate.rs index 9558ec6164e..b07aa8944c0 100644 --- a/tests/ui/traits/const-traits/cross-crate.rs +++ b/tests/ui/traits/const-traits/cross-crate.rs @@ -18,11 +18,9 @@ const fn const_context() { #[cfg(any(stocknc, gatednc))] NonConst.func(); //[stocknc]~^ ERROR: cannot call - //[stocknc]~| ERROR: cannot call - //[gatednc]~^^^ ERROR: the trait bound + //[gatednc]~^^ ERROR: the trait bound Const.func(); //[stock,stocknc]~^ ERROR: cannot call - //[stock,stocknc]~| ERROR: cannot call } fn main() {} diff --git a/tests/ui/traits/const-traits/cross-crate.stock.stderr b/tests/ui/traits/const-traits/cross-crate.stock.stderr index b35891071b0..d26228f6958 100644 --- a/tests/ui/traits/const-traits/cross-crate.stock.stderr +++ b/tests/ui/traits/const-traits/cross-crate.stock.stderr @@ -1,28 +1,8 @@ -error[E0015]: cannot call non-const fn `::func` in constant functions - --> $DIR/cross-crate.rs:23:11 +error: cannot call conditionally-const method `::func` in constant functions + --> $DIR/cross-crate.rs:22:5 | LL | Const.func(); - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | + | ^^^^^^^^^^^^ -error[E0015]: cannot call non-const fn `::func` in constant functions - --> $DIR/cross-crate.rs:23:11 - | -LL | Const.func(); - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/cross-crate.stocknc.stderr b/tests/ui/traits/const-traits/cross-crate.stocknc.stderr index 89de89159db..9b372860262 100644 --- a/tests/ui/traits/const-traits/cross-crate.stocknc.stderr +++ b/tests/ui/traits/const-traits/cross-crate.stocknc.stderr @@ -1,53 +1,14 @@ -error[E0015]: cannot call non-const fn `::func` in constant functions - --> $DIR/cross-crate.rs:19:14 +error: cannot call conditionally-const method `::func` in constant functions + --> $DIR/cross-crate.rs:19:5 | LL | NonConst.func(); - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | + | ^^^^^^^^^^^^^^^ -error[E0015]: cannot call non-const fn `::func` in constant functions - --> $DIR/cross-crate.rs:19:14 - | -LL | NonConst.func(); - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | - -error[E0015]: cannot call non-const fn `::func` in constant functions - --> $DIR/cross-crate.rs:23:11 +error: cannot call conditionally-const method `::func` in constant functions + --> $DIR/cross-crate.rs:22:5 | LL | Const.func(); - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | + | ^^^^^^^^^^^^ -error[E0015]: cannot call non-const fn `::func` in constant functions - --> $DIR/cross-crate.rs:23:11 - | -LL | Const.func(); - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | +error: aborting due to 2 previous errors -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/staged-api-user-crate.rs b/tests/ui/traits/const-traits/staged-api-user-crate.rs index c820d1ff47c..7587042cf27 100644 --- a/tests/ui/traits/const-traits/staged-api-user-crate.rs +++ b/tests/ui/traits/const-traits/staged-api-user-crate.rs @@ -10,8 +10,7 @@ fn non_const_context() { const fn stable_const_context() { Unstable::func(); - //~^ ERROR cannot call non-const fn `::func` in constant functions - //~| ERROR cannot call non-const fn `::func` in constant functions + //~^ ERROR cannot call conditionally-const associated function `::func` in constant functions } fn main() {} diff --git a/tests/ui/traits/const-traits/staged-api-user-crate.stderr b/tests/ui/traits/const-traits/staged-api-user-crate.stderr index 24cdb1d3d5a..2bce230ffdf 100644 --- a/tests/ui/traits/const-traits/staged-api-user-crate.stderr +++ b/tests/ui/traits/const-traits/staged-api-user-crate.stderr @@ -1,28 +1,8 @@ -error[E0015]: cannot call non-const fn `::func` in constant functions +error: cannot call conditionally-const associated function `::func` in constant functions --> $DIR/staged-api-user-crate.rs:12:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | -error[E0015]: cannot call non-const fn `::func` in constant functions - --> $DIR/staged-api-user-crate.rs:12:5 - | -LL | Unstable::func(); - | ^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: add `#![feature(const_trait_impl)]` to the crate attributes to enable - | -LL + #![feature(const_trait_impl)] - | +error: aborting due to 1 previous error -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/staged-api.rs b/tests/ui/traits/const-traits/staged-api.rs index 401a81d8142..755a4e456bc 100644 --- a/tests/ui/traits/const-traits/staged-api.rs +++ b/tests/ui/traits/const-traits/staged-api.rs @@ -1,10 +1,11 @@ -//@ revisions: stable unstable +//! Checks whether we are properly enforcing recursive const stability for trait calls. //@ compile-flags: -Znext-solver -#![cfg_attr(unstable, feature(unstable))] // The feature from the ./auxiliary/staged-api.rs file. -#![cfg_attr(unstable, feature(local_feature))] +#![feature(unstable)] // The feature from the ./auxiliary/staged-api.rs file. +#![feature(local_feature)] #![feature(const_trait_impl)] #![feature(staged_api)] +#![feature(rustc_allow_const_fn_unstable)] #![stable(feature = "rust1", since = "1.0.0")] //@ aux-build: staged-api.rs @@ -16,13 +17,16 @@ pub struct Foo; #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(unstable, rustc_const_unstable(feature = "local_feature", issue = "none"))] -#[cfg_attr(stable, rustc_const_stable(feature = "local_feature", since = "1.0.0"))] +#[rustc_const_unstable(feature = "local_feature", issue = "none")] impl const MyTrait for Foo { - //[stable]~^ ERROR trait implementations cannot be const stable yet fn func() {} } +#[rustc_allow_const_fn_unstable(const_trait_impl)] +const fn conditionally_const() { + T::func(); +} + // Const stability has no impact on usage in non-const contexts. fn non_const_context() { Unstable::func(); @@ -32,43 +36,35 @@ fn non_const_context() { #[unstable(feature = "none", issue = "none")] const fn const_context() { Unstable::func(); - //[unstable]~^ ERROR cannot use `#[feature(unstable)]` - //[stable]~^^ ERROR not yet stable as a const fn + //~^ ERROR cannot use `#[feature(const_trait_impl)]` Foo::func(); - //[unstable]~^ ERROR cannot use `#[feature(local_feature)]` - //[stable]~^^ cannot be (indirectly) exposed to stable - // We get the error on `stable` since this is a trait function. + //~^ ERROR cannot use `#[feature(const_trait_impl)]` Unstable2::func(); - //~^ ERROR not yet stable as a const fn - // ^ fails, because the `unstable2` feature is not active + //~^ ERROR cannot use `#[feature(const_trait_impl)]` + conditionally_const::(); + //~^ ERROR cannot use `#[feature(const_trait_impl)]` } #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(unstable, rustc_const_unstable(feature = "local_feature", issue = "none"))] +#[rustc_const_unstable(feature = "local_feature", issue = "none")] pub const fn const_context_not_const_stable() { - //[stable]~^ ERROR function has missing const stability attribute Unstable::func(); - //[stable]~^ ERROR not yet stable as a const fn Foo::func(); - //[stable]~^ cannot be (indirectly) exposed to stable - // We get the error on `stable` since this is a trait function. Unstable2::func(); - //~^ ERROR not yet stable as a const fn - // ^ fails, because the `unstable2` feature is not active + conditionally_const::(); } #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "cheese", since = "1.0.0")] const fn stable_const_context() { Unstable::func(); - //[unstable]~^ ERROR cannot use `#[feature(unstable)]` - //[stable]~^^ ERROR not yet stable as a const fn + //~^ ERROR cannot use `#[feature(const_trait_impl)]` Foo::func(); - //[unstable]~^ ERROR cannot use `#[feature(local_feature)]` - //[stable]~^^ cannot be (indirectly) exposed to stable - // We get the error on `stable` since this is a trait function. - const_context_not_const_stable() - //[unstable]~^ ERROR cannot use `#[feature(local_feature)]` + //~^ ERROR cannot use `#[feature(const_trait_impl)]` + const_context_not_const_stable(); + //~^ ERROR cannot use `#[feature(local_feature)]` + conditionally_const::(); + //~^ ERROR cannot use `#[feature(const_trait_impl)]` } fn main() {} diff --git a/tests/ui/traits/const-traits/staged-api.stable.stderr b/tests/ui/traits/const-traits/staged-api.stable.stderr deleted file mode 100644 index 8f491b2f182..00000000000 --- a/tests/ui/traits/const-traits/staged-api.stable.stderr +++ /dev/null @@ -1,89 +0,0 @@ -error: trait implementations cannot be const stable yet - --> $DIR/staged-api.rs:21:1 - | -LL | / impl const MyTrait for Foo { -LL | | -LL | | fn func() {} -LL | | } - | |_^ - | - = note: see issue #67792 for more information - -error: function has missing const stability attribute - --> $DIR/staged-api.rs:48:1 - | -LL | / pub const fn const_context_not_const_stable() { -LL | | -LL | | Unstable::func(); -LL | | -... | -LL | | // ^ fails, because the `unstable2` feature is not active -LL | | } - | |_^ - -error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:34:5 - | -LL | Unstable::func(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable)]` to the crate attributes to enable - -error: `::func` cannot be (indirectly) exposed to stable - --> $DIR/staged-api.rs:37:5 - | -LL | Foo::func(); - | ^^^^^^^^^^^ - | - = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` - -error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:41:5 - | -LL | Unstable2::func(); - | ^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable2)]` to the crate attributes to enable - -error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:50:5 - | -LL | Unstable::func(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable)]` to the crate attributes to enable - -error: `::func` cannot be (indirectly) exposed to stable - --> $DIR/staged-api.rs:52:5 - | -LL | Foo::func(); - | ^^^^^^^^^^^ - | - = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` - -error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:55:5 - | -LL | Unstable2::func(); - | ^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable2)]` to the crate attributes to enable - -error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:63:5 - | -LL | Unstable::func(); - | ^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable)]` to the crate attributes to enable - -error: `::func` cannot be (indirectly) exposed to stable - --> $DIR/staged-api.rs:66:5 - | -LL | Foo::func(); - | ^^^^^^^^^^^ - | - = help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]` - -error: aborting due to 10 previous errors - diff --git a/tests/ui/traits/const-traits/staged-api.stderr b/tests/ui/traits/const-traits/staged-api.stderr new file mode 100644 index 00000000000..29aafa4e0f3 --- /dev/null +++ b/tests/ui/traits/const-traits/staged-api.stderr @@ -0,0 +1,139 @@ +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:38:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | +help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const fn const_context() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] +LL | const fn const_context() { + | + +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:40:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | +help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const fn const_context() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] +LL | const fn const_context() { + | + +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:42:5 + | +LL | Unstable2::func(); + | ^^^^^^^^^^^^^^^^^ + | +help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const fn const_context() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] +LL | const fn const_context() { + | + +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:44:5 + | +LL | conditionally_const::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const fn const_context() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] +LL | const fn const_context() { + | + +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:60:5 + | +LL | Unstable::func(); + | ^^^^^^^^^^^^^^^^ + | +help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const fn stable_const_context() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] +LL | const fn stable_const_context() { + | + +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:62:5 + | +LL | Foo::func(); + | ^^^^^^^^^^^ + | +help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const fn stable_const_context() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] +LL | const fn stable_const_context() { + | + +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]` + --> $DIR/staged-api.rs:64:5 + | +LL | const_context_not_const_stable(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features +help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const fn stable_const_context() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(local_feature)] +LL | const fn stable_const_context() { + | + +error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]` + --> $DIR/staged-api.rs:66:5 + | +LL | conditionally_const::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) + | +LL + #[rustc_const_unstable(feature = "...", issue = "...")] +LL | const fn stable_const_context() { + | +help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) + | +LL + #[rustc_allow_const_fn_unstable(const_trait_impl)] +LL | const fn stable_const_context() { + | + +error: aborting due to 8 previous errors + diff --git a/tests/ui/traits/const-traits/staged-api.unstable.stderr b/tests/ui/traits/const-traits/staged-api.unstable.stderr deleted file mode 100644 index 76275452e90..00000000000 --- a/tests/ui/traits/const-traits/staged-api.unstable.stderr +++ /dev/null @@ -1,108 +0,0 @@ -error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]` - --> $DIR/staged-api.rs:34:5 - | -LL | Unstable::func(); - | ^^^^^^^^^^^^^^^^ - | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) - | -LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(unstable)] -LL | const fn const_context() { - | - -error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]` - --> $DIR/staged-api.rs:37:5 - | -LL | Foo::func(); - | ^^^^^^^^^^^ - | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) - | -LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(local_feature)] -LL | const fn const_context() { - | - -error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:41:5 - | -LL | Unstable2::func(); - | ^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable2)]` to the crate attributes to enable - -error: `::func` is not yet stable as a const fn - --> $DIR/staged-api.rs:55:5 - | -LL | Unstable2::func(); - | ^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(unstable2)]` to the crate attributes to enable - -error: const function that might be (indirectly) exposed to stable cannot use `#[feature(unstable)]` - --> $DIR/staged-api.rs:63:5 - | -LL | Unstable::func(); - | ^^^^^^^^^^^^^^^^ - | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) - | -LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(unstable)] -LL | const fn stable_const_context() { - | - -error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]` - --> $DIR/staged-api.rs:66:5 - | -LL | Foo::func(); - | ^^^^^^^^^^^ - | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) - | -LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(local_feature)] -LL | const fn stable_const_context() { - | - -error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local_feature)]` - --> $DIR/staged-api.rs:70:5 - | -LL | const_context_not_const_stable() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features -help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do) - | -LL + #[rustc_const_unstable(feature = "...", issue = "...")] -LL | const fn stable_const_context() { - | -help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval) - | -LL + #[rustc_allow_const_fn_unstable(local_feature)] -LL | const fn stable_const_context() { - | - -error: aborting due to 7 previous errors - From f235b6f9c6788e213b6365103cfa9c6c798fe659 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Nov 2024 23:32:06 +0100 Subject: [PATCH 51/54] give a hint which feature is missing --- .../rustc_const_eval/src/check_consts/ops.rs | 26 ++++++++----------- compiler/rustc_session/src/parse.rs | 1 + compiler/rustc_session/src/session.rs | 1 + .../const-traits/cross-crate.stock.stderr | 7 ++++- .../const-traits/cross-crate.stocknc.stderr | 13 ++++++++-- .../const-traits/staged-api-user-crate.stderr | 7 ++++- 6 files changed, 36 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 5b745e6dffd..036ca763280 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -89,12 +89,15 @@ fn status_in_item(&self, _ccx: &ConstCx<'_, 'tcx>) -> Status { } fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { - ccx.dcx().create_err(errors::ConditionallyConstCall { - span, - def_path_str: ccx.tcx.def_path_str_with_args(self.callee, self.args), - def_descr: ccx.tcx.def_descr(self.callee), - kind: ccx.const_kind(), - }) + ccx.tcx.sess.create_feature_err( + errors::ConditionallyConstCall { + span, + def_path_str: ccx.tcx.def_path_str_with_args(self.callee, self.args), + def_descr: ccx.tcx.def_descr(self.callee), + kind: ccx.const_kind(), + }, + sym::const_trait_impl, + ) } } @@ -417,15 +420,8 @@ fn status_in_item(&self, _: &ConstCx<'_, 'tcx>) -> Status { fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> { let msg = format!("{:#}s are not allowed in {}s", self.0, ccx.const_kind()); - if let hir::CoroutineKind::Desugared( - hir::CoroutineDesugaring::Async, - hir::CoroutineSource::Block, - ) = self.0 - { - ccx.tcx.sess.create_feature_err( - errors::UnallowedOpInConstContext { span, msg }, - sym::const_async_blocks, - ) + if let Status::Unstable { gate, .. } = self.status_in_item(ccx) { + ccx.tcx.sess.create_feature_err(errors::UnallowedOpInConstContext { span, msg }, gate) } else { ccx.dcx().create_err(errors::UnallowedOpInConstContext { span, msg }) } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index f20ae85b8e8..21c11655110 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -155,6 +155,7 @@ pub fn feature_warn_issue( } /// Adds the diagnostics for a feature to an existing error. +/// Must be a language feature! pub fn add_feature_diagnostics( err: &mut Diag<'_, G>, sess: &Session, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 470e372ee48..9d9434a7776 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -300,6 +300,7 @@ pub fn is_test_crate(&self) -> bool { self.opts.test } + /// `feature` must be a language feature. #[track_caller] pub fn create_feature_err<'a>(&'a self, err: impl Diagnostic<'a>, feature: Symbol) -> Diag<'a> { let mut err = self.dcx().create_err(err); diff --git a/tests/ui/traits/const-traits/cross-crate.stock.stderr b/tests/ui/traits/const-traits/cross-crate.stock.stderr index d26228f6958..09bf9c023c8 100644 --- a/tests/ui/traits/const-traits/cross-crate.stock.stderr +++ b/tests/ui/traits/const-traits/cross-crate.stock.stderr @@ -1,8 +1,13 @@ -error: cannot call conditionally-const method `::func` in constant functions +error[E0658]: cannot call conditionally-const method `::func` in constant functions --> $DIR/cross-crate.rs:22:5 | LL | Const.func(); | ^^^^^^^^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/cross-crate.stocknc.stderr b/tests/ui/traits/const-traits/cross-crate.stocknc.stderr index 9b372860262..e52e5609b01 100644 --- a/tests/ui/traits/const-traits/cross-crate.stocknc.stderr +++ b/tests/ui/traits/const-traits/cross-crate.stocknc.stderr @@ -1,14 +1,23 @@ -error: cannot call conditionally-const method `::func` in constant functions +error[E0658]: cannot call conditionally-const method `::func` in constant functions --> $DIR/cross-crate.rs:19:5 | LL | NonConst.func(); | ^^^^^^^^^^^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: cannot call conditionally-const method `::func` in constant functions +error[E0658]: cannot call conditionally-const method `::func` in constant functions --> $DIR/cross-crate.rs:22:5 | LL | Const.func(); | ^^^^^^^^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/staged-api-user-crate.stderr b/tests/ui/traits/const-traits/staged-api-user-crate.stderr index 2bce230ffdf..bf7466b8e16 100644 --- a/tests/ui/traits/const-traits/staged-api-user-crate.stderr +++ b/tests/ui/traits/const-traits/staged-api-user-crate.stderr @@ -1,8 +1,13 @@ -error: cannot call conditionally-const associated function `::func` in constant functions +error[E0658]: cannot call conditionally-const associated function `::func` in constant functions --> $DIR/staged-api-user-crate.rs:12:5 | LL | Unstable::func(); | ^^^^^^^^^^^^^^^^ + | + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0658`. From be30861174202b669f69ad43d4d4545beeb9b800 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Sat, 9 Nov 2024 18:12:21 -0500 Subject: [PATCH 52/54] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 0310497822a..4a2d8dc6364 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 0310497822a7a673a330a5dd068b7aaa579a265e +Subproject commit 4a2d8dc636445b276288543882e076f254b3ae95 From 7312b41239c83112f57cd495a0d516d2f3547fa5 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 9 Nov 2024 22:55:20 +0100 Subject: [PATCH 53/54] Unify disallowed-positions test files into one file Also make the file have a third mode for where everything is cfg'd out to make sure it's an early error. --- ...sallowed-positions-without-feature-gate.rs | 340 ----- ...rr => disallowed-positions.feature.stderr} | 302 ++--- .../disallowed-positions.no_feature.stderr | 1111 +++++++++++++++++ ... => disallowed-positions.nofeature.stderr} | 462 ++++--- .../disallowed-positions.nothing.stderr | 862 +++++++++++++ .../disallowed-positions.rs | 58 +- 6 files changed, 2444 insertions(+), 691 deletions(-) delete mode 100644 tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.rs rename tests/ui/rfcs/rfc-2497-if-let-chains/{disallowed-positions.stderr => disallowed-positions.feature.stderr} (84%) create mode 100644 tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr rename tests/ui/rfcs/rfc-2497-if-let-chains/{disallowed-positions-without-feature-gate.stderr => disallowed-positions.nofeature.stderr} (70%) create mode 100644 tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.rs deleted file mode 100644 index 096036bb133..00000000000 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.rs +++ /dev/null @@ -1,340 +0,0 @@ -// Check that we don't suggest enabling a feature for code that's -// not accepted even with that feature. - -#![allow(irrefutable_let_patterns)] - -use std::ops::Range; - -fn main() {} - -fn _if() { - if (let 0 = 1) {} - //~^ ERROR expected expression, found `let` statement - - if (((let 0 = 1))) {} - //~^ ERROR expected expression, found `let` statement - - if (let 0 = 1) && true {} - //~^ ERROR expected expression, found `let` statement - - if true && (let 0 = 1) {} - //~^ ERROR expected expression, found `let` statement - - if (let 0 = 1) && (let 0 = 1) {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR expected expression, found `let` statement - - if (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR expected expression, found `let` statement - //~| ERROR expected expression, found `let` statement -} - -fn _while() { - while (let 0 = 1) {} - //~^ ERROR expected expression, found `let` statement - - while (((let 0 = 1))) {} - //~^ ERROR expected expression, found `let` statement - - while (let 0 = 1) && true {} - //~^ ERROR expected expression, found `let` statement - - while true && (let 0 = 1) {} - //~^ ERROR expected expression, found `let` statement - - while (let 0 = 1) && (let 0 = 1) {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR expected expression, found `let` statement - - while (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR expected expression, found `let` statement - //~| ERROR expected expression, found `let` statement -} - -fn _macros() { - macro_rules! use_expr { - ($e:expr) => { - if $e {} - while $e {} - } - } - use_expr!((let 0 = 1 && 0 == 0)); - //~^ ERROR expected expression, found `let` statement - use_expr!((let 0 = 1)); - //~^ ERROR expected expression, found `let` statement -} - -fn nested_within_if_expr() { - if &let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - - if !let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - if *let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - if -let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - - fn _check_try_binds_tighter() -> Result<(), ()> { - if let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `Try` - Ok(()) - } - if (let 0 = 0)? {} - //~^ ERROR expected expression, found `let` statement - - if true || let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - if (true || let 0 = 0) {} - //~^ ERROR expected expression, found `let` statement - if true && (true || let 0 = 0) {} - //~^ ERROR expected expression, found `let` statement - if true || (true && let 0 = 0) {} - //~^ ERROR expected expression, found `let` statement - - let mut x = true; - if x = let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - - if true..(let 0 = 0) {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types - if ..(let 0 = 0) {} - //~^ ERROR expected expression, found `let` statement - if (let 0 = 0).. {} - //~^ ERROR expected expression, found `let` statement - - // Binds as `(let ... = true)..true &&/|| false`. - if let Range { start: _, end: _ } = true..true && false {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types - if let Range { start: _, end: _ } = true..true || false {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types - - // Binds as `(let Range { start: F, end } = F)..(|| true)`. - const F: fn() -> bool = || true; - if let Range { start: F, end } = F..|| true {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types - - // Binds as `(let Range { start: true, end } = t)..(&&false)`. - let t = &&true; - if let Range { start: true, end } = t..&&false {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types - - if let true = let true = true {} - //~^ ERROR expected expression, found `let` statement -} - -fn nested_within_while_expr() { - while &let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - - while !let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - while *let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - while -let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - - fn _check_try_binds_tighter() -> Result<(), ()> { - while let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `Try` - Ok(()) - } - while (let 0 = 0)? {} - //~^ ERROR expected expression, found `let` statement - - while true || let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - while (true || let 0 = 0) {} - //~^ ERROR expected expression, found `let` statement - while true && (true || let 0 = 0) {} - //~^ ERROR expected expression, found `let` statement - while true || (true && let 0 = 0) {} - //~^ ERROR expected expression, found `let` statement - - let mut x = true; - while x = let 0 = 0 {} - //~^ ERROR expected expression, found `let` statement - - while true..(let 0 = 0) {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types - while ..(let 0 = 0) {} - //~^ ERROR expected expression, found `let` statement - while (let 0 = 0).. {} - //~^ ERROR expected expression, found `let` statement - - // Binds as `(let ... = true)..true &&/|| false`. - while let Range { start: _, end: _ } = true..true && false {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types - while let Range { start: _, end: _ } = true..true || false {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types - - // Binds as `(let Range { start: F, end } = F)..(|| true)`. - const F: fn() -> bool = || true; - while let Range { start: F, end } = F..|| true {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types - - // Binds as `(let Range { start: true, end } = t)..(&&false)`. - let t = &&true; - while let Range { start: true, end } = t..&&false {} - //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types - - while let true = let true = true {} - //~^ ERROR expected expression, found `let` statement -} - -fn not_error_because_clarified_intent() { - if let Range { start: _, end: _ } = (true..true || false) { } - - if let Range { start: _, end: _ } = (true..true && false) { } - - while let Range { start: _, end: _ } = (true..true || false) { } - - while let Range { start: _, end: _ } = (true..true && false) { } -} - -fn outside_if_and_while_expr() { - &let 0 = 0; - //~^ ERROR expected expression, found `let` statement - - !let 0 = 0; - //~^ ERROR expected expression, found `let` statement - *let 0 = 0; - //~^ ERROR expected expression, found `let` statement - -let 0 = 0; - //~^ ERROR expected expression, found `let` statement - let _ = let _ = 3; - //~^ ERROR expected expression, found `let` statement - - fn _check_try_binds_tighter() -> Result<(), ()> { - let 0 = 0?; - //~^ ERROR the `?` operator can only be applied to values that implement `Try` - Ok(()) - } - (let 0 = 0)?; - //~^ ERROR expected expression, found `let` statement - - true || let 0 = 0; - //~^ ERROR expected expression, found `let` statement - (true || let 0 = 0); - //~^ ERROR expected expression, found `let` statement - true && (true || let 0 = 0); - //~^ ERROR expected expression, found `let` statement - - let mut x = true; - x = let 0 = 0; - //~^ ERROR expected expression, found `let` statement - - true..(let 0 = 0); - //~^ ERROR expected expression, found `let` statement - ..(let 0 = 0); - //~^ ERROR expected expression, found `let` statement - (let 0 = 0)..; - //~^ ERROR expected expression, found `let` statement - - (let Range { start: _, end: _ } = true..true || false); - //~^ ERROR mismatched types - //~| ERROR expected expression, found `let` statement - - (let true = let true = true); - //~^ ERROR expected expression, found `let` statement - //~| ERROR expected expression, found `let` statement - - { - #[cfg(FALSE)] - let x = true && let y = 1; - //~^ ERROR expected expression, found `let` statement - } - - #[cfg(FALSE)] - { - [1, 2, 3][let _ = ()] - //~^ ERROR expected expression, found `let` statement - } - - // Check function tail position. - &let 0 = 0 - //~^ ERROR expected expression, found `let` statement -} - -// Let's make sure that `let` inside const generic arguments are considered. -fn inside_const_generic_arguments() { - struct A; - impl A<{B}> { const O: u32 = 5; } - - if let A::<{ - true && let 1 = 1 - //~^ ERROR expected expression, found `let` statement - }>::O = 5 {} - - while let A::<{ - true && let 1 = 1 - //~^ ERROR expected expression, found `let` statement - }>::O = 5 {} - - if A::<{ - true && let 1 = 1 - //~^ ERROR expected expression, found `let` statement - }>::O == 5 {} - - // In the cases above we have `ExprKind::Block` to help us out. - // Below however, we would not have a block and so an implementation might go - // from visiting expressions to types without banning `let` expressions down the tree. - // This tests ensures that we are not caught by surprise should the parser - // admit non-IDENT expressions in const generic arguments. - - if A::< - true && let 1 = 1 - //~^ ERROR expressions must be enclosed in braces - //~| ERROR expected expression, found `let` statement - >::O == 5 {} -} - -fn with_parenthesis() { - let opt = Some(Some(1i32)); - - if (let Some(a) = opt && true) { - //~^ ERROR expected expression, found `let` statement - } - - if (let Some(a) = opt) && true { - //~^ ERROR expected expression, found `let` statement - } - if (let Some(a) = opt) && (let Some(b) = a) { - //~^ ERROR expected expression, found `let` statement - //~| ERROR expected expression, found `let` statement - } - - if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { - //~^ ERROR expected expression, found `let` statement - //~| ERROR expected expression, found `let` statement - } - if (let Some(a) = opt && (let Some(b) = a)) && true { - //~^ ERROR expected expression, found `let` statement - //~| ERROR expected expression, found `let` statement - } - if (let Some(a) = opt && (true)) && true { - //~^ ERROR expected expression, found `let` statement - } - - #[cfg(FALSE)] - let x = (true && let y = 1); - //~^ ERROR expected expression, found `let` statement - - #[cfg(FALSE)] - { - ([1, 2, 3][let _ = ()]) - //~^ ERROR expected expression, found `let` statement - } -} diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr similarity index 84% rename from tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.stderr rename to tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr index ab58abf4d46..ae3856b7e75 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr @@ -1,239 +1,239 @@ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:29:9 + --> $DIR/disallowed-positions.rs:32:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:29:9 + --> $DIR/disallowed-positions.rs:32:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:32:11 + --> $DIR/disallowed-positions.rs:35:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:32:11 + --> $DIR/disallowed-positions.rs:35:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:35:9 + --> $DIR/disallowed-positions.rs:38:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:35:9 + --> $DIR/disallowed-positions.rs:38:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:38:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:38:17 + --> $DIR/disallowed-positions.rs:41:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:41:9 + --> $DIR/disallowed-positions.rs:44:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:41:9 + --> $DIR/disallowed-positions.rs:44:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:41:24 + --> $DIR/disallowed-positions.rs:44:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:41:24 + --> $DIR/disallowed-positions.rs:44:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:45:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:45:48 + --> $DIR/disallowed-positions.rs:48:48 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:45:61 + --> $DIR/disallowed-positions.rs:48:61 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:45:35 + --> $DIR/disallowed-positions.rs:48:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:52:12 + --> $DIR/disallowed-positions.rs:58:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:52:12 + --> $DIR/disallowed-positions.rs:58:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:55:14 + --> $DIR/disallowed-positions.rs:61:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:55:14 + --> $DIR/disallowed-positions.rs:61:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:58:12 + --> $DIR/disallowed-positions.rs:64:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:58:12 + --> $DIR/disallowed-positions.rs:64:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:61:20 + --> $DIR/disallowed-positions.rs:67:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:61:20 + --> $DIR/disallowed-positions.rs:67:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:64:12 + --> $DIR/disallowed-positions.rs:70:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:64:12 + --> $DIR/disallowed-positions.rs:70:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:64:27 + --> $DIR/disallowed-positions.rs:70:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:64:27 + --> $DIR/disallowed-positions.rs:70:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:68:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:68:51 + --> $DIR/disallowed-positions.rs:74:51 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:68:64 + --> $DIR/disallowed-positions.rs:74:64 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:68:38 + --> $DIR/disallowed-positions.rs:74:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:88:9 + --> $DIR/disallowed-positions.rs:98:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:91:9 + --> $DIR/disallowed-positions.rs:101:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:93:9 + --> $DIR/disallowed-positions.rs:103:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:95:9 + --> $DIR/disallowed-positions.rs:105:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:103:9 + --> $DIR/disallowed-positions.rs:113:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:106:16 + --> $DIR/disallowed-positions.rs:116:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:106:13 + --> $DIR/disallowed-positions.rs:116:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:108:17 + --> $DIR/disallowed-positions.rs:118:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:110:25 + --> $DIR/disallowed-positions.rs:120:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:112:25 + --> $DIR/disallowed-positions.rs:122:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:116:12 + --> $DIR/disallowed-positions.rs:126:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:119:15 + --> $DIR/disallowed-positions.rs:129:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:122:11 + --> $DIR/disallowed-positions.rs:132:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:124:9 + --> $DIR/disallowed-positions.rs:134:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:128:8 + --> $DIR/disallowed-positions.rs:138:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:131:8 + --> $DIR/disallowed-positions.rs:141:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:137:8 + --> $DIR/disallowed-positions.rs:147:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:143:8 + --> $DIR/disallowed-positions.rs:153:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:147:19 + --> $DIR/disallowed-positions.rs:157:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:152:12 + --> $DIR/disallowed-positions.rs:163:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -390,7 +390,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:155:12 + --> $DIR/disallowed-positions.rs:166:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -398,7 +398,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:157:12 + --> $DIR/disallowed-positions.rs:168:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -406,7 +406,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:159:12 + --> $DIR/disallowed-positions.rs:170:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:167:12 + --> $DIR/disallowed-positions.rs:178:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -422,20 +422,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:19 + --> $DIR/disallowed-positions.rs:181:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:170:16 + --> $DIR/disallowed-positions.rs:181:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:172:20 + --> $DIR/disallowed-positions.rs:183:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -443,7 +443,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:174:28 + --> $DIR/disallowed-positions.rs:185:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -451,7 +451,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:176:28 + --> $DIR/disallowed-positions.rs:187:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -459,7 +459,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:180:15 + --> $DIR/disallowed-positions.rs:191:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -467,7 +467,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:183:18 + --> $DIR/disallowed-positions.rs:194:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -475,7 +475,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:186:14 + --> $DIR/disallowed-positions.rs:197:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -483,7 +483,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:188:12 + --> $DIR/disallowed-positions.rs:199:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -491,7 +491,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:192:11 + --> $DIR/disallowed-positions.rs:203:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -499,7 +499,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:195:11 + --> $DIR/disallowed-positions.rs:206:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:201:11 + --> $DIR/disallowed-positions.rs:212:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:207:11 + --> $DIR/disallowed-positions.rs:218:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:211:22 + --> $DIR/disallowed-positions.rs:222:22 | LL | while let true = let true = true {} | ^^^ @@ -531,7 +531,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:226:6 + --> $DIR/disallowed-positions.rs:239:6 | LL | &let 0 = 0; | ^^^ @@ -539,7 +539,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:229:6 + --> $DIR/disallowed-positions.rs:242:6 | LL | !let 0 = 0; | ^^^ @@ -547,7 +547,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:231:6 + --> $DIR/disallowed-positions.rs:244:6 | LL | *let 0 = 0; | ^^^ @@ -555,7 +555,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:233:6 + --> $DIR/disallowed-positions.rs:246:6 | LL | -let 0 = 0; | ^^^ @@ -563,7 +563,15 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:241:6 + --> $DIR/disallowed-positions.rs:248:13 + | +LL | let _ = let _ = 3; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:256:6 | LL | (let 0 = 0)?; | ^^^ @@ -571,7 +579,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:244:13 + --> $DIR/disallowed-positions.rs:259:13 | LL | true || let 0 = 0; | ^^^ @@ -579,7 +587,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:246:14 + --> $DIR/disallowed-positions.rs:261:14 | LL | (true || let 0 = 0); | ^^^ @@ -587,7 +595,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:248:22 + --> $DIR/disallowed-positions.rs:263:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -595,7 +603,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:252:9 + --> $DIR/disallowed-positions.rs:267:9 | LL | x = let 0 = 0; | ^^^ @@ -603,7 +611,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:255:12 + --> $DIR/disallowed-positions.rs:270:12 | LL | true..(let 0 = 0); | ^^^ @@ -611,7 +619,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:257:8 + --> $DIR/disallowed-positions.rs:272:8 | LL | ..(let 0 = 0); | ^^^ @@ -619,7 +627,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:259:6 + --> $DIR/disallowed-positions.rs:274:6 | LL | (let 0 = 0)..; | ^^^ @@ -627,7 +635,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:262:6 + --> $DIR/disallowed-positions.rs:277:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -635,7 +643,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:266:6 + --> $DIR/disallowed-positions.rs:281:6 | LL | (let true = let true = true); | ^^^ @@ -643,7 +651,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:266:17 + --> $DIR/disallowed-positions.rs:281:17 | LL | (let true = let true = true); | ^^^ @@ -651,7 +659,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:25 + --> $DIR/disallowed-positions.rs:287:25 | LL | let x = true && let y = 1; | ^^^ @@ -659,7 +667,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:278:19 + --> $DIR/disallowed-positions.rs:293:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -667,7 +675,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:283:6 + --> $DIR/disallowed-positions.rs:298:6 | LL | &let 0 = 0 | ^^^ @@ -675,23 +683,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:293:17 - | -LL | true && let 1 = 1 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:298:17 - | -LL | true && let 1 = 1 - | ^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:303:17 + --> $DIR/disallowed-positions.rs:309:17 | LL | true && let 1 = 1 | ^^^ @@ -706,8 +698,24 @@ LL | true && let 1 = 1 | = note: only supported directly in conditions of `if` and `while` expressions +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:319:17 + | +LL | true && let 1 = 1 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:330:17 + | +LL | true && let 1 = 1 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:314:9 + --> $DIR/disallowed-positions.rs:330:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -718,124 +726,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:323:9 + --> $DIR/disallowed-positions.rs:340:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:323:9 + --> $DIR/disallowed-positions.rs:340:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:327:9 + --> $DIR/disallowed-positions.rs:344:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:327:9 + --> $DIR/disallowed-positions.rs:344:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:9 + --> $DIR/disallowed-positions.rs:347:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:330:9 + --> $DIR/disallowed-positions.rs:347:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:32 + --> $DIR/disallowed-positions.rs:347:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:330:32 + --> $DIR/disallowed-positions.rs:347:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:337:9 + --> $DIR/disallowed-positions.rs:355:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:337:9 + --> $DIR/disallowed-positions.rs:355:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:337:31 + --> $DIR/disallowed-positions.rs:355:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:337:31 + --> $DIR/disallowed-positions.rs:355:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:341:9 + --> $DIR/disallowed-positions.rs:359:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:341:9 + --> $DIR/disallowed-positions.rs:359:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:341:31 + --> $DIR/disallowed-positions.rs:359:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:341:31 + --> $DIR/disallowed-positions.rs:359:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:345:9 + --> $DIR/disallowed-positions.rs:363:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:345:9 + --> $DIR/disallowed-positions.rs:363:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:361:22 + --> $DIR/disallowed-positions.rs:383:22 | LL | let x = (true && let y = 1); | ^^^ @@ -843,7 +851,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:366:20 + --> $DIR/disallowed-positions.rs:388:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -851,7 +859,7 @@ LL | ([1, 2, 3][let _ = ()]) = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:81:16 + --> $DIR/disallowed-positions.rs:90:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ @@ -859,7 +867,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:83:16 + --> $DIR/disallowed-positions.rs:92:16 | LL | use_expr!((let 0 = 1)); | ^^^ @@ -867,7 +875,7 @@ LL | use_expr!((let 0 = 1)); = note: only supported directly in conditions of `if` and `while` expressions error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:119:8 + --> $DIR/disallowed-positions.rs:129:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -876,7 +884,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:128:12 + --> $DIR/disallowed-positions.rs:138:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -887,7 +895,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:131:12 + --> $DIR/disallowed-positions.rs:141:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -898,7 +906,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:137:12 + --> $DIR/disallowed-positions.rs:147:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -909,7 +917,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:143:12 + --> $DIR/disallowed-positions.rs:153:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -920,7 +928,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:99:20 + --> $DIR/disallowed-positions.rs:109:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -928,7 +936,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:183:11 + --> $DIR/disallowed-positions.rs:194:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -937,7 +945,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:192:15 + --> $DIR/disallowed-positions.rs:203:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -948,7 +956,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:195:15 + --> $DIR/disallowed-positions.rs:206:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -959,7 +967,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:201:15 + --> $DIR/disallowed-positions.rs:212:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -970,7 +978,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:207:15 + --> $DIR/disallowed-positions.rs:218:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -981,7 +989,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:163:23 + --> $DIR/disallowed-positions.rs:174:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -989,7 +997,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:262:10 + --> $DIR/disallowed-positions.rs:277:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1000,14 +1008,14 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:237:17 + --> $DIR/disallowed-positions.rs:252:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 104 previous errors +error: aborting due to 105 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr new file mode 100644 index 00000000000..fd418f4ed7c --- /dev/null +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr @@ -0,0 +1,1111 @@ +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:32:9 + | +LL | if (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:32:9 + | +LL | if (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:35:11 + | +LL | if (((let 0 = 1))) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:35:11 + | +LL | if (((let 0 = 1))) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:38:9 + | +LL | if (let 0 = 1) && true {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:38:9 + | +LL | if (let 0 = 1) && true {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:41:17 + | +LL | if true && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:41:17 + | +LL | if true && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:44:9 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:44:9 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:44:24 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:44:24 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:48:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:48:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:48:48 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:48:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:48:61 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:48:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:58:12 + | +LL | while (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:58:12 + | +LL | while (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:61:14 + | +LL | while (((let 0 = 1))) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:61:14 + | +LL | while (((let 0 = 1))) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:64:12 + | +LL | while (let 0 = 1) && true {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:64:12 + | +LL | while (let 0 = 1) && true {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:67:20 + | +LL | while true && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:67:20 + | +LL | while true && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:70:12 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:70:12 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:70:27 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:70:27 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:74:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:74:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:74:51 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:74:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:74:64 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:74:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:98:9 + | +LL | if &let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:101:9 + | +LL | if !let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:103:9 + | +LL | if *let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:105:9 + | +LL | if -let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:113:9 + | +LL | if (let 0 = 0)? {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:116:16 + | +LL | if true || let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:116:13 + | +LL | if true || let 0 = 0 {} + | ^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:118:17 + | +LL | if (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:120:25 + | +LL | if true && (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:122:25 + | +LL | if true || (true && let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:126:12 + | +LL | if x = let 0 = 0 {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:129:15 + | +LL | if true..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:132:11 + | +LL | if ..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:134:9 + | +LL | if (let 0 = 0).. {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:138:8 + | +LL | if let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:141:8 + | +LL | if let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:147:8 + | +LL | if let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:153:8 + | +LL | if let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:157:19 + | +LL | if let true = let true = true {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:163:12 + | +LL | while &let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:166:12 + | +LL | while !let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:168:12 + | +LL | while *let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:170:12 + | +LL | while -let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:178:12 + | +LL | while (let 0 = 0)? {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:181:19 + | +LL | while true || let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:181:16 + | +LL | while true || let 0 = 0 {} + | ^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:183:20 + | +LL | while (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:185:28 + | +LL | while true && (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:187:28 + | +LL | while true || (true && let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:191:15 + | +LL | while x = let 0 = 0 {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:194:18 + | +LL | while true..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:197:14 + | +LL | while ..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:199:12 + | +LL | while (let 0 = 0).. {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:203:11 + | +LL | while let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:206:11 + | +LL | while let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:212:11 + | +LL | while let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:218:11 + | +LL | while let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:222:22 + | +LL | while let true = let true = true {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:239:6 + | +LL | &let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:242:6 + | +LL | !let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:244:6 + | +LL | *let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:246:6 + | +LL | -let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:248:13 + | +LL | let _ = let _ = 3; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:256:6 + | +LL | (let 0 = 0)?; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:259:13 + | +LL | true || let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:261:14 + | +LL | (true || let 0 = 0); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:263:22 + | +LL | true && (true || let 0 = 0); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:267:9 + | +LL | x = let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:270:12 + | +LL | true..(let 0 = 0); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:272:8 + | +LL | ..(let 0 = 0); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:274:6 + | +LL | (let 0 = 0)..; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:277:6 + | +LL | (let Range { start: _, end: _ } = true..true || false); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:281:6 + | +LL | (let true = let true = true); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:281:17 + | +LL | (let true = let true = true); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:287:25 + | +LL | let x = true && let y = 1; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:293:19 + | +LL | [1, 2, 3][let _ = ()] + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:298:6 + | +LL | &let 0 = 0 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:309:17 + | +LL | true && let 1 = 1 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:314:17 + | +LL | true && let 1 = 1 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:319:17 + | +LL | true && let 1 = 1 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:330:17 + | +LL | true && let 1 = 1 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/disallowed-positions.rs:330:9 + | +LL | true && let 1 = 1 + | ^^^^^^^^^^^^^^^^^ + | +help: enclose the `const` expression in braces + | +LL | { true && let 1 = 1 } + | + + + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:340:9 + | +LL | if (let Some(a) = opt && true) { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:340:9 + | +LL | if (let Some(a) = opt && true) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:344:9 + | +LL | if (let Some(a) = opt) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:344:9 + | +LL | if (let Some(a) = opt) && true { + | ^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:347:9 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:347:9 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:347:32 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:347:32 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:355:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:355:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:355:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:355:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:359:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:359:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:359:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:359:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:363:9 + | +LL | if (let Some(a) = opt && (true)) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:363:9 + | +LL | if (let Some(a) = opt && (true)) && true { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:383:22 + | +LL | let x = (true && let y = 1); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:388:20 + | +LL | ([1, 2, 3][let _ = ()]) + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:90:16 + | +LL | use_expr!((let 0 = 1 && 0 == 0)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:92:16 + | +LL | use_expr!((let 0 = 1)); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:48:8 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:48:21 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:74:11 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:74:24 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:351:8 + | +LL | if let Some(a) = opt && (true && true) { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:367:28 + | +LL | if (true && (true)) && let Some(a) = opt { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:370:18 + | +LL | if (true) && let Some(a) = opt { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:373:16 + | +LL | if true && let Some(a) = opt { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:378:8 + | +LL | if let true = (true && fun()) && (true) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:129:8 + | +LL | if true..(let 0 = 0) {} + | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:138:12 + | +LL | if let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` + | | + | expected `bool`, found `Range<_>` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:141:12 + | +LL | if let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` + | | + | expected `bool`, found `Range<_>` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:147:12 + | +LL | if let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` + | | + | expected fn pointer, found `Range<_>` + | + = note: expected fn pointer `fn() -> bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:153:12 + | +LL | if let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` + | | + | expected `bool`, found `Range<_>` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/disallowed-positions.rs:109:20 + | +LL | if let 0 = 0? {} + | ^^ the `?` operator cannot be applied to type `{integer}` + | + = help: the trait `Try` is not implemented for `{integer}` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:194:11 + | +LL | while true..(let 0 = 0) {} + | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` + | + = note: expected type `bool` + found struct `std::ops::Range` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:203:15 + | +LL | while let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` + | | + | expected `bool`, found `Range<_>` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:206:15 + | +LL | while let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` + | | + | expected `bool`, found `Range<_>` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:212:15 + | +LL | while let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` + | | + | expected fn pointer, found `Range<_>` + | + = note: expected fn pointer `fn() -> bool` + found struct `std::ops::Range<_>` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:218:15 + | +LL | while let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` + | | + | expected `bool`, found `Range<_>` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/disallowed-positions.rs:174:23 + | +LL | while let 0 = 0? {} + | ^^ the `?` operator cannot be applied to type `{integer}` + | + = help: the trait `Try` is not implemented for `{integer}` + +error[E0308]: mismatched types + --> $DIR/disallowed-positions.rs:277:10 + | +LL | (let Range { start: _, end: _ } = true..true || false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` + | | + | expected `bool`, found `Range<_>` + | + = note: expected type `bool` + found struct `std::ops::Range<_>` + +error[E0277]: the `?` operator can only be applied to values that implement `Try` + --> $DIR/disallowed-positions.rs:252:17 + | +LL | let 0 = 0?; + | ^^ the `?` operator cannot be applied to type `{integer}` + | + = help: the trait `Try` is not implemented for `{integer}` + +error: aborting due to 114 previous errors + +Some errors have detailed explanations: E0277, E0308, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nofeature.stderr similarity index 70% rename from tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.stderr rename to tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nofeature.stderr index 31f389512ed..f556ecf7f91 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions-without-feature-gate.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nofeature.stderr @@ -1,239 +1,239 @@ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:11:9 + --> $DIR/disallowed-positions.rs:31:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:11:9 + --> $DIR/disallowed-positions.rs:31:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:14:11 + --> $DIR/disallowed-positions.rs:34:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:14:11 + --> $DIR/disallowed-positions.rs:34:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:17:9 + --> $DIR/disallowed-positions.rs:37:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:17:9 + --> $DIR/disallowed-positions.rs:37:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:20:17 + --> $DIR/disallowed-positions.rs:40:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:20:17 + --> $DIR/disallowed-positions.rs:40:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:23:9 + --> $DIR/disallowed-positions.rs:43:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:23:9 + --> $DIR/disallowed-positions.rs:43:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:23:24 + --> $DIR/disallowed-positions.rs:43:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:23:24 + --> $DIR/disallowed-positions.rs:43:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:27:9 + --> $DIR/disallowed-positions.rs:47:35 | -LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:27:9 - | -LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:27:22 - | -LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:27:9 - | -LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:27:35 - | -LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {} +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:27:9 + --> $DIR/disallowed-positions.rs:47:35 | -LL | if (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:34:12 + --> $DIR/disallowed-positions.rs:47:48 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:47:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:47:61 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:47:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:56:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:34:12 + --> $DIR/disallowed-positions.rs:56:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:37:14 + --> $DIR/disallowed-positions.rs:59:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:37:14 + --> $DIR/disallowed-positions.rs:59:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:40:12 + --> $DIR/disallowed-positions.rs:62:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:40:12 + --> $DIR/disallowed-positions.rs:62:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:43:20 + --> $DIR/disallowed-positions.rs:65:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:43:20 + --> $DIR/disallowed-positions.rs:65:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:46:12 + --> $DIR/disallowed-positions.rs:68:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:46:12 + --> $DIR/disallowed-positions.rs:68:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:46:27 + --> $DIR/disallowed-positions.rs:68:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:46:27 + --> $DIR/disallowed-positions.rs:68:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:50:12 + --> $DIR/disallowed-positions.rs:72:38 | -LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:50:12 - | -LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:50:25 - | -LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^ - | - = note: only supported directly in conditions of `if` and `while` expressions -note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:50:12 - | -LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:50:38 - | -LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {} +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:50:12 + --> $DIR/disallowed-positions.rs:72:38 | -LL | while (let 2 = 3 && let 3 = 4 && let 4 = 5) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:70:9 + --> $DIR/disallowed-positions.rs:72:51 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:72:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:72:64 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:72:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:95:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:73:9 + --> $DIR/disallowed-positions.rs:98:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:75:9 + --> $DIR/disallowed-positions.rs:100:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:77:9 + --> $DIR/disallowed-positions.rs:102:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:85:9 + --> $DIR/disallowed-positions.rs:110:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:88:16 + --> $DIR/disallowed-positions.rs:113:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions-without-feature-gate.rs:88:13 + --> $DIR/disallowed-positions.rs:113:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:90:17 + --> $DIR/disallowed-positions.rs:115:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:92:25 + --> $DIR/disallowed-positions.rs:117:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:94:25 + --> $DIR/disallowed-positions.rs:119:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:98:12 + --> $DIR/disallowed-positions.rs:123:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:101:15 + --> $DIR/disallowed-positions.rs:126:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:104:11 + --> $DIR/disallowed-positions.rs:129:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:106:9 + --> $DIR/disallowed-positions.rs:131:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:110:8 + --> $DIR/disallowed-positions.rs:135:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:113:8 + --> $DIR/disallowed-positions.rs:138:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:119:8 + --> $DIR/disallowed-positions.rs:144:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:125:8 + --> $DIR/disallowed-positions.rs:150:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:129:19 + --> $DIR/disallowed-positions.rs:154:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,7 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:134:12 + --> $DIR/disallowed-positions.rs:160:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -390,7 +390,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:137:12 + --> $DIR/disallowed-positions.rs:163:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -398,7 +398,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:139:12 + --> $DIR/disallowed-positions.rs:165:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -406,7 +406,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:141:12 + --> $DIR/disallowed-positions.rs:167:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -414,7 +414,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:149:12 + --> $DIR/disallowed-positions.rs:175:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -422,20 +422,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:152:19 + --> $DIR/disallowed-positions.rs:178:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions-without-feature-gate.rs:152:16 + --> $DIR/disallowed-positions.rs:178:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:154:20 + --> $DIR/disallowed-positions.rs:180:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -443,7 +443,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:156:28 + --> $DIR/disallowed-positions.rs:182:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -451,7 +451,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:158:28 + --> $DIR/disallowed-positions.rs:184:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -459,7 +459,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:162:15 + --> $DIR/disallowed-positions.rs:188:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -467,7 +467,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:165:18 + --> $DIR/disallowed-positions.rs:191:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -475,7 +475,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:168:14 + --> $DIR/disallowed-positions.rs:194:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -483,7 +483,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:170:12 + --> $DIR/disallowed-positions.rs:196:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -491,7 +491,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:174:11 + --> $DIR/disallowed-positions.rs:200:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -499,7 +499,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:177:11 + --> $DIR/disallowed-positions.rs:203:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,7 +507,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:183:11 + --> $DIR/disallowed-positions.rs:209:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -515,7 +515,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:189:11 + --> $DIR/disallowed-positions.rs:215:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -523,7 +523,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:193:22 + --> $DIR/disallowed-positions.rs:219:22 | LL | while let true = let true = true {} | ^^^ @@ -531,7 +531,7 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:208:6 + --> $DIR/disallowed-positions.rs:236:6 | LL | &let 0 = 0; | ^^^ @@ -539,7 +539,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:211:6 + --> $DIR/disallowed-positions.rs:239:6 | LL | !let 0 = 0; | ^^^ @@ -547,7 +547,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:213:6 + --> $DIR/disallowed-positions.rs:241:6 | LL | *let 0 = 0; | ^^^ @@ -555,7 +555,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:215:6 + --> $DIR/disallowed-positions.rs:243:6 | LL | -let 0 = 0; | ^^^ @@ -563,7 +563,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:217:13 + --> $DIR/disallowed-positions.rs:245:13 | LL | let _ = let _ = 3; | ^^^ @@ -571,7 +571,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:225:6 + --> $DIR/disallowed-positions.rs:253:6 | LL | (let 0 = 0)?; | ^^^ @@ -579,7 +579,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:228:13 + --> $DIR/disallowed-positions.rs:256:13 | LL | true || let 0 = 0; | ^^^ @@ -587,7 +587,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:230:14 + --> $DIR/disallowed-positions.rs:258:14 | LL | (true || let 0 = 0); | ^^^ @@ -595,7 +595,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:232:22 + --> $DIR/disallowed-positions.rs:260:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -603,7 +603,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:236:9 + --> $DIR/disallowed-positions.rs:264:9 | LL | x = let 0 = 0; | ^^^ @@ -611,7 +611,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:239:12 + --> $DIR/disallowed-positions.rs:267:12 | LL | true..(let 0 = 0); | ^^^ @@ -619,7 +619,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:241:8 + --> $DIR/disallowed-positions.rs:269:8 | LL | ..(let 0 = 0); | ^^^ @@ -627,7 +627,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:243:6 + --> $DIR/disallowed-positions.rs:271:6 | LL | (let 0 = 0)..; | ^^^ @@ -635,7 +635,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:246:6 + --> $DIR/disallowed-positions.rs:274:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -643,7 +643,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:250:6 + --> $DIR/disallowed-positions.rs:278:6 | LL | (let true = let true = true); | ^^^ @@ -651,7 +651,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:250:17 + --> $DIR/disallowed-positions.rs:278:17 | LL | (let true = let true = true); | ^^^ @@ -659,7 +659,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:256:25 + --> $DIR/disallowed-positions.rs:284:25 | LL | let x = true && let y = 1; | ^^^ @@ -667,7 +667,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:262:19 + --> $DIR/disallowed-positions.rs:290:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -675,7 +675,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:267:6 + --> $DIR/disallowed-positions.rs:295:6 | LL | &let 0 = 0 | ^^^ @@ -683,7 +683,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:277:17 + --> $DIR/disallowed-positions.rs:306:17 | LL | true && let 1 = 1 | ^^^ @@ -691,7 +691,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:282:17 + --> $DIR/disallowed-positions.rs:311:17 | LL | true && let 1 = 1 | ^^^ @@ -699,7 +699,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:287:17 + --> $DIR/disallowed-positions.rs:316:17 | LL | true && let 1 = 1 | ^^^ @@ -707,7 +707,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:298:17 + --> $DIR/disallowed-positions.rs:327:17 | LL | true && let 1 = 1 | ^^^ @@ -715,7 +715,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions-without-feature-gate.rs:298:9 + --> $DIR/disallowed-positions.rs:327:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -726,124 +726,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:307:9 + --> $DIR/disallowed-positions.rs:337:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:307:9 + --> $DIR/disallowed-positions.rs:337:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:311:9 + --> $DIR/disallowed-positions.rs:341:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:311:9 + --> $DIR/disallowed-positions.rs:341:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:314:9 + --> $DIR/disallowed-positions.rs:344:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:314:9 + --> $DIR/disallowed-positions.rs:344:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:314:32 + --> $DIR/disallowed-positions.rs:344:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:314:32 + --> $DIR/disallowed-positions.rs:344:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:319:9 + --> $DIR/disallowed-positions.rs:351:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:319:9 + --> $DIR/disallowed-positions.rs:351:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:319:31 + --> $DIR/disallowed-positions.rs:351:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:319:31 + --> $DIR/disallowed-positions.rs:351:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:323:9 + --> $DIR/disallowed-positions.rs:355:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:323:9 + --> $DIR/disallowed-positions.rs:355:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:323:31 + --> $DIR/disallowed-positions.rs:355:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:323:31 + --> $DIR/disallowed-positions.rs:355:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:327:9 + --> $DIR/disallowed-positions.rs:359:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions-without-feature-gate.rs:327:9 + --> $DIR/disallowed-positions.rs:359:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:332:22 + --> $DIR/disallowed-positions.rs:375:22 | LL | let x = (true && let y = 1); | ^^^ @@ -851,7 +851,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:337:20 + --> $DIR/disallowed-positions.rs:380:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -859,7 +859,7 @@ LL | ([1, 2, 3][let _ = ()]) = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:63:16 + --> $DIR/disallowed-positions.rs:87:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ @@ -867,15 +867,105 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions-without-feature-gate.rs:65:16 + --> $DIR/disallowed-positions.rs:89:16 | LL | use_expr!((let 0 = 1)); | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:47:8 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:47:21 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:72:11 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:72:24 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:348:8 + | +LL | if let Some(a) = opt && (true && true) { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:363:28 + | +LL | if (true && (true)) && let Some(a) = opt { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:365:18 + | +LL | if (true) && let Some(a) = opt { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:367:16 + | +LL | if true && let Some(a) = opt { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `let` expressions in this position are unstable + --> $DIR/disallowed-positions.rs:371:8 + | +LL | if let true = (true && fun()) && (true) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #53667 for more information + = help: add `#![feature(let_chains)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:101:8 + --> $DIR/disallowed-positions.rs:126:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -884,7 +974,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:110:12 + --> $DIR/disallowed-positions.rs:135:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -895,7 +985,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:113:12 + --> $DIR/disallowed-positions.rs:138:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -906,7 +996,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:119:12 + --> $DIR/disallowed-positions.rs:144:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -917,7 +1007,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:125:12 + --> $DIR/disallowed-positions.rs:150:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -928,7 +1018,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions-without-feature-gate.rs:81:20 + --> $DIR/disallowed-positions.rs:106:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -936,7 +1026,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:165:11 + --> $DIR/disallowed-positions.rs:191:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -945,7 +1035,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:174:15 + --> $DIR/disallowed-positions.rs:200:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -956,7 +1046,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:177:15 + --> $DIR/disallowed-positions.rs:203:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -967,7 +1057,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:183:15 + --> $DIR/disallowed-positions.rs:209:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -978,7 +1068,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:189:15 + --> $DIR/disallowed-positions.rs:215:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -989,7 +1079,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions-without-feature-gate.rs:145:23 + --> $DIR/disallowed-positions.rs:171:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -997,7 +1087,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions-without-feature-gate.rs:246:10 + --> $DIR/disallowed-positions.rs:274:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1008,14 +1098,14 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions-without-feature-gate.rs:221:17 + --> $DIR/disallowed-positions.rs:249:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 105 previous errors +error: aborting due to 114 previous errors -Some errors have detailed explanations: E0277, E0308. +Some errors have detailed explanations: E0277, E0308, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr new file mode 100644 index 00000000000..dbe694b6e94 --- /dev/null +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr @@ -0,0 +1,862 @@ +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:32:9 + | +LL | if (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:32:9 + | +LL | if (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:35:11 + | +LL | if (((let 0 = 1))) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:35:11 + | +LL | if (((let 0 = 1))) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:38:9 + | +LL | if (let 0 = 1) && true {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:38:9 + | +LL | if (let 0 = 1) && true {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:41:17 + | +LL | if true && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:41:17 + | +LL | if true && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:44:9 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:44:9 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:44:24 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:44:24 + | +LL | if (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:48:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:48:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:48:48 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:48:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:48:61 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:48:35 + | +LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:58:12 + | +LL | while (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:58:12 + | +LL | while (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:61:14 + | +LL | while (((let 0 = 1))) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:61:14 + | +LL | while (((let 0 = 1))) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:64:12 + | +LL | while (let 0 = 1) && true {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:64:12 + | +LL | while (let 0 = 1) && true {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:67:20 + | +LL | while true && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:67:20 + | +LL | while true && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:70:12 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:70:12 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:70:27 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:70:27 + | +LL | while (let 0 = 1) && (let 0 = 1) {} + | ^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:74:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:74:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:74:51 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:74:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:74:64 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:74:38 + | +LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:98:9 + | +LL | if &let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:101:9 + | +LL | if !let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:103:9 + | +LL | if *let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:105:9 + | +LL | if -let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:113:9 + | +LL | if (let 0 = 0)? {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:116:16 + | +LL | if true || let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:116:13 + | +LL | if true || let 0 = 0 {} + | ^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:118:17 + | +LL | if (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:120:25 + | +LL | if true && (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:122:25 + | +LL | if true || (true && let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:126:12 + | +LL | if x = let 0 = 0 {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:129:15 + | +LL | if true..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:132:11 + | +LL | if ..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:134:9 + | +LL | if (let 0 = 0).. {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:138:8 + | +LL | if let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:141:8 + | +LL | if let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:147:8 + | +LL | if let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:153:8 + | +LL | if let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:157:19 + | +LL | if let true = let true = true {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:163:12 + | +LL | while &let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:166:12 + | +LL | while !let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:168:12 + | +LL | while *let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:170:12 + | +LL | while -let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:178:12 + | +LL | while (let 0 = 0)? {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:181:19 + | +LL | while true || let 0 = 0 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `||` operators are not supported in let chain expressions + --> $DIR/disallowed-positions.rs:181:16 + | +LL | while true || let 0 = 0 {} + | ^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:183:20 + | +LL | while (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:185:28 + | +LL | while true && (true || let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:187:28 + | +LL | while true || (true && let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:191:15 + | +LL | while x = let 0 = 0 {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:194:18 + | +LL | while true..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:197:14 + | +LL | while ..(let 0 = 0) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:199:12 + | +LL | while (let 0 = 0).. {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:203:11 + | +LL | while let Range { start: _, end: _ } = true..true && false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:206:11 + | +LL | while let Range { start: _, end: _ } = true..true || false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:212:11 + | +LL | while let Range { start: F, end } = F..|| true {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:218:11 + | +LL | while let Range { start: true, end } = t..&&false {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:222:22 + | +LL | while let true = let true = true {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:239:6 + | +LL | &let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:242:6 + | +LL | !let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:244:6 + | +LL | *let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:246:6 + | +LL | -let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:248:13 + | +LL | let _ = let _ = 3; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:256:6 + | +LL | (let 0 = 0)?; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:259:13 + | +LL | true || let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:261:14 + | +LL | (true || let 0 = 0); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:263:22 + | +LL | true && (true || let 0 = 0); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:267:9 + | +LL | x = let 0 = 0; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:270:12 + | +LL | true..(let 0 = 0); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:272:8 + | +LL | ..(let 0 = 0); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:274:6 + | +LL | (let 0 = 0)..; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:277:6 + | +LL | (let Range { start: _, end: _ } = true..true || false); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:281:6 + | +LL | (let true = let true = true); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:281:17 + | +LL | (let true = let true = true); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:287:25 + | +LL | let x = true && let y = 1; + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:293:19 + | +LL | [1, 2, 3][let _ = ()] + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:298:6 + | +LL | &let 0 = 0 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:309:17 + | +LL | true && let 1 = 1 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:314:17 + | +LL | true && let 1 = 1 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:319:17 + | +LL | true && let 1 = 1 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:330:17 + | +LL | true && let 1 = 1 + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expressions must be enclosed in braces to be used as const generic arguments + --> $DIR/disallowed-positions.rs:330:9 + | +LL | true && let 1 = 1 + | ^^^^^^^^^^^^^^^^^ + | +help: enclose the `const` expression in braces + | +LL | { true && let 1 = 1 } + | + + + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:340:9 + | +LL | if (let Some(a) = opt && true) { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:340:9 + | +LL | if (let Some(a) = opt && true) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:344:9 + | +LL | if (let Some(a) = opt) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:344:9 + | +LL | if (let Some(a) = opt) && true { + | ^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:347:9 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:347:9 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:347:32 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:347:32 + | +LL | if (let Some(a) = opt) && (let Some(b) = a) { + | ^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:355:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:355:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:355:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:355:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { + | ^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:359:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:359:9 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:359:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:359:31 + | +LL | if (let Some(a) = opt && (let Some(b) = a)) && true { + | ^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:363:9 + | +LL | if (let Some(a) = opt && (true)) && true { + | ^^^^^^^^^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions +note: `let`s wrapped in parentheses are not supported in a context with let chains + --> $DIR/disallowed-positions.rs:363:9 + | +LL | if (let Some(a) = opt && (true)) && true { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:383:22 + | +LL | let x = (true && let y = 1); + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:388:20 + | +LL | ([1, 2, 3][let _ = ()]) + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: aborting due to 89 previous errors + diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs index 4ac3ea53a08..c0f7b03a6e3 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs @@ -1,3 +1,4 @@ +//@ revisions: no_feature feature nothing // Here we test that `lowering` behaves correctly wrt. `let $pats = $expr` expressions. // // We want to make sure that `let` is banned in situations other than: @@ -17,7 +18,8 @@ // // To that end, we check some positions which is not part of the language above. -#![feature(let_chains)] // Avoid inflating `.stderr` with overzealous gates in this test. +// Avoid inflating `.stderr` with overzealous gates (or test what happens if you disable the gate) +#![cfg_attr(not(no_feature), feature(let_chains))] #![allow(irrefutable_let_patterns)] @@ -25,6 +27,7 @@ fn main() {} +#[cfg(not(nothing))] fn _if() { if (let 0 = 1) {} //~^ ERROR expected expression, found `let` statement @@ -46,8 +49,11 @@ fn _if() { //~^ ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement + //[no_feature]~| ERROR `let` expressions in this position are unstable + //[no_feature]~| ERROR `let` expressions in this position are unstable } +#[cfg(not(nothing))] fn _while() { while (let 0 = 1) {} //~^ ERROR expected expression, found `let` statement @@ -69,8 +75,11 @@ fn _while() { //~^ ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement //~| ERROR expected expression, found `let` statement + //[no_feature]~| ERROR `let` expressions in this position are unstable + //[no_feature]~| ERROR `let` expressions in this position are unstable } +#[cfg(not(nothing))] fn _macros() { macro_rules! use_expr { ($e:expr) => { @@ -79,11 +88,12 @@ macro_rules! use_expr { } } use_expr!((let 0 = 1 && 0 == 0)); - //~^ ERROR expected expression, found `let` statement + //[feature,no_feature]~^ ERROR expected expression, found `let` statement use_expr!((let 0 = 1)); - //~^ ERROR expected expression, found `let` statement + //[feature,no_feature]~^ ERROR expected expression, found `let` statement } +#[cfg(not(nothing))] fn nested_within_if_expr() { if &let 0 = 0 {} //~^ ERROR expected expression, found `let` statement @@ -97,7 +107,7 @@ fn nested_within_if_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { if let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //[feature,no_feature]~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } if (let 0 = 0)? {} @@ -118,7 +128,7 @@ fn _check_try_binds_tighter() -> Result<(), ()> { if true..(let 0 = 0) {} //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types + //[feature,no_feature]~| ERROR mismatched types if ..(let 0 = 0) {} //~^ ERROR expected expression, found `let` statement if (let 0 = 0).. {} @@ -127,27 +137,28 @@ fn _check_try_binds_tighter() -> Result<(), ()> { // Binds as `(let ... = true)..true &&/|| false`. if let Range { start: _, end: _ } = true..true && false {} //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types + //[feature,no_feature]~| ERROR mismatched types if let Range { start: _, end: _ } = true..true || false {} //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types + //[feature,no_feature]~| ERROR mismatched types // Binds as `(let Range { start: F, end } = F)..(|| true)`. const F: fn() -> bool = || true; if let Range { start: F, end } = F..|| true {} //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types + //[feature,no_feature]~| ERROR mismatched types // Binds as `(let Range { start: true, end } = t)..(&&false)`. let t = &&true; if let Range { start: true, end } = t..&&false {} //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types + //[feature,no_feature]~| ERROR mismatched types if let true = let true = true {} //~^ ERROR expected expression, found `let` statement } +#[cfg(not(nothing))] fn nested_within_while_expr() { while &let 0 = 0 {} //~^ ERROR expected expression, found `let` statement @@ -161,7 +172,7 @@ fn nested_within_while_expr() { fn _check_try_binds_tighter() -> Result<(), ()> { while let 0 = 0? {} - //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //[feature,no_feature]~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } while (let 0 = 0)? {} @@ -182,7 +193,7 @@ fn _check_try_binds_tighter() -> Result<(), ()> { while true..(let 0 = 0) {} //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types + //[feature,no_feature]~| ERROR mismatched types while ..(let 0 = 0) {} //~^ ERROR expected expression, found `let` statement while (let 0 = 0).. {} @@ -191,27 +202,28 @@ fn _check_try_binds_tighter() -> Result<(), ()> { // Binds as `(let ... = true)..true &&/|| false`. while let Range { start: _, end: _ } = true..true && false {} //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types + //[feature,no_feature]~| ERROR mismatched types while let Range { start: _, end: _ } = true..true || false {} //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types + //[feature,no_feature]~| ERROR mismatched types // Binds as `(let Range { start: F, end } = F)..(|| true)`. const F: fn() -> bool = || true; while let Range { start: F, end } = F..|| true {} //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types + //[feature,no_feature]~| ERROR mismatched types // Binds as `(let Range { start: true, end } = t)..(&&false)`. let t = &&true; while let Range { start: true, end } = t..&&false {} //~^ ERROR expected expression, found `let` statement - //~| ERROR mismatched types + //[feature,no_feature]~| ERROR mismatched types while let true = let true = true {} //~^ ERROR expected expression, found `let` statement } +#[cfg(not(nothing))] fn not_error_because_clarified_intent() { if let Range { start: _, end: _ } = (true..true || false) { } @@ -222,6 +234,7 @@ fn not_error_because_clarified_intent() { while let Range { start: _, end: _ } = (true..true && false) { } } +#[cfg(not(nothing))] fn outside_if_and_while_expr() { &let 0 = 0; //~^ ERROR expected expression, found `let` statement @@ -232,10 +245,12 @@ fn outside_if_and_while_expr() { //~^ ERROR expected expression, found `let` statement -let 0 = 0; //~^ ERROR expected expression, found `let` statement + let _ = let _ = 3; + //~^ ERROR expected expression, found `let` statement fn _check_try_binds_tighter() -> Result<(), ()> { let 0 = 0?; - //~^ ERROR the `?` operator can only be applied to values that implement `Try` + //[feature,no_feature]~^ ERROR the `?` operator can only be applied to values that implement `Try` Ok(()) } (let 0 = 0)?; @@ -260,8 +275,8 @@ fn _check_try_binds_tighter() -> Result<(), ()> { //~^ ERROR expected expression, found `let` statement (let Range { start: _, end: _ } = true..true || false); - //~^ ERROR mismatched types - //~| ERROR expected expression, found `let` statement + //~^ ERROR expected expression, found `let` statement + //[feature,no_feature]~| ERROR mismatched types (let true = let true = true); //~^ ERROR expected expression, found `let` statement @@ -285,6 +300,7 @@ fn _check_try_binds_tighter() -> Result<(), ()> { } // Let's make sure that `let` inside const generic arguments are considered. +#[cfg(not(nothing))] fn inside_const_generic_arguments() { struct A; impl A<{B}> { const O: u32 = 5; } @@ -317,6 +333,7 @@ fn inside_const_generic_arguments() { >::O == 5 {} } +#[cfg(not(nothing))] fn with_parenthesis() { let opt = Some(Some(1i32)); @@ -332,6 +349,7 @@ fn with_parenthesis() { //~| ERROR expected expression, found `let` statement } if let Some(a) = opt && (true && true) { + //[no_feature]~^ ERROR `let` expressions in this position are unstable } if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { @@ -347,14 +365,18 @@ fn with_parenthesis() { } if (true && (true)) && let Some(a) = opt { + //[no_feature]~^ ERROR `let` expressions in this position are unstable } if (true) && let Some(a) = opt { + //[no_feature]~^ ERROR `let` expressions in this position are unstable } if true && let Some(a) = opt { + //[no_feature]~^ ERROR `let` expressions in this position are unstable } let fun = || true; if let true = (true && fun()) && (true) { + //[no_feature]~^ ERROR `let` expressions in this position are unstable } #[cfg(FALSE)] From 935bf6995f7cad774b12168b76d8253285a4101e Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 9 Nov 2024 23:31:11 +0100 Subject: [PATCH 54/54] Add more places where expressions can occur --- .../disallowed-positions.feature.stderr | 398 +++++++++++------ .../disallowed-positions.no_feature.stderr | 416 ++++++++++++------ .../disallowed-positions.nothing.stderr | 366 ++++++++++----- .../disallowed-positions.rs | 53 +++ 4 files changed, 835 insertions(+), 398 deletions(-) diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr index ae3856b7e75..db32b8c1de4 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.feature.stderr @@ -1,239 +1,239 @@ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:32:9 + --> $DIR/disallowed-positions.rs:33:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:32:9 + --> $DIR/disallowed-positions.rs:33:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:35:11 + --> $DIR/disallowed-positions.rs:36:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:35:11 + --> $DIR/disallowed-positions.rs:36:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:38:9 + --> $DIR/disallowed-positions.rs:39:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:38:9 + --> $DIR/disallowed-positions.rs:39:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:41:17 + --> $DIR/disallowed-positions.rs:42:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:41:17 + --> $DIR/disallowed-positions.rs:42:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:44:9 + --> $DIR/disallowed-positions.rs:45:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:44:9 + --> $DIR/disallowed-positions.rs:45:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:44:24 + --> $DIR/disallowed-positions.rs:45:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:44:24 + --> $DIR/disallowed-positions.rs:45:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:48:48 + --> $DIR/disallowed-positions.rs:49:48 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:48:61 + --> $DIR/disallowed-positions.rs:49:61 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:58:12 + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:58:12 + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:61:14 + --> $DIR/disallowed-positions.rs:62:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:61:14 + --> $DIR/disallowed-positions.rs:62:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:64:12 + --> $DIR/disallowed-positions.rs:65:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:64:12 + --> $DIR/disallowed-positions.rs:65:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:67:20 + --> $DIR/disallowed-positions.rs:68:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:67:20 + --> $DIR/disallowed-positions.rs:68:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:70:12 + --> $DIR/disallowed-positions.rs:71:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:70:12 + --> $DIR/disallowed-positions.rs:71:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:70:27 + --> $DIR/disallowed-positions.rs:71:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:70:27 + --> $DIR/disallowed-positions.rs:71:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:74:51 + --> $DIR/disallowed-positions.rs:75:51 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:74:64 + --> $DIR/disallowed-positions.rs:75:64 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:98:9 + --> $DIR/disallowed-positions.rs:99:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:101:9 + --> $DIR/disallowed-positions.rs:102:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:103:9 + --> $DIR/disallowed-positions.rs:104:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:105:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:113:9 + --> $DIR/disallowed-positions.rs:114:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:116:16 + --> $DIR/disallowed-positions.rs:117:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:116:13 + --> $DIR/disallowed-positions.rs:117:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:118:17 + --> $DIR/disallowed-positions.rs:119:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:120:25 + --> $DIR/disallowed-positions.rs:121:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:122:25 + --> $DIR/disallowed-positions.rs:123:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:126:12 + --> $DIR/disallowed-positions.rs:127:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:129:15 + --> $DIR/disallowed-positions.rs:130:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:132:11 + --> $DIR/disallowed-positions.rs:133:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:134:9 + --> $DIR/disallowed-positions.rs:135:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:138:8 + --> $DIR/disallowed-positions.rs:139:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:141:8 + --> $DIR/disallowed-positions.rs:142:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:147:8 + --> $DIR/disallowed-positions.rs:148:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:153:8 + --> $DIR/disallowed-positions.rs:154:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:157:19 + --> $DIR/disallowed-positions.rs:158:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,71 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:163:12 + --> $DIR/disallowed-positions.rs:161:15 + | +LL | if return let 0 = 0 {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:164:21 + | +LL | loop { if break let 0 = 0 {} } + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:167:15 + | +LL | if (match let 0 = 0 { _ => { false } }) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:170:9 + | +LL | if (let 0 = 0, false).1 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:173:9 + | +LL | if (let 0 = 0,) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:177:13 + | +LL | if (let 0 = 0).await {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:181:12 + | +LL | if (|| let 0 = 0) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:184:9 + | +LL | if (let 0 = 0)() {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:190:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -390,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:166:12 + --> $DIR/disallowed-positions.rs:193:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -398,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:168:12 + --> $DIR/disallowed-positions.rs:195:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -406,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -414,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:178:12 + --> $DIR/disallowed-positions.rs:205:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -422,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:19 + --> $DIR/disallowed-positions.rs:208:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:181:16 + --> $DIR/disallowed-positions.rs:208:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:183:20 + --> $DIR/disallowed-positions.rs:210:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -443,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:185:28 + --> $DIR/disallowed-positions.rs:212:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -451,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:187:28 + --> $DIR/disallowed-positions.rs:214:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -459,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:191:15 + --> $DIR/disallowed-positions.rs:218:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -467,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:194:18 + --> $DIR/disallowed-positions.rs:221:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -475,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:14 + --> $DIR/disallowed-positions.rs:224:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -483,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:199:12 + --> $DIR/disallowed-positions.rs:226:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -491,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:203:11 + --> $DIR/disallowed-positions.rs:230:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -499,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:206:11 + --> $DIR/disallowed-positions.rs:233:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:11 + --> $DIR/disallowed-positions.rs:239:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -515,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:11 + --> $DIR/disallowed-positions.rs:245:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -523,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:222:22 + --> $DIR/disallowed-positions.rs:249:22 | LL | while let true = let true = true {} | ^^^ @@ -531,7 +595,71 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:6 + --> $DIR/disallowed-positions.rs:252:18 + | +LL | while return let 0 = 0 {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:255:39 + | +LL | 'outer: loop { while break 'outer let 0 = 0 {} } + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:258:18 + | +LL | while (match let 0 = 0 { _ => { false } }) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:261:12 + | +LL | while (let 0 = 0, false).1 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:264:12 + | +LL | while (let 0 = 0,) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:268:16 + | +LL | while (let 0 = 0).await {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:272:15 + | +LL | while (|| let 0 = 0) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:275:12 + | +LL | while (let 0 = 0)() {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:292:6 | LL | &let 0 = 0; | ^^^ @@ -539,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:242:6 + --> $DIR/disallowed-positions.rs:295:6 | LL | !let 0 = 0; | ^^^ @@ -547,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:244:6 + --> $DIR/disallowed-positions.rs:297:6 | LL | *let 0 = 0; | ^^^ @@ -555,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:246:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | -let 0 = 0; | ^^^ @@ -563,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:248:13 + --> $DIR/disallowed-positions.rs:301:13 | LL | let _ = let _ = 3; | ^^^ @@ -571,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:256:6 + --> $DIR/disallowed-positions.rs:309:6 | LL | (let 0 = 0)?; | ^^^ @@ -579,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:259:13 + --> $DIR/disallowed-positions.rs:312:13 | LL | true || let 0 = 0; | ^^^ @@ -587,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:14 + --> $DIR/disallowed-positions.rs:314:14 | LL | (true || let 0 = 0); | ^^^ @@ -595,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:263:22 + --> $DIR/disallowed-positions.rs:316:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -603,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:267:9 + --> $DIR/disallowed-positions.rs:320:9 | LL | x = let 0 = 0; | ^^^ @@ -611,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:270:12 + --> $DIR/disallowed-positions.rs:323:12 | LL | true..(let 0 = 0); | ^^^ @@ -619,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:8 + --> $DIR/disallowed-positions.rs:325:8 | LL | ..(let 0 = 0); | ^^^ @@ -627,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:274:6 + --> $DIR/disallowed-positions.rs:327:6 | LL | (let 0 = 0)..; | ^^^ @@ -635,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:277:6 + --> $DIR/disallowed-positions.rs:330:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -643,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:281:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let true = let true = true); | ^^^ @@ -651,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:281:17 + --> $DIR/disallowed-positions.rs:334:17 | LL | (let true = let true = true); | ^^^ @@ -659,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:287:25 + --> $DIR/disallowed-positions.rs:340:25 | LL | let x = true && let y = 1; | ^^^ @@ -667,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:293:19 + --> $DIR/disallowed-positions.rs:346:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -675,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:298:6 + --> $DIR/disallowed-positions.rs:351:6 | LL | &let 0 = 0 | ^^^ @@ -683,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:17 + --> $DIR/disallowed-positions.rs:362:17 | LL | true && let 1 = 1 | ^^^ @@ -691,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:17 + --> $DIR/disallowed-positions.rs:367:17 | LL | true && let 1 = 1 | ^^^ @@ -699,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:319:17 + --> $DIR/disallowed-positions.rs:372:17 | LL | true && let 1 = 1 | ^^^ @@ -707,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:17 + --> $DIR/disallowed-positions.rs:383:17 | LL | true && let 1 = 1 | ^^^ @@ -715,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:330:9 + --> $DIR/disallowed-positions.rs:383:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -726,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:9 + --> $DIR/disallowed-positions.rs:393:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:340:9 + --> $DIR/disallowed-positions.rs:393:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:344:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:347:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:347:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:347:32 + --> $DIR/disallowed-positions.rs:400:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:347:32 + --> $DIR/disallowed-positions.rs:400:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:9 + --> $DIR/disallowed-positions.rs:408:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:355:9 + --> $DIR/disallowed-positions.rs:408:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:31 + --> $DIR/disallowed-positions.rs:408:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:355:31 + --> $DIR/disallowed-positions.rs:408:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:359:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:359:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:359:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:359:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:363:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:363:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:22 + --> $DIR/disallowed-positions.rs:436:22 | LL | let x = (true && let y = 1); | ^^^ @@ -851,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:388:20 + --> $DIR/disallowed-positions.rs:441:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -859,7 +987,7 @@ LL | ([1, 2, 3][let _ = ()]) = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:90:16 + --> $DIR/disallowed-positions.rs:91:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ @@ -867,7 +995,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:92:16 + --> $DIR/disallowed-positions.rs:93:16 | LL | use_expr!((let 0 = 1)); | ^^^ @@ -875,7 +1003,7 @@ LL | use_expr!((let 0 = 1)); = note: only supported directly in conditions of `if` and `while` expressions error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:129:8 + --> $DIR/disallowed-positions.rs:130:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -884,7 +1012,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:138:12 + --> $DIR/disallowed-positions.rs:139:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -895,7 +1023,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:141:12 + --> $DIR/disallowed-positions.rs:142:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -906,7 +1034,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:147:12 + --> $DIR/disallowed-positions.rs:148:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -917,7 +1045,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:153:12 + --> $DIR/disallowed-positions.rs:154:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -928,7 +1056,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:109:20 + --> $DIR/disallowed-positions.rs:110:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -936,7 +1064,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:194:11 + --> $DIR/disallowed-positions.rs:221:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -945,7 +1073,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:203:15 + --> $DIR/disallowed-positions.rs:230:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -956,7 +1084,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:206:15 + --> $DIR/disallowed-positions.rs:233:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -967,7 +1095,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:212:15 + --> $DIR/disallowed-positions.rs:239:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -978,7 +1106,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:245:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -989,7 +1117,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:174:23 + --> $DIR/disallowed-positions.rs:201:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -997,7 +1125,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:277:10 + --> $DIR/disallowed-positions.rs:330:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1008,14 +1136,14 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:252:17 + --> $DIR/disallowed-positions.rs:305:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 105 previous errors +error: aborting due to 121 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr index fd418f4ed7c..ad16a0f8ed8 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.no_feature.stderr @@ -1,239 +1,239 @@ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:32:9 + --> $DIR/disallowed-positions.rs:33:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:32:9 + --> $DIR/disallowed-positions.rs:33:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:35:11 + --> $DIR/disallowed-positions.rs:36:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:35:11 + --> $DIR/disallowed-positions.rs:36:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:38:9 + --> $DIR/disallowed-positions.rs:39:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:38:9 + --> $DIR/disallowed-positions.rs:39:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:41:17 + --> $DIR/disallowed-positions.rs:42:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:41:17 + --> $DIR/disallowed-positions.rs:42:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:44:9 + --> $DIR/disallowed-positions.rs:45:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:44:9 + --> $DIR/disallowed-positions.rs:45:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:44:24 + --> $DIR/disallowed-positions.rs:45:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:44:24 + --> $DIR/disallowed-positions.rs:45:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:48:48 + --> $DIR/disallowed-positions.rs:49:48 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:48:61 + --> $DIR/disallowed-positions.rs:49:61 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:58:12 + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:58:12 + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:61:14 + --> $DIR/disallowed-positions.rs:62:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:61:14 + --> $DIR/disallowed-positions.rs:62:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:64:12 + --> $DIR/disallowed-positions.rs:65:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:64:12 + --> $DIR/disallowed-positions.rs:65:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:67:20 + --> $DIR/disallowed-positions.rs:68:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:67:20 + --> $DIR/disallowed-positions.rs:68:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:70:12 + --> $DIR/disallowed-positions.rs:71:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:70:12 + --> $DIR/disallowed-positions.rs:71:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:70:27 + --> $DIR/disallowed-positions.rs:71:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:70:27 + --> $DIR/disallowed-positions.rs:71:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:74:51 + --> $DIR/disallowed-positions.rs:75:51 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:74:64 + --> $DIR/disallowed-positions.rs:75:64 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:98:9 + --> $DIR/disallowed-positions.rs:99:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:101:9 + --> $DIR/disallowed-positions.rs:102:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:103:9 + --> $DIR/disallowed-positions.rs:104:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:105:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:113:9 + --> $DIR/disallowed-positions.rs:114:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:116:16 + --> $DIR/disallowed-positions.rs:117:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:116:13 + --> $DIR/disallowed-positions.rs:117:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:118:17 + --> $DIR/disallowed-positions.rs:119:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:120:25 + --> $DIR/disallowed-positions.rs:121:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:122:25 + --> $DIR/disallowed-positions.rs:123:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:126:12 + --> $DIR/disallowed-positions.rs:127:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:129:15 + --> $DIR/disallowed-positions.rs:130:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:132:11 + --> $DIR/disallowed-positions.rs:133:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:134:9 + --> $DIR/disallowed-positions.rs:135:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:138:8 + --> $DIR/disallowed-positions.rs:139:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:141:8 + --> $DIR/disallowed-positions.rs:142:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:147:8 + --> $DIR/disallowed-positions.rs:148:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:153:8 + --> $DIR/disallowed-positions.rs:154:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:157:19 + --> $DIR/disallowed-positions.rs:158:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,71 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:163:12 + --> $DIR/disallowed-positions.rs:161:15 + | +LL | if return let 0 = 0 {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:164:21 + | +LL | loop { if break let 0 = 0 {} } + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:167:15 + | +LL | if (match let 0 = 0 { _ => { false } }) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:170:9 + | +LL | if (let 0 = 0, false).1 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:173:9 + | +LL | if (let 0 = 0,) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:177:13 + | +LL | if (let 0 = 0).await {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:181:12 + | +LL | if (|| let 0 = 0) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:184:9 + | +LL | if (let 0 = 0)() {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:190:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -390,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:166:12 + --> $DIR/disallowed-positions.rs:193:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -398,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:168:12 + --> $DIR/disallowed-positions.rs:195:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -406,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -414,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:178:12 + --> $DIR/disallowed-positions.rs:205:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -422,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:19 + --> $DIR/disallowed-positions.rs:208:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:181:16 + --> $DIR/disallowed-positions.rs:208:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:183:20 + --> $DIR/disallowed-positions.rs:210:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -443,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:185:28 + --> $DIR/disallowed-positions.rs:212:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -451,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:187:28 + --> $DIR/disallowed-positions.rs:214:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -459,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:191:15 + --> $DIR/disallowed-positions.rs:218:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -467,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:194:18 + --> $DIR/disallowed-positions.rs:221:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -475,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:14 + --> $DIR/disallowed-positions.rs:224:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -483,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:199:12 + --> $DIR/disallowed-positions.rs:226:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -491,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:203:11 + --> $DIR/disallowed-positions.rs:230:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -499,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:206:11 + --> $DIR/disallowed-positions.rs:233:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:11 + --> $DIR/disallowed-positions.rs:239:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -515,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:11 + --> $DIR/disallowed-positions.rs:245:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -523,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:222:22 + --> $DIR/disallowed-positions.rs:249:22 | LL | while let true = let true = true {} | ^^^ @@ -531,7 +595,71 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:6 + --> $DIR/disallowed-positions.rs:252:18 + | +LL | while return let 0 = 0 {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:255:39 + | +LL | 'outer: loop { while break 'outer let 0 = 0 {} } + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:258:18 + | +LL | while (match let 0 = 0 { _ => { false } }) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:261:12 + | +LL | while (let 0 = 0, false).1 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:264:12 + | +LL | while (let 0 = 0,) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:268:16 + | +LL | while (let 0 = 0).await {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:272:15 + | +LL | while (|| let 0 = 0) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:275:12 + | +LL | while (let 0 = 0)() {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:292:6 | LL | &let 0 = 0; | ^^^ @@ -539,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:242:6 + --> $DIR/disallowed-positions.rs:295:6 | LL | !let 0 = 0; | ^^^ @@ -547,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:244:6 + --> $DIR/disallowed-positions.rs:297:6 | LL | *let 0 = 0; | ^^^ @@ -555,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:246:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | -let 0 = 0; | ^^^ @@ -563,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:248:13 + --> $DIR/disallowed-positions.rs:301:13 | LL | let _ = let _ = 3; | ^^^ @@ -571,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:256:6 + --> $DIR/disallowed-positions.rs:309:6 | LL | (let 0 = 0)?; | ^^^ @@ -579,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:259:13 + --> $DIR/disallowed-positions.rs:312:13 | LL | true || let 0 = 0; | ^^^ @@ -587,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:14 + --> $DIR/disallowed-positions.rs:314:14 | LL | (true || let 0 = 0); | ^^^ @@ -595,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:263:22 + --> $DIR/disallowed-positions.rs:316:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -603,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:267:9 + --> $DIR/disallowed-positions.rs:320:9 | LL | x = let 0 = 0; | ^^^ @@ -611,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:270:12 + --> $DIR/disallowed-positions.rs:323:12 | LL | true..(let 0 = 0); | ^^^ @@ -619,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:8 + --> $DIR/disallowed-positions.rs:325:8 | LL | ..(let 0 = 0); | ^^^ @@ -627,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:274:6 + --> $DIR/disallowed-positions.rs:327:6 | LL | (let 0 = 0)..; | ^^^ @@ -635,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:277:6 + --> $DIR/disallowed-positions.rs:330:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -643,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:281:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let true = let true = true); | ^^^ @@ -651,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:281:17 + --> $DIR/disallowed-positions.rs:334:17 | LL | (let true = let true = true); | ^^^ @@ -659,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:287:25 + --> $DIR/disallowed-positions.rs:340:25 | LL | let x = true && let y = 1; | ^^^ @@ -667,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:293:19 + --> $DIR/disallowed-positions.rs:346:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -675,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:298:6 + --> $DIR/disallowed-positions.rs:351:6 | LL | &let 0 = 0 | ^^^ @@ -683,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:17 + --> $DIR/disallowed-positions.rs:362:17 | LL | true && let 1 = 1 | ^^^ @@ -691,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:17 + --> $DIR/disallowed-positions.rs:367:17 | LL | true && let 1 = 1 | ^^^ @@ -699,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:319:17 + --> $DIR/disallowed-positions.rs:372:17 | LL | true && let 1 = 1 | ^^^ @@ -707,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:17 + --> $DIR/disallowed-positions.rs:383:17 | LL | true && let 1 = 1 | ^^^ @@ -715,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:330:9 + --> $DIR/disallowed-positions.rs:383:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -726,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:9 + --> $DIR/disallowed-positions.rs:393:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:340:9 + --> $DIR/disallowed-positions.rs:393:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:344:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:347:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:347:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:347:32 + --> $DIR/disallowed-positions.rs:400:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:347:32 + --> $DIR/disallowed-positions.rs:400:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:9 + --> $DIR/disallowed-positions.rs:408:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:355:9 + --> $DIR/disallowed-positions.rs:408:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:31 + --> $DIR/disallowed-positions.rs:408:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:355:31 + --> $DIR/disallowed-positions.rs:408:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:359:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:359:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:359:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:359:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:363:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:363:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:22 + --> $DIR/disallowed-positions.rs:436:22 | LL | let x = (true && let y = 1); | ^^^ @@ -851,7 +979,7 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:388:20 + --> $DIR/disallowed-positions.rs:441:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ @@ -859,7 +987,7 @@ LL | ([1, 2, 3][let _ = ()]) = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:90:16 + --> $DIR/disallowed-positions.rs:91:16 | LL | use_expr!((let 0 = 1 && 0 == 0)); | ^^^ @@ -867,7 +995,7 @@ LL | use_expr!((let 0 = 1 && 0 == 0)); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:92:16 + --> $DIR/disallowed-positions.rs:93:16 | LL | use_expr!((let 0 = 1)); | ^^^ @@ -875,7 +1003,7 @@ LL | use_expr!((let 0 = 1)); = note: only supported directly in conditions of `if` and `while` expressions error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:48:8 + --> $DIR/disallowed-positions.rs:49:8 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ @@ -885,7 +1013,7 @@ LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:48:21 + --> $DIR/disallowed-positions.rs:49:21 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ @@ -895,7 +1023,7 @@ LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:74:11 + --> $DIR/disallowed-positions.rs:75:11 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ @@ -905,7 +1033,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:74:24 + --> $DIR/disallowed-positions.rs:75:24 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ @@ -915,7 +1043,7 @@ LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:351:8 + --> $DIR/disallowed-positions.rs:404:8 | LL | if let Some(a) = opt && (true && true) { | ^^^^^^^^^^^^^^^^^ @@ -925,7 +1053,7 @@ LL | if let Some(a) = opt && (true && true) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:367:28 + --> $DIR/disallowed-positions.rs:420:28 | LL | if (true && (true)) && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -935,7 +1063,7 @@ LL | if (true && (true)) && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:370:18 + --> $DIR/disallowed-positions.rs:423:18 | LL | if (true) && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -945,7 +1073,7 @@ LL | if (true) && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:373:16 + --> $DIR/disallowed-positions.rs:426:16 | LL | if true && let Some(a) = opt { | ^^^^^^^^^^^^^^^^^ @@ -955,7 +1083,7 @@ LL | if true && let Some(a) = opt { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `let` expressions in this position are unstable - --> $DIR/disallowed-positions.rs:378:8 + --> $DIR/disallowed-positions.rs:431:8 | LL | if let true = (true && fun()) && (true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -965,7 +1093,7 @@ LL | if let true = (true && fun()) && (true) { = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:129:8 + --> $DIR/disallowed-positions.rs:130:8 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -974,7 +1102,7 @@ LL | if true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:138:12 + --> $DIR/disallowed-positions.rs:139:12 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -985,7 +1113,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:141:12 + --> $DIR/disallowed-positions.rs:142:12 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -996,7 +1124,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:147:12 + --> $DIR/disallowed-positions.rs:148:12 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1007,7 +1135,7 @@ LL | if let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:153:12 + --> $DIR/disallowed-positions.rs:154:12 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1018,7 +1146,7 @@ LL | if let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:109:20 + --> $DIR/disallowed-positions.rs:110:20 | LL | if let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1026,7 +1154,7 @@ LL | if let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:194:11 + --> $DIR/disallowed-positions.rs:221:11 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^^^^^^^^^ expected `bool`, found `Range` @@ -1035,7 +1163,7 @@ LL | while true..(let 0 = 0) {} found struct `std::ops::Range` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:203:15 + --> $DIR/disallowed-positions.rs:230:15 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1046,7 +1174,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:206:15 + --> $DIR/disallowed-positions.rs:233:15 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1057,7 +1185,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:212:15 + --> $DIR/disallowed-positions.rs:239:15 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `fn() -> bool` @@ -1068,7 +1196,7 @@ LL | while let Range { start: F, end } = F..|| true {} found struct `std::ops::Range<_>` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:218:15 + --> $DIR/disallowed-positions.rs:245:15 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `&&bool` @@ -1079,7 +1207,7 @@ LL | while let Range { start: true, end } = t..&&false {} found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:174:23 + --> $DIR/disallowed-positions.rs:201:23 | LL | while let 0 = 0? {} | ^^ the `?` operator cannot be applied to type `{integer}` @@ -1087,7 +1215,7 @@ LL | while let 0 = 0? {} = help: the trait `Try` is not implemented for `{integer}` error[E0308]: mismatched types - --> $DIR/disallowed-positions.rs:277:10 + --> $DIR/disallowed-positions.rs:330:10 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ---- this expression has type `bool` @@ -1098,14 +1226,14 @@ LL | (let Range { start: _, end: _ } = true..true || false); found struct `std::ops::Range<_>` error[E0277]: the `?` operator can only be applied to values that implement `Try` - --> $DIR/disallowed-positions.rs:252:17 + --> $DIR/disallowed-positions.rs:305:17 | LL | let 0 = 0?; | ^^ the `?` operator cannot be applied to type `{integer}` | = help: the trait `Try` is not implemented for `{integer}` -error: aborting due to 114 previous errors +error: aborting due to 130 previous errors Some errors have detailed explanations: E0277, E0308, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr index dbe694b6e94..2d5fd1144ad 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.nothing.stderr @@ -1,239 +1,239 @@ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:32:9 + --> $DIR/disallowed-positions.rs:33:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:32:9 + --> $DIR/disallowed-positions.rs:33:9 | LL | if (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:35:11 + --> $DIR/disallowed-positions.rs:36:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:35:11 + --> $DIR/disallowed-positions.rs:36:11 | LL | if (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:38:9 + --> $DIR/disallowed-positions.rs:39:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:38:9 + --> $DIR/disallowed-positions.rs:39:9 | LL | if (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:41:17 + --> $DIR/disallowed-positions.rs:42:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:41:17 + --> $DIR/disallowed-positions.rs:42:17 | LL | if true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:44:9 + --> $DIR/disallowed-positions.rs:45:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:44:9 + --> $DIR/disallowed-positions.rs:45:9 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:44:24 + --> $DIR/disallowed-positions.rs:45:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:44:24 + --> $DIR/disallowed-positions.rs:45:24 | LL | if (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:48:48 + --> $DIR/disallowed-positions.rs:49:48 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:48:61 + --> $DIR/disallowed-positions.rs:49:61 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:48:35 + --> $DIR/disallowed-positions.rs:49:35 | LL | if let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:58:12 + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:58:12 + --> $DIR/disallowed-positions.rs:59:12 | LL | while (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:61:14 + --> $DIR/disallowed-positions.rs:62:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:61:14 + --> $DIR/disallowed-positions.rs:62:14 | LL | while (((let 0 = 1))) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:64:12 + --> $DIR/disallowed-positions.rs:65:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:64:12 + --> $DIR/disallowed-positions.rs:65:12 | LL | while (let 0 = 1) && true {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:67:20 + --> $DIR/disallowed-positions.rs:68:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:67:20 + --> $DIR/disallowed-positions.rs:68:20 | LL | while true && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:70:12 + --> $DIR/disallowed-positions.rs:71:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:70:12 + --> $DIR/disallowed-positions.rs:71:12 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:70:27 + --> $DIR/disallowed-positions.rs:71:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:70:27 + --> $DIR/disallowed-positions.rs:71:27 | LL | while (let 0 = 1) && (let 0 = 1) {} | ^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:74:51 + --> $DIR/disallowed-positions.rs:75:51 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:74:64 + --> $DIR/disallowed-positions.rs:75:64 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:74:38 + --> $DIR/disallowed-positions.rs:75:38 | LL | while let 0 = 1 && let 1 = 2 && (let 2 = 3 && let 3 = 4 && let 4 = 5) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:98:9 + --> $DIR/disallowed-positions.rs:99:9 | LL | if &let 0 = 0 {} | ^^^^^^^^^ @@ -241,7 +241,7 @@ LL | if &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:101:9 + --> $DIR/disallowed-positions.rs:102:9 | LL | if !let 0 = 0 {} | ^^^^^^^^^ @@ -249,7 +249,7 @@ LL | if !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:103:9 + --> $DIR/disallowed-positions.rs:104:9 | LL | if *let 0 = 0 {} | ^^^^^^^^^ @@ -257,7 +257,7 @@ LL | if *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:105:9 + --> $DIR/disallowed-positions.rs:106:9 | LL | if -let 0 = 0 {} | ^^^^^^^^^ @@ -265,7 +265,7 @@ LL | if -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:113:9 + --> $DIR/disallowed-positions.rs:114:9 | LL | if (let 0 = 0)? {} | ^^^^^^^^^ @@ -273,20 +273,20 @@ LL | if (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:116:16 + --> $DIR/disallowed-positions.rs:117:16 | LL | if true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:116:13 + --> $DIR/disallowed-positions.rs:117:13 | LL | if true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:118:17 + --> $DIR/disallowed-positions.rs:119:17 | LL | if (true || let 0 = 0) {} | ^^^^^^^^^ @@ -294,7 +294,7 @@ LL | if (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:120:25 + --> $DIR/disallowed-positions.rs:121:25 | LL | if true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -302,7 +302,7 @@ LL | if true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:122:25 + --> $DIR/disallowed-positions.rs:123:25 | LL | if true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -310,7 +310,7 @@ LL | if true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:126:12 + --> $DIR/disallowed-positions.rs:127:12 | LL | if x = let 0 = 0 {} | ^^^ @@ -318,7 +318,7 @@ LL | if x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:129:15 + --> $DIR/disallowed-positions.rs:130:15 | LL | if true..(let 0 = 0) {} | ^^^^^^^^^ @@ -326,7 +326,7 @@ LL | if true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:132:11 + --> $DIR/disallowed-positions.rs:133:11 | LL | if ..(let 0 = 0) {} | ^^^^^^^^^ @@ -334,7 +334,7 @@ LL | if ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:134:9 + --> $DIR/disallowed-positions.rs:135:9 | LL | if (let 0 = 0).. {} | ^^^^^^^^^ @@ -342,7 +342,7 @@ LL | if (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:138:8 + --> $DIR/disallowed-positions.rs:139:8 | LL | if let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -350,7 +350,7 @@ LL | if let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:141:8 + --> $DIR/disallowed-positions.rs:142:8 | LL | if let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -358,7 +358,7 @@ LL | if let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:147:8 + --> $DIR/disallowed-positions.rs:148:8 | LL | if let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -366,7 +366,7 @@ LL | if let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:153:8 + --> $DIR/disallowed-positions.rs:154:8 | LL | if let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -374,7 +374,7 @@ LL | if let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:157:19 + --> $DIR/disallowed-positions.rs:158:19 | LL | if let true = let true = true {} | ^^^ @@ -382,7 +382,71 @@ LL | if let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:163:12 + --> $DIR/disallowed-positions.rs:161:15 + | +LL | if return let 0 = 0 {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:164:21 + | +LL | loop { if break let 0 = 0 {} } + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:167:15 + | +LL | if (match let 0 = 0 { _ => { false } }) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:170:9 + | +LL | if (let 0 = 0, false).1 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:173:9 + | +LL | if (let 0 = 0,) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:177:13 + | +LL | if (let 0 = 0).await {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:181:12 + | +LL | if (|| let 0 = 0) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:184:9 + | +LL | if (let 0 = 0)() {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:190:12 | LL | while &let 0 = 0 {} | ^^^^^^^^^ @@ -390,7 +454,7 @@ LL | while &let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:166:12 + --> $DIR/disallowed-positions.rs:193:12 | LL | while !let 0 = 0 {} | ^^^^^^^^^ @@ -398,7 +462,7 @@ LL | while !let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:168:12 + --> $DIR/disallowed-positions.rs:195:12 | LL | while *let 0 = 0 {} | ^^^^^^^^^ @@ -406,7 +470,7 @@ LL | while *let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:170:12 + --> $DIR/disallowed-positions.rs:197:12 | LL | while -let 0 = 0 {} | ^^^^^^^^^ @@ -414,7 +478,7 @@ LL | while -let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:178:12 + --> $DIR/disallowed-positions.rs:205:12 | LL | while (let 0 = 0)? {} | ^^^^^^^^^ @@ -422,20 +486,20 @@ LL | while (let 0 = 0)? {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:181:19 + --> $DIR/disallowed-positions.rs:208:19 | LL | while true || let 0 = 0 {} | ^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `||` operators are not supported in let chain expressions - --> $DIR/disallowed-positions.rs:181:16 + --> $DIR/disallowed-positions.rs:208:16 | LL | while true || let 0 = 0 {} | ^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:183:20 + --> $DIR/disallowed-positions.rs:210:20 | LL | while (true || let 0 = 0) {} | ^^^^^^^^^ @@ -443,7 +507,7 @@ LL | while (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:185:28 + --> $DIR/disallowed-positions.rs:212:28 | LL | while true && (true || let 0 = 0) {} | ^^^^^^^^^ @@ -451,7 +515,7 @@ LL | while true && (true || let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:187:28 + --> $DIR/disallowed-positions.rs:214:28 | LL | while true || (true && let 0 = 0) {} | ^^^^^^^^^ @@ -459,7 +523,7 @@ LL | while true || (true && let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:191:15 + --> $DIR/disallowed-positions.rs:218:15 | LL | while x = let 0 = 0 {} | ^^^ @@ -467,7 +531,7 @@ LL | while x = let 0 = 0 {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:194:18 + --> $DIR/disallowed-positions.rs:221:18 | LL | while true..(let 0 = 0) {} | ^^^^^^^^^ @@ -475,7 +539,7 @@ LL | while true..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:197:14 + --> $DIR/disallowed-positions.rs:224:14 | LL | while ..(let 0 = 0) {} | ^^^^^^^^^ @@ -483,7 +547,7 @@ LL | while ..(let 0 = 0) {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:199:12 + --> $DIR/disallowed-positions.rs:226:12 | LL | while (let 0 = 0).. {} | ^^^^^^^^^ @@ -491,7 +555,7 @@ LL | while (let 0 = 0).. {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:203:11 + --> $DIR/disallowed-positions.rs:230:11 | LL | while let Range { start: _, end: _ } = true..true && false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -499,7 +563,7 @@ LL | while let Range { start: _, end: _ } = true..true && false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:206:11 + --> $DIR/disallowed-positions.rs:233:11 | LL | while let Range { start: _, end: _ } = true..true || false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,7 +571,7 @@ LL | while let Range { start: _, end: _ } = true..true || false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:212:11 + --> $DIR/disallowed-positions.rs:239:11 | LL | while let Range { start: F, end } = F..|| true {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -515,7 +579,7 @@ LL | while let Range { start: F, end } = F..|| true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:218:11 + --> $DIR/disallowed-positions.rs:245:11 | LL | while let Range { start: true, end } = t..&&false {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -523,7 +587,7 @@ LL | while let Range { start: true, end } = t..&&false {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:222:22 + --> $DIR/disallowed-positions.rs:249:22 | LL | while let true = let true = true {} | ^^^ @@ -531,7 +595,71 @@ LL | while let true = let true = true {} = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:239:6 + --> $DIR/disallowed-positions.rs:252:18 + | +LL | while return let 0 = 0 {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:255:39 + | +LL | 'outer: loop { while break 'outer let 0 = 0 {} } + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:258:18 + | +LL | while (match let 0 = 0 { _ => { false } }) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:261:12 + | +LL | while (let 0 = 0, false).1 {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:264:12 + | +LL | while (let 0 = 0,) {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:268:16 + | +LL | while (let 0 = 0).await {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:272:15 + | +LL | while (|| let 0 = 0) {} + | ^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:275:12 + | +LL | while (let 0 = 0)() {} + | ^^^^^^^^^ + | + = note: only supported directly in conditions of `if` and `while` expressions + +error: expected expression, found `let` statement + --> $DIR/disallowed-positions.rs:292:6 | LL | &let 0 = 0; | ^^^ @@ -539,7 +667,7 @@ LL | &let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:242:6 + --> $DIR/disallowed-positions.rs:295:6 | LL | !let 0 = 0; | ^^^ @@ -547,7 +675,7 @@ LL | !let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:244:6 + --> $DIR/disallowed-positions.rs:297:6 | LL | *let 0 = 0; | ^^^ @@ -555,7 +683,7 @@ LL | *let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:246:6 + --> $DIR/disallowed-positions.rs:299:6 | LL | -let 0 = 0; | ^^^ @@ -563,7 +691,7 @@ LL | -let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:248:13 + --> $DIR/disallowed-positions.rs:301:13 | LL | let _ = let _ = 3; | ^^^ @@ -571,7 +699,7 @@ LL | let _ = let _ = 3; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:256:6 + --> $DIR/disallowed-positions.rs:309:6 | LL | (let 0 = 0)?; | ^^^ @@ -579,7 +707,7 @@ LL | (let 0 = 0)?; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:259:13 + --> $DIR/disallowed-positions.rs:312:13 | LL | true || let 0 = 0; | ^^^ @@ -587,7 +715,7 @@ LL | true || let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:261:14 + --> $DIR/disallowed-positions.rs:314:14 | LL | (true || let 0 = 0); | ^^^ @@ -595,7 +723,7 @@ LL | (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:263:22 + --> $DIR/disallowed-positions.rs:316:22 | LL | true && (true || let 0 = 0); | ^^^ @@ -603,7 +731,7 @@ LL | true && (true || let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:267:9 + --> $DIR/disallowed-positions.rs:320:9 | LL | x = let 0 = 0; | ^^^ @@ -611,7 +739,7 @@ LL | x = let 0 = 0; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:270:12 + --> $DIR/disallowed-positions.rs:323:12 | LL | true..(let 0 = 0); | ^^^ @@ -619,7 +747,7 @@ LL | true..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:272:8 + --> $DIR/disallowed-positions.rs:325:8 | LL | ..(let 0 = 0); | ^^^ @@ -627,7 +755,7 @@ LL | ..(let 0 = 0); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:274:6 + --> $DIR/disallowed-positions.rs:327:6 | LL | (let 0 = 0)..; | ^^^ @@ -635,7 +763,7 @@ LL | (let 0 = 0)..; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:277:6 + --> $DIR/disallowed-positions.rs:330:6 | LL | (let Range { start: _, end: _ } = true..true || false); | ^^^ @@ -643,7 +771,7 @@ LL | (let Range { start: _, end: _ } = true..true || false); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:281:6 + --> $DIR/disallowed-positions.rs:334:6 | LL | (let true = let true = true); | ^^^ @@ -651,7 +779,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:281:17 + --> $DIR/disallowed-positions.rs:334:17 | LL | (let true = let true = true); | ^^^ @@ -659,7 +787,7 @@ LL | (let true = let true = true); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:287:25 + --> $DIR/disallowed-positions.rs:340:25 | LL | let x = true && let y = 1; | ^^^ @@ -667,7 +795,7 @@ LL | let x = true && let y = 1; = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:293:19 + --> $DIR/disallowed-positions.rs:346:19 | LL | [1, 2, 3][let _ = ()] | ^^^ @@ -675,7 +803,7 @@ LL | [1, 2, 3][let _ = ()] = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:298:6 + --> $DIR/disallowed-positions.rs:351:6 | LL | &let 0 = 0 | ^^^ @@ -683,7 +811,7 @@ LL | &let 0 = 0 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:309:17 + --> $DIR/disallowed-positions.rs:362:17 | LL | true && let 1 = 1 | ^^^ @@ -691,7 +819,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:314:17 + --> $DIR/disallowed-positions.rs:367:17 | LL | true && let 1 = 1 | ^^^ @@ -699,7 +827,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:319:17 + --> $DIR/disallowed-positions.rs:372:17 | LL | true && let 1 = 1 | ^^^ @@ -707,7 +835,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:330:17 + --> $DIR/disallowed-positions.rs:383:17 | LL | true && let 1 = 1 | ^^^ @@ -715,7 +843,7 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if` and `while` expressions error: expressions must be enclosed in braces to be used as const generic arguments - --> $DIR/disallowed-positions.rs:330:9 + --> $DIR/disallowed-positions.rs:383:9 | LL | true && let 1 = 1 | ^^^^^^^^^^^^^^^^^ @@ -726,124 +854,124 @@ LL | { true && let 1 = 1 } | + + error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:340:9 + --> $DIR/disallowed-positions.rs:393:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:340:9 + --> $DIR/disallowed-positions.rs:393:9 | LL | if (let Some(a) = opt && true) { | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:344:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:344:9 + --> $DIR/disallowed-positions.rs:397:9 | LL | if (let Some(a) = opt) && true { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:347:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:347:9 + --> $DIR/disallowed-positions.rs:400:9 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:347:32 + --> $DIR/disallowed-positions.rs:400:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:347:32 + --> $DIR/disallowed-positions.rs:400:32 | LL | if (let Some(a) = opt) && (let Some(b) = a) { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:9 + --> $DIR/disallowed-positions.rs:408:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:355:9 + --> $DIR/disallowed-positions.rs:408:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:355:31 + --> $DIR/disallowed-positions.rs:408:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:355:31 + --> $DIR/disallowed-positions.rs:408:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && b == 1 { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:359:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:359:9 + --> $DIR/disallowed-positions.rs:412:9 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:359:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:359:31 + --> $DIR/disallowed-positions.rs:412:31 | LL | if (let Some(a) = opt && (let Some(b) = a)) && true { | ^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:363:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^ | = note: only supported directly in conditions of `if` and `while` expressions note: `let`s wrapped in parentheses are not supported in a context with let chains - --> $DIR/disallowed-positions.rs:363:9 + --> $DIR/disallowed-positions.rs:416:9 | LL | if (let Some(a) = opt && (true)) && true { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:383:22 + --> $DIR/disallowed-positions.rs:436:22 | LL | let x = (true && let y = 1); | ^^^ @@ -851,12 +979,12 @@ LL | let x = (true && let y = 1); = note: only supported directly in conditions of `if` and `while` expressions error: expected expression, found `let` statement - --> $DIR/disallowed-positions.rs:388:20 + --> $DIR/disallowed-positions.rs:441:20 | LL | ([1, 2, 3][let _ = ()]) | ^^^ | = note: only supported directly in conditions of `if` and `while` expressions -error: aborting due to 89 previous errors +error: aborting due to 105 previous errors diff --git a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs index c0f7b03a6e3..8eb8d617d58 100644 --- a/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs +++ b/tests/ui/rfcs/rfc-2497-if-let-chains/disallowed-positions.rs @@ -1,4 +1,5 @@ //@ revisions: no_feature feature nothing +//@ edition: 2021 // Here we test that `lowering` behaves correctly wrt. `let $pats = $expr` expressions. // // We want to make sure that `let` is banned in situations other than: @@ -156,6 +157,32 @@ fn _check_try_binds_tighter() -> Result<(), ()> { if let true = let true = true {} //~^ ERROR expected expression, found `let` statement + + if return let 0 = 0 {} + //~^ ERROR expected expression, found `let` statement + + loop { if break let 0 = 0 {} } + //~^ ERROR expected expression, found `let` statement + + if (match let 0 = 0 { _ => { false } }) {} + //~^ ERROR expected expression, found `let` statement + + if (let 0 = 0, false).1 {} + //~^ ERROR expected expression, found `let` statement + + if (let 0 = 0,) {} + //~^ ERROR expected expression, found `let` statement + + async fn foo() { + if (let 0 = 0).await {} + //~^ ERROR expected expression, found `let` statement + } + + if (|| let 0 = 0) {} + //~^ ERROR expected expression, found `let` statement + + if (let 0 = 0)() {} + //~^ ERROR expected expression, found `let` statement } #[cfg(not(nothing))] @@ -221,6 +248,32 @@ fn _check_try_binds_tighter() -> Result<(), ()> { while let true = let true = true {} //~^ ERROR expected expression, found `let` statement + + while return let 0 = 0 {} + //~^ ERROR expected expression, found `let` statement + + 'outer: loop { while break 'outer let 0 = 0 {} } + //~^ ERROR expected expression, found `let` statement + + while (match let 0 = 0 { _ => { false } }) {} + //~^ ERROR expected expression, found `let` statement + + while (let 0 = 0, false).1 {} + //~^ ERROR expected expression, found `let` statement + + while (let 0 = 0,) {} + //~^ ERROR expected expression, found `let` statement + + async fn foo() { + while (let 0 = 0).await {} + //~^ ERROR expected expression, found `let` statement + } + + while (|| let 0 = 0) {} + //~^ ERROR expected expression, found `let` statement + + while (let 0 = 0)() {} + //~^ ERROR expected expression, found `let` statement } #[cfg(not(nothing))]