From b7e68dfc945c4cf8d1753cc3a8be48a71bb39d5a Mon Sep 17 00:00:00 2001 From: joboet Date: Sat, 18 Mar 2023 20:06:12 +0100 Subject: [PATCH 1/7] std: make `Debug` representations of `[Lazy, Once]*[Cell, Lock]` consistent with `Mutex` and `RwLock` `Mutex` prints `` as a field value when its inner value cannot be accessed, but the lazy types print a fixed string like "`OnceCell(Uninit)`". This could cause confusion if the inner type is a unit type named `Uninit` and does not respect the pretty-printing flag. With this change, the format message is now "`OnceCell()`", consistent with `Mutex`. --- library/core/src/cell/once.rs | 8 +++++--- library/core/src/fmt/mod.rs | 20 +++++--------------- library/std/src/sync/lazy_lock.rs | 8 +++++--- library/std/src/sync/mutex.rs | 8 +------- library/std/src/sync/once_lock.rs | 8 +++++--- library/std/src/sync/rwlock.rs | 8 +------- 6 files changed, 22 insertions(+), 38 deletions(-) diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 5dc2d52319800..c9655c180f9c2 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -250,10 +250,12 @@ impl Default for OnceCell { #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for OnceCell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut d = f.debug_tuple("OnceCell"); match self.get() { - Some(v) => f.debug_tuple("OnceCell").field(v).finish(), - None => f.write_str("OnceCell(Uninit)"), - } + Some(v) => d.field(v), + None => d.field(&format_args!("")), + }; + d.finish() } } diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index fcda097f01fce..0c7b2c5df991c 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2669,22 +2669,12 @@ impl Debug for Cell { #[stable(feature = "rust1", since = "1.0.0")] impl Debug for RefCell { fn fmt(&self, f: &mut Formatter<'_>) -> Result { + let mut d = f.debug_struct("RefCell"); match self.try_borrow() { - Ok(borrow) => f.debug_struct("RefCell").field("value", &borrow).finish(), - Err(_) => { - // The RefCell is mutably borrowed so we can't look at its value - // here. Show a placeholder instead. - struct BorrowedPlaceholder; - - impl Debug for BorrowedPlaceholder { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - f.write_str("") - } - } - - f.debug_struct("RefCell").field("value", &BorrowedPlaceholder).finish() - } - } + Ok(borrow) => d.field("value", &borrow), + Err(_) => d.field("value", &format_args!("")), + }; + d.finish() } } diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index 8e9ea293ce4e9..1d0ed4bb45268 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -157,10 +157,12 @@ impl Default for LazyLock { #[unstable(feature = "lazy_cell", issue = "109736")] impl fmt::Debug for LazyLock { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut d = f.debug_tuple("LazyLock"); match self.get() { - Some(v) => f.debug_tuple("LazyLock").field(v).finish(), - None => f.write_str("LazyLock(Uninit)"), - } + Some(v) => d.field(v), + None => d.field(&format_args!("")), + }; + d.finish() } } diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index b8fec6902a08c..b4ae6b7e07ebc 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -490,13 +490,7 @@ impl fmt::Debug for Mutex { d.field("data", &&**err.get_ref()); } Err(TryLockError::WouldBlock) => { - struct LockedPlaceholder; - impl fmt::Debug for LockedPlaceholder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("") - } - } - d.field("data", &LockedPlaceholder); + d.field("data", &format_args!("")); } } d.field("poisoned", &self.poison.get()); diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index 8c34375ea0712..cd8a62d55c5f5 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -366,10 +366,12 @@ impl const Default for OnceLock { #[stable(feature = "once_cell", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for OnceLock { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut d = f.debug_tuple("OnceLock"); match self.get() { - Some(v) => f.debug_tuple("Once").field(v).finish(), - None => f.write_str("Once(Uninit)"), - } + Some(v) => d.field(v), + None => d.field(&format_args!("")), + }; + d.finish() } } diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 7c409cb3e9776..26aaa2414c979 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -485,13 +485,7 @@ impl fmt::Debug for RwLock { d.field("data", &&**err.get_ref()); } Err(TryLockError::WouldBlock) => { - struct LockedPlaceholder; - impl fmt::Debug for LockedPlaceholder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("") - } - } - d.field("data", &LockedPlaceholder); + d.field("data", &format_args!("")); } } d.field("poisoned", &self.poison.get()); From fda3d2abaa325c49a6ff382a624af59c6e75db37 Mon Sep 17 00:00:00 2001 From: Allen Wild Date: Fri, 14 Jul 2023 11:08:57 -0400 Subject: [PATCH 2/7] Re-export core::ffi::FromBytesUntilNulError in std::ffi Like the other CStr and CString error types, make a re-export for std::ffi::FromBytesUntilNulError. This seems to have slipped through the cracks in the cstr_from_bytes_until_nul implementation and core_c_str migration. Tracking Issue: #95027 --- library/std/src/ffi/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs index 3ddb8748753e4..b0484474712fb 100644 --- a/library/std/src/ffi/mod.rs +++ b/library/std/src/ffi/mod.rs @@ -156,6 +156,8 @@ #[stable(feature = "alloc_c_string", since = "1.64.0")] pub use alloc::ffi::{CString, FromVecWithNulError, IntoStringError, NulError}; +#[stable(feature = "cstr_from_bytes_until_nul", since = "CURRENT_RUSTC_VERSION")] +pub use core::ffi::FromBytesUntilNulError; #[stable(feature = "core_c_str", since = "1.64.0")] pub use core::ffi::{CStr, FromBytesWithNulError}; From 50d117ee7d54d1f74a69ae067a8304f6db61ffb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 17 Jul 2023 21:24:43 +0200 Subject: [PATCH 3/7] Resolve correct archive version name in `opt-dist` --- src/tools/opt-dist/src/tests.rs | 25 +++++++++++++++++++------ src/tools/opt-dist/src/utils/io.rs | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/tools/opt-dist/src/tests.rs b/src/tools/opt-dist/src/tests.rs index 6b35b13e58624..c85418baecd1a 100644 --- a/src/tools/opt-dist/src/tests.rs +++ b/src/tools/opt-dist/src/tests.rs @@ -1,8 +1,8 @@ use crate::environment::Environment; use crate::exec::cmd; -use crate::utils::io::{copy_directory, unpack_archive}; +use crate::utils::io::{copy_directory, find_file_in_dir, unpack_archive}; use anyhow::Context; -use camino::Utf8PathBuf; +use camino::{Utf8Path, Utf8PathBuf}; /// Run tests on optimized dist artifacts. pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> { @@ -22,13 +22,14 @@ pub fn run_tests(env: &dyn Environment) -> anyhow::Result<()> { Ok(extracted_path) }; let host_triple = env.host_triple(); + let version = find_dist_version(&dist_dir)?; // Extract rustc, libstd, cargo and src archives to create the optimized sysroot - let rustc_dir = extract_dist_dir(&format!("rustc-nightly-{host_triple}"))?.join("rustc"); - let libstd_dir = extract_dist_dir(&format!("rust-std-nightly-{host_triple}"))? + let rustc_dir = extract_dist_dir(&format!("rustc-{version}-{host_triple}"))?.join("rustc"); + let libstd_dir = extract_dist_dir(&format!("rust-std-{version}-{host_triple}"))? .join(format!("rust-std-{host_triple}")); - let cargo_dir = extract_dist_dir(&format!("cargo-nightly-{host_triple}"))?.join("cargo"); - let extracted_src_dir = extract_dist_dir("rust-src-nightly")?.join("rust-src"); + let cargo_dir = extract_dist_dir(&format!("cargo-{version}-{host_triple}"))?.join("cargo"); + let extracted_src_dir = extract_dist_dir(&format!("rust-src-{version}"))?.join("rust-src"); // We need to manually copy libstd to the extracted rustc sysroot copy_directory( @@ -99,3 +100,15 @@ llvm-config = "{llvm_config}" } cmd(&args).env("COMPILETEST_FORCE_STAGE0", "1").run().context("Cannot execute tests") } + +/// Tries to find the version of the dist artifacts (either nightly, beta, or 1.XY.Z). +fn find_dist_version(directory: &Utf8Path) -> anyhow::Result { + // Lookup a known file with a unique prefix and extract the version from its filename + let archive = find_file_in_dir(directory, "reproducible-artifacts-", ".tar.xz")? + .file_name() + .unwrap() + .to_string(); + let (version, _) = + archive.strip_prefix("reproducible-artifacts-").unwrap().split_once("-").unwrap(); + Ok(version.to_string()) +} diff --git a/src/tools/opt-dist/src/utils/io.rs b/src/tools/opt-dist/src/utils/io.rs index aab078067afca..211f867ac003b 100644 --- a/src/tools/opt-dist/src/utils/io.rs +++ b/src/tools/opt-dist/src/utils/io.rs @@ -60,3 +60,22 @@ pub fn get_files_from_dir( .map(|p| p.map(|p| Utf8PathBuf::from_path_buf(p).unwrap())) .collect::, _>>()?) } + +/// Finds a single file in the specified `directory` with the given `prefix` and `suffix`. +pub fn find_file_in_dir( + directory: &Utf8Path, + prefix: &str, + suffix: &str, +) -> anyhow::Result { + let files = glob::glob(&format!("{directory}/{prefix}*{suffix}"))? + .into_iter() + .collect::, _>>()?; + match files.len() { + 0 => Err(anyhow::anyhow!("No file with prefix {prefix} found in {directory}")), + 1 => Ok(Utf8PathBuf::from_path_buf(files[0].clone()).unwrap()), + _ => Err(anyhow::anyhow!( + "More than one file with prefix {prefix} found in {directory}: {:?}", + files + )), + } +} From 63845e78e18a906e8920b0f823001ee7218e118f Mon Sep 17 00:00:00 2001 From: Oleksandr Babak Date: Fri, 28 Jul 2023 20:15:12 +0200 Subject: [PATCH 4/7] clean up after 113312 --- tests/ui/auto-traits/issue-83857-ub.rs | 2 ++ tests/ui/auto-traits/issue-83857-ub.stderr | 4 ++-- tests/ui/impl-trait/auto-trait-leak | 0 3 files changed, 4 insertions(+), 2 deletions(-) delete mode 100644 tests/ui/impl-trait/auto-trait-leak diff --git a/tests/ui/auto-traits/issue-83857-ub.rs b/tests/ui/auto-traits/issue-83857-ub.rs index 0a8865295c63f..626e60c37f63f 100644 --- a/tests/ui/auto-traits/issue-83857-ub.rs +++ b/tests/ui/auto-traits/issue-83857-ub.rs @@ -1,4 +1,6 @@ #![allow(suspicious_auto_trait_impls)] +// Tests that we don't incorrectly allow overlap between a builtin auto trait +// impl and a user written one. See #83857 for more details struct Always(T, U); unsafe impl Send for Always {} diff --git a/tests/ui/auto-traits/issue-83857-ub.stderr b/tests/ui/auto-traits/issue-83857-ub.stderr index d2aef17e7f8d2..23a2f62d9057f 100644 --- a/tests/ui/auto-traits/issue-83857-ub.stderr +++ b/tests/ui/auto-traits/issue-83857-ub.stderr @@ -1,12 +1,12 @@ error[E0277]: `Foo` cannot be sent between threads safely - --> $DIR/issue-83857-ub.rs:20:38 + --> $DIR/issue-83857-ub.rs:22:38 | LL | fn generic(v: Foo, f: fn( as WithAssoc>::Output) -> i32) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be sent between threads safely | = help: the trait `Send` is not implemented for `Foo` note: required for `Foo` to implement `WithAssoc` - --> $DIR/issue-83857-ub.rs:13:15 + --> $DIR/issue-83857-ub.rs:15:15 | LL | impl WithAssoc for T { | ---- ^^^^^^^^^ ^ diff --git a/tests/ui/impl-trait/auto-trait-leak b/tests/ui/impl-trait/auto-trait-leak deleted file mode 100644 index e69de29bb2d1d..0000000000000 From bca79a26d80147e3bcf87d6d5e95ff4a303d7eda Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Sat, 29 Jul 2023 08:47:21 +0800 Subject: [PATCH 5/7] Update lexer emoji diagnostics to Unicode 15.0 --- Cargo.lock | 49 +++------------------ compiler/rustc_lexer/Cargo.toml | 6 ++- compiler/rustc_lexer/src/lib.rs | 11 ++--- src/tools/tidy/src/deps.rs | 6 +-- tests/ui/lexer/lex-emoji-identifiers.rs | 6 +-- tests/ui/lexer/lex-emoji-identifiers.stderr | 34 +++++++------- 6 files changed, 36 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45959c039e7ea..56390d1fb4fad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3785,7 +3785,7 @@ name = "rustc_lexer" version = "0.1.0" dependencies = [ "expect-test", - "unic-emoji-char", + "unicode-properties", "unicode-xid", ] @@ -5445,38 +5445,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-emoji-char" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b07221e68897210270a38bde4babb655869637af0f69407f96053a34f76494d" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - [[package]] name = "unic-langid" version = "0.9.1" @@ -5520,15 +5488,6 @@ dependencies = [ "unic-langid-impl", ] -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] - [[package]] name = "unicase" version = "2.6.0" @@ -5566,6 +5525,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0" + [[package]] name = "unicode-script" version = "0.5.5" diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml index 23294dc2e1b6a..2211ac1c8a753 100644 --- a/compiler/rustc_lexer/Cargo.toml +++ b/compiler/rustc_lexer/Cargo.toml @@ -16,7 +16,11 @@ Rust lexer used by rustc. No stability guarantees are provided. # Note that this crate purposefully does not depend on other rustc crates [dependencies] unicode-xid = "0.2.0" -unic-emoji-char = "0.9.0" + +[dependencies.unicode-properties] +version = "0.1.0" +default-features = false +features = ["emoji"] [dev-dependencies] expect-test = "1.4.0" diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index d511d2b1280d9..43dfd34a6ff74 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -34,6 +34,7 @@ pub use crate::cursor::Cursor; use self::LiteralKind::*; use self::TokenKind::*; use crate::cursor::EOF_CHAR; +use unicode_properties::UnicodeEmoji; /// Parsed token. /// It doesn't contain information about data that has been parsed, @@ -428,9 +429,7 @@ impl Cursor<'_> { Literal { kind, suffix_start } } // Identifier starting with an emoji. Only lexed for graceful error recovery. - c if !c.is_ascii() && unic_emoji_char::is_emoji(c) => { - self.fake_ident_or_unknown_prefix() - } + c if !c.is_ascii() && c.is_emoji_char() => self.fake_ident_or_unknown_prefix(), _ => Unknown, }; let res = Token::new(token_kind, self.pos_within_token()); @@ -514,9 +513,7 @@ impl Cursor<'_> { // we see a prefix here, it is definitely an unknown prefix. match self.first() { '#' | '"' | '\'' => UnknownPrefix, - c if !c.is_ascii() && unic_emoji_char::is_emoji(c) => { - self.fake_ident_or_unknown_prefix() - } + c if !c.is_ascii() && c.is_emoji_char() => self.fake_ident_or_unknown_prefix(), _ => Ident, } } @@ -525,7 +522,7 @@ impl Cursor<'_> { // Start is already eaten, eat the rest of identifier. self.eat_while(|c| { unicode_xid::UnicodeXID::is_xid_continue(c) - || (!c.is_ascii() && unic_emoji_char::is_emoji(c)) + || (!c.is_ascii() && c.is_emoji_char()) || c == '\u{200d}' }); // Known prefixes must have been handled earlier. So if diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 57cbfe68be46c..a015c36d7ebb1 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -270,18 +270,14 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "twox-hash", "type-map", "typenum", - "unic-char-property", - "unic-char-range", - "unic-common", - "unic-emoji-char", "unic-langid", "unic-langid-impl", "unic-langid-macros", "unic-langid-macros-impl", - "unic-ucd-version", "unicase", "unicode-ident", "unicode-normalization", + "unicode-properties", "unicode-script", "unicode-security", "unicode-width", diff --git a/tests/ui/lexer/lex-emoji-identifiers.rs b/tests/ui/lexer/lex-emoji-identifiers.rs index 91b5929c0fea6..decf2f0058721 100644 --- a/tests/ui/lexer/lex-emoji-identifiers.rs +++ b/tests/ui/lexer/lex-emoji-identifiers.rs @@ -1,9 +1,7 @@ fn invalid_emoji_usages() { let arrow↔️ = "basic emoji"; //~ ERROR: identifiers cannot contain emoji - // FIXME - let planet🪐 = "basic emoji"; //~ ERROR: unknown start of token - // FIXME - let wireless🛜 = "basic emoji"; //~ ERROR: unknown start of token + let planet🪐 = "basic emoji"; //~ ERROR: identifiers cannot contain emoji + let wireless🛜 = "basic emoji"; //~ ERROR: identifiers cannot contain emoji // FIXME let key1️⃣ = "keycap sequence"; //~ ERROR: unknown start of token //~^ WARN: identifier contains uncommon Unicode codepoints diff --git a/tests/ui/lexer/lex-emoji-identifiers.stderr b/tests/ui/lexer/lex-emoji-identifiers.stderr index 6237c5d0236d2..747825fa2a988 100644 --- a/tests/ui/lexer/lex-emoji-identifiers.stderr +++ b/tests/ui/lexer/lex-emoji-identifiers.stderr @@ -1,17 +1,5 @@ -error: unknown start of token: \u{1fa90} - --> $DIR/lex-emoji-identifiers.rs:4:15 - | -LL | let planet🪐 = "basic emoji"; - | ^^ - -error: unknown start of token: \u{1f6dc} - --> $DIR/lex-emoji-identifiers.rs:6:17 - | -LL | let wireless🛜 = "basic emoji"; - | ^^ - error: unknown start of token: \u{20e3} - --> $DIR/lex-emoji-identifiers.rs:8:14 + --> $DIR/lex-emoji-identifiers.rs:6:14 | LL | let key1️⃣ = "keycap sequence"; | ^ @@ -22,26 +10,38 @@ error: identifiers cannot contain emoji: `arrow↔️` LL | let arrow↔️ = "basic emoji"; | ^^^^^^ +error: identifiers cannot contain emoji: `planet🪐` + --> $DIR/lex-emoji-identifiers.rs:3:9 + | +LL | let planet🪐 = "basic emoji"; + | ^^^^^^^^ + +error: identifiers cannot contain emoji: `wireless🛜` + --> $DIR/lex-emoji-identifiers.rs:4:9 + | +LL | let wireless🛜 = "basic emoji"; + | ^^^^^^^^^^ + error: identifiers cannot contain emoji: `flag🇺🇳` - --> $DIR/lex-emoji-identifiers.rs:10:9 + --> $DIR/lex-emoji-identifiers.rs:8:9 | LL | let flag🇺🇳 = "flag sequence"; | ^^^^^^ error: identifiers cannot contain emoji: `wales🏴` - --> $DIR/lex-emoji-identifiers.rs:11:9 + --> $DIR/lex-emoji-identifiers.rs:9:9 | LL | let wales🏴 = "tag sequence"; | ^^^^^^^ error: identifiers cannot contain emoji: `folded🙏🏿` - --> $DIR/lex-emoji-identifiers.rs:12:9 + --> $DIR/lex-emoji-identifiers.rs:10:9 | LL | let folded🙏🏿 = "modifier sequence"; | ^^^^^^^^^^ warning: identifier contains uncommon Unicode codepoints - --> $DIR/lex-emoji-identifiers.rs:8:9 + --> $DIR/lex-emoji-identifiers.rs:6:9 | LL | let key1️⃣ = "keycap sequence"; | ^^^^ From 752e6e13adacd499049985ad9c5f7f4d08b78261 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 29 Jul 2023 01:04:04 +0000 Subject: [PATCH 6/7] Detect trait upcasting through struct tail unsizing --- .../src/solve/eval_ctxt/select.rs | 25 +++++++++++++++---- .../upcast-through-struct-tail.current.stderr | 13 ++++++++++ .../upcast-through-struct-tail.next.stderr | 13 ++++++++++ .../upcast-through-struct-tail.rs | 14 +++++++++++ 4 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr create mode 100644 tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr create mode 100644 tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 6045001510e42..69af33e874b4d 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -100,10 +100,18 @@ impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { rematch_impl(self, goal, def_id, nested_obligations) } + // If an unsize goal is ambiguous, then we can manually rematch it to make + // selection progress for coercion during HIR typeck. If it is *not* ambiguous, + // but is `BuiltinImplSource::Misc`, it may have nested `Unsize` goals, + // and we need to rematch those to detect tuple unsizing and trait upcasting. + // FIXME: This will be wrong if we have param-env or where-clause bounds + // with the unsize goal -- we may need to mark those with different impl + // sources. (Certainty::Maybe(_), CandidateSource::BuiltinImpl(src)) + | (Certainty::Yes, CandidateSource::BuiltinImpl(src @ BuiltinImplSource::Misc)) if self.tcx.lang_items().unsize_trait() == Some(goal.predicate.def_id()) => { - rematch_unsize(self, goal, nested_obligations, src) + rematch_unsize(self, goal, nested_obligations, src, certainty) } // Technically some builtin impls have nested obligations, but if @@ -217,6 +225,7 @@ fn rematch_unsize<'tcx>( goal: Goal<'tcx, ty::TraitPredicate<'tcx>>, mut nested: Vec>, source: BuiltinImplSource, + certainty: Certainty, ) -> SelectionResult<'tcx, Selection<'tcx>> { let tcx = infcx.tcx; let a_ty = structurally_normalize(goal.predicate.self_ty(), infcx, goal.param_env, &mut nested); @@ -227,6 +236,12 @@ fn rematch_unsize<'tcx>( &mut nested, ); match (a_ty.kind(), b_ty.kind()) { + // Stall any ambiguous upcasting goals, since we can't rematch those + (ty::Dynamic(_, _, ty::Dyn), ty::Dynamic(_, _, ty::Dyn)) => match certainty { + Certainty::Yes => Ok(Some(ImplSource::Builtin(source, nested))), + _ => Ok(None), + }, + // `T` -> `dyn Trait` upcasting (_, &ty::Dynamic(data, region, ty::Dyn)) => { // Check that the type implements all of the predicates of the def-id. // (i.e. the principal, all of the associated types match, and any auto traits) @@ -354,10 +369,10 @@ fn rematch_unsize<'tcx>( ); Ok(Some(ImplSource::Builtin(source, nested))) } - // FIXME: We *could* ICE here if either: - // 1. the certainty is `Certainty::Yes`, - // 2. we're in codegen (which should mean `Certainty::Yes`). - _ => Ok(None), + _ => { + assert_ne!(certainty, Certainty::Yes); + Ok(None) + } } } diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr new file mode 100644 index 0000000000000..9f0993d65a710 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr @@ -0,0 +1,13 @@ +error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental + --> $DIR/upcast-through-struct-tail.rs:10:5 + | +LL | x + | ^ + | + = note: see issue #65991 for more information + = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable + = note: required when coercing `Box>` into `Box>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr new file mode 100644 index 0000000000000..9f0993d65a710 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr @@ -0,0 +1,13 @@ +error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental + --> $DIR/upcast-through-struct-tail.rs:10:5 + | +LL | x + | ^ + | + = note: see issue #65991 for more information + = help: add `#![feature(trait_upcasting)]` to the crate attributes to enable + = note: required when coercing `Box>` into `Box>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs new file mode 100644 index 0000000000000..42495f45f8a65 --- /dev/null +++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs @@ -0,0 +1,14 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next + +struct Wrapper(T); + +trait A: B {} +trait B {} + +fn test<'a>(x: Box>) -> Box> { + x + //~^ ERROR cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental +} + +fn main() {} From 2a3da87c0e5ab8faf8d360f13f8e057072876dd6 Mon Sep 17 00:00:00 2001 From: ouz-a Date: Fri, 28 Jul 2023 12:31:59 +0300 Subject: [PATCH 7/7] add missing rvalues to smir --- compiler/rustc_smir/src/rustc_smir/mod.rs | 51 +++++++++++++++++-- .../rustc_smir/src/stable_mir/mir/body.rs | 39 +++++++++++++- compiler/rustc_smir/src/stable_mir/ty.rs | 2 +- 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 0a33030c6035e..847ec4ffe9c4f 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -132,7 +132,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { use mir::Rvalue::*; match self { Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)), - Repeat(_, _) => todo!(), + Repeat(op, len) => stable_mir::mir::Rvalue::Repeat(op.stable(tables), opaque(len)), Ref(region, kind, place) => stable_mir::mir::Rvalue::Ref( opaque(region), kind.stable(tables), @@ -145,7 +145,11 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables)) } Len(place) => stable_mir::mir::Rvalue::Len(place.stable(tables)), - Cast(_, _, _) => todo!(), + Cast(cast_kind, op, ty) => stable_mir::mir::Rvalue::Cast( + cast_kind.stable(tables), + op.stable(tables), + tables.intern_ty(*ty), + ), BinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::BinaryOp( bin_op.stable(tables), ops.0.stable(tables), @@ -163,8 +167,13 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { stable_mir::mir::Rvalue::UnaryOp(un_op.stable(tables), op.stable(tables)) } Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable(tables)), - Aggregate(_, _) => todo!(), - ShallowInitBox(_, _) => todo!(), + Aggregate(agg_kind, operands) => { + let operands = operands.iter().map(|op| op.stable(tables)).collect(); + stable_mir::mir::Rvalue::Aggregate(agg_kind.stable(tables), operands) + } + ShallowInitBox(op, ty) => { + stable_mir::mir::Rvalue::ShallowInitBox(op.stable(tables), tables.intern_ty(*ty)) + } CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable(tables)), } } @@ -478,6 +487,40 @@ impl<'tcx> Stable<'tcx> for mir::UnOp { } } +impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { + type T = stable_mir::mir::AggregateKind; + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { + match self { + mir::AggregateKind::Array(ty) => { + stable_mir::mir::AggregateKind::Array(tables.intern_ty(*ty)) + } + mir::AggregateKind::Tuple => stable_mir::mir::AggregateKind::Tuple, + mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => { + stable_mir::mir::AggregateKind::Adt( + rustc_internal::adt_def(*def_id), + var_idx.index(), + generic_arg.stable(tables), + user_ty_index.map(|idx| idx.index()), + field_idx.map(|idx| idx.index()), + ) + } + mir::AggregateKind::Closure(def_id, generic_arg) => { + stable_mir::mir::AggregateKind::Closure( + rustc_internal::closure_def(*def_id), + generic_arg.stable(tables), + ) + } + mir::AggregateKind::Generator(def_id, generic_arg, movability) => { + stable_mir::mir::AggregateKind::Generator( + rustc_internal::generator_def(*def_id), + generic_arg.stable(tables), + movability.stable(tables), + ) + } + } + } +} + impl<'tcx> Stable<'tcx> for rustc_hir::GeneratorKind { type T = stable_mir::mir::GeneratorKind; fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index 1b1871bcd2a75..e08359067dfc3 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -1,4 +1,6 @@ -use crate::stable_mir::ty::Region; +use crate::stable_mir::ty::{ + AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region, +}; use crate::stable_mir::{self, ty::Ty}; #[derive(Clone, Debug)] @@ -137,7 +139,6 @@ pub enum Statement { Nop, } -// FIXME this is incomplete #[derive(Clone, Debug)] pub enum Rvalue { /// Creates a pointer with the indicated mutability to the place. @@ -146,6 +147,16 @@ pub enum Rvalue { /// `&raw v` or `addr_of!(v)`. AddressOf(Mutability, Place), + /// Creates an aggregate value, like a tuple or struct. + /// + /// This is needed because dataflow analysis needs to distinguish + /// `dest = Foo { x: ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case that `Foo` + /// has a destructor. + /// + /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Generator`. After + /// generator lowering, `Generator` aggregate kinds are disallowed too. + Aggregate(AggregateKind, Vec), + /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second /// parameter may be a `usize` as well. /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats, @@ -198,6 +209,16 @@ pub enum Rvalue { /// Creates a reference to the place. Ref(Region, BorrowKind, Place), + /// Creates an array where each element is the value of the operand. + /// + /// This is the cause of a bug in the case where the repetition count is zero because the value + /// is not dropped, see [#74836]. + /// + /// Corresponds to source code like `[x; 32]`. + /// + /// [#74836]: https://github.com/rust-lang/rust/issues/74836 + Repeat(Operand, Const), + /// Transmutes a `*mut u8` into shallow-initialized `Box`. /// /// This is different from a normal transmute because dataflow analysis will treat the box as @@ -232,6 +253,15 @@ pub enum Rvalue { Use(Operand), } +#[derive(Clone, Debug)] +pub enum AggregateKind { + Array(Ty), + Tuple, + Adt(AdtDef, VariantIdx, GenericArgs, Option, Option), + Closure(ClosureDef, GenericArgs), + Generator(GeneratorDef, GenericArgs, Movability), +} + #[derive(Clone, Debug)] pub enum Operand { Copy(Place), @@ -247,6 +277,11 @@ pub struct Place { type FieldIdx = usize; +/// The source-order index of a variant in a type. +type VariantIdx = usize; + +type UserTypeAnnotationIndex = usize; + #[derive(Clone, Debug)] pub struct SwitchTarget { pub value: u128, diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 7a72afd666cf1..025225b8d19f1 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -10,7 +10,7 @@ impl Ty { } } -type Const = Opaque; +pub(crate) type Const = Opaque; pub(crate) type Region = Opaque; type Span = Opaque;