From cbe428d8cb60f901cae2c99a5aff0f563b142681 Mon Sep 17 00:00:00 2001 From: Thom Chiovoloni Date: Thu, 18 Aug 2022 20:23:01 -0700 Subject: [PATCH 01/10] use `confstr(_CS_DARWIN_USER_TEMP_DIR, ...)` as a `TMPDIR` fallback on darwin --- library/std/src/env.rs | 15 ++++- library/std/src/sys/pal/unix/os.rs | 76 ++++++++++++++++++++++-- library/std/src/sys/pal/unix/os/tests.rs | 25 ++++++++ 3 files changed, 109 insertions(+), 7 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 97a1b846a91a4..5a2deada6c355 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -653,19 +653,28 @@ pub fn home_dir() -> Option { /// may result in "insecure temporary file" security vulnerabilities. Consider /// using a crate that securely creates temporary files or directories. /// +/// Note that the returned value may be a symbolic link, not a directory. +/// /// # Platform-specific behavior /// /// On Unix, returns the value of the `TMPDIR` environment variable if it is -/// set, otherwise for non-Android it returns `/tmp`. On Android, since there -/// is no global temporary folder (it is usually allocated per-app), it returns -/// `/data/local/tmp`. +/// set, otherwise the value is OS-specific: +/// - On Android, there is no global temporary folder (it is usually allocated +/// per-app), it returns `/data/local/tmp`. +/// - On Darwin-based OSes (macOS, iOS, etc) it returns the directory provided +/// by `confstr(_CS_DARWIN_USER_TEMP_DIR, ...)`, as recommended by [Apple's +/// security guidelines][appledoc]. +/// - On all other unix-based OSes, it returns `/tmp`. +/// /// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] / /// [`GetTempPath`][GetTempPath], which this function uses internally. +/// /// Note that, this [may change in the future][changes]. /// /// [changes]: io#platform-specific-behavior /// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a /// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha +/// [appledoc]: https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10 /// /// ```no_run /// use std::env; diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index f983d174ed61c..7db037d02eba0 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -698,12 +698,80 @@ pub fn page_size() -> usize { unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } } +// Returns the value for [`confstr(key, ...)`][posix_confstr]. Currently only +// used on Darwin, but should work on any unix (in case we need to get +// `_CS_PATH` or `_CS_V[67]_ENV` in the future). +// +// [posix_confstr]: +// https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] +fn confstr(key: c_int, size_hint: Option) -> io::Result { + let mut buf: Vec = Vec::new(); + let mut bytes_needed_including_nul = size_hint + .unwrap_or_else(|| { + // Treat "None" as "do an extra call to get the length". In theory + // we could move this into the loop below, but it's hard to do given + // that it isn't 100% clear if it's legal to pass 0 for `len` when + // the buffer isn't null. + unsafe { libc::confstr(key, core::ptr::null_mut(), 0) } + }) + .max(1); + // If the value returned by `confstr` is greater than the len passed into + // it, then the value was truncated, meaning we need to retry. Note that + // while `confstr` results don't seem to change for a process, it's unclear + // if this is guaranteed anywhere, so looping does seem required. + while bytes_needed_including_nul > buf.capacity() { + // We write into the spare capacity of `buf`. This lets us avoid + // changing buf's `len`, which both simplifies `reserve` computation, + // allows working with `Vec` instead of `Vec>`, and + // may avoid a copy, since the Vec knows that none of the bytes are needed + // when reallocating (well, in theory anyway). + buf.reserve(bytes_needed_including_nul); + // `confstr` returns + // - 0 in the case of errors: we break and return an error. + // - The number of bytes written, iff the provided buffer is enough to + // hold the entire value: we break and return the data in `buf`. + // - Otherwise, the number of bytes needed (including nul): we go + // through the loop again. + bytes_needed_including_nul = + unsafe { libc::confstr(key, buf.as_mut_ptr().cast::(), buf.capacity()) }; + } + // `confstr` returns 0 in the case of an error. + if bytes_needed_including_nul == 0 { + return Err(io::Error::last_os_error()); + } + // Safety: `confstr(..., buf.as_mut_ptr(), buf.capacity())` returned a + // non-zero value, meaning `bytes_needed_including_nul` bytes were + // initialized. + unsafe { + buf.set_len(bytes_needed_including_nul); + // Remove the NUL-terminator. + let last_byte = buf.pop(); + // ... and smoke-check that it *was* a NUL-terminator. + assert_eq!(last_byte, Some(0), "`confstr` provided a string which wasn't nul-terminated"); + }; + Ok(OsString::from_vec(buf)) +} + +#[cfg(target_vendor = "apple")] +fn darwin_temp_dir() -> PathBuf { + confstr(libc::_CS_DARWIN_USER_TEMP_DIR, Some(64)).map(PathBuf::from).unwrap_or_else(|_| { + // It failed for whatever reason (there are several possible reasons), + // so return the global one. + PathBuf::from("/tmp") + }) +} + pub fn temp_dir() -> PathBuf { crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { - if cfg!(target_os = "android") { - PathBuf::from("/data/local/tmp") - } else { - PathBuf::from("/tmp") + cfg_if::cfg_if! { + if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] { + darwin_temp_dir() + } else if #[cfg(target_os = "android")] { + PathBuf::from("/data/local/tmp") + } else { + PathBuf::from("/tmp") + } } }) } diff --git a/library/std/src/sys/pal/unix/os/tests.rs b/library/std/src/sys/pal/unix/os/tests.rs index efc29955b05fe..ab9742fc677e9 100644 --- a/library/std/src/sys/pal/unix/os/tests.rs +++ b/library/std/src/sys/pal/unix/os/tests.rs @@ -21,3 +21,28 @@ fn test_parse_glibc_version() { assert_eq!(parsed, super::parse_glibc_version(version_str)); } } + +// Smoke check `confstr`, do it for several hint values, to ensure our resizing +// logic is correct. +#[test] +#[cfg(target_os = "macos")] +fn test_confstr() { + for key in [libc::_CS_DARWIN_USER_TEMP_DIR, libc::_CS_PATH] { + let value_nohint = super::confstr(key, None).unwrap_or_else(|e| { + panic!("confstr({key}, None) failed: {e:?}"); + }); + let end = (value_nohint.len() + 1) * 2; + for hint in 0..end { + assert_eq!( + super::confstr(key, Some(hint)).as_deref().ok(), + Some(&*value_nohint), + "confstr({key}, Some({hint})) failed", + ); + } + } + // Smoke check that we don't loop forever or something if the input was not valid. + for hint in [None, Some(0), Some(1)] { + let hopefully_invalid = 123456789_i32; + assert!(super::confstr(hopefully_invalid, hint).is_err()); + } +} From 6d075dc4d7335a239f887b28a630bdc9aa08e140 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 18:41:55 +0200 Subject: [PATCH 02/10] Prefer `target_vendor = "apple"` on confstr --- library/std/src/sys/pal/unix/os.rs | 4 ++-- library/std/src/sys/pal/unix/os/tests.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 7db037d02eba0..9750c32eed5e5 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -704,7 +704,7 @@ pub fn page_size() -> usize { // // [posix_confstr]: // https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html -#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] +#[cfg(target_vendor = "apple")] fn confstr(key: c_int, size_hint: Option) -> io::Result { let mut buf: Vec = Vec::new(); let mut bytes_needed_including_nul = size_hint @@ -765,7 +765,7 @@ fn darwin_temp_dir() -> PathBuf { pub fn temp_dir() -> PathBuf { crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { cfg_if::cfg_if! { - if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] { + if #[cfg(target_vendor = "apple")] { darwin_temp_dir() } else if #[cfg(target_os = "android")] { PathBuf::from("/data/local/tmp") diff --git a/library/std/src/sys/pal/unix/os/tests.rs b/library/std/src/sys/pal/unix/os/tests.rs index ab9742fc677e9..a84086037ce0b 100644 --- a/library/std/src/sys/pal/unix/os/tests.rs +++ b/library/std/src/sys/pal/unix/os/tests.rs @@ -25,7 +25,7 @@ fn test_parse_glibc_version() { // Smoke check `confstr`, do it for several hint values, to ensure our resizing // logic is correct. #[test] -#[cfg(target_os = "macos")] +#[cfg(target_vendor = "apple")] fn test_confstr() { for key in [libc::_CS_DARWIN_USER_TEMP_DIR, libc::_CS_PATH] { let value_nohint = super::confstr(key, None).unwrap_or_else(|e| { From b62ee10e5448a077e67e46f6907a4a04415895a8 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 18:57:44 +0200 Subject: [PATCH 03/10] Use with_capacity(0) because we're reading the capacity later on --- library/std/src/sys/pal/unix/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index 9750c32eed5e5..d26a1bdef74b4 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -706,7 +706,7 @@ pub fn page_size() -> usize { // https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html #[cfg(target_vendor = "apple")] fn confstr(key: c_int, size_hint: Option) -> io::Result { - let mut buf: Vec = Vec::new(); + let mut buf: Vec = Vec::with_capacity(0); let mut bytes_needed_including_nul = size_hint .unwrap_or_else(|| { // Treat "None" as "do an extra call to get the length". In theory From 204b2281fa508cf512d343cb1631955a5dfa9e0e Mon Sep 17 00:00:00 2001 From: Daniel Bertalan Date: Mon, 8 Jul 2024 15:49:50 +0200 Subject: [PATCH 04/10] Allow disabling ASan instrumentation for globals AddressSanitizer adds instrumentation to global variables unless the [`no_sanitize_address`](https://llvm.org/docs/LangRef.html#global-attributes) attribute is set on them. This commit extends the existing `#[no_sanitize(address)]` attribute to set this; previously it only had the desired effect on functions. --- compiler/rustc_codegen_llvm/src/base.rs | 9 +++ compiler/rustc_codegen_llvm/src/consts.rs | 2 + compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 3 + .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 19 ++++++ compiler/rustc_passes/messages.ftl | 4 ++ compiler/rustc_passes/src/check_attr.rs | 37 +++++++++++- compiler/rustc_passes/src/errors.rs | 11 ++++ tests/codegen/sanitizer/no-sanitize.rs | 10 ++++ tests/ui/attributes/no-sanitize.rs | 18 ++++-- tests/ui/attributes/no-sanitize.stderr | 58 +++++++++++-------- 10 files changed, 137 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 3279389479499..f62310bd94808 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -172,3 +172,12 @@ pub(crate) fn visibility_to_llvm(linkage: Visibility) -> llvm::Visibility { Visibility::Protected => llvm::Visibility::Protected, } } + +pub(crate) fn set_variable_sanitizer_attrs(llval: &Value, attrs: &CodegenFnAttrs) { + if attrs.no_sanitize.contains(SanitizerSet::ADDRESS) { + unsafe { llvm::LLVMRustSetNoSanitizeAddress(llval) }; + } + if attrs.no_sanitize.contains(SanitizerSet::HWADDRESS) { + unsafe { llvm::LLVMRustSetNoSanitizeHWAddress(llval) }; + } +} diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 21d996ef460c0..ce9f8a2a9ea98 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -476,6 +476,8 @@ impl<'ll> CodegenCx<'ll, '_> { base::set_link_section(g, attrs); } + base::set_variable_sanitizer_attrs(g, attrs); + if attrs.flags.contains(CodegenFnAttrFlags::USED) { // `USED` and `USED_LINKER` can't be used together. assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 5fad7583e1aee..2679d8ba9fe8c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2474,4 +2474,7 @@ unsafe extern "C" { pub fn LLVMRustIs64BitSymbolicFile(buf_ptr: *const u8, buf_len: usize) -> bool; pub fn LLVMRustIsECObject(buf_ptr: *const u8, buf_len: usize) -> bool; + + pub fn LLVMRustSetNoSanitizeAddress(Global: &Value); + pub fn LLVMRustSetNoSanitizeHWAddress(Global: &Value); } diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 645b4082be5de..b474a7547dc38 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1999,6 +1999,25 @@ extern "C" bool LLVMRustLLVMHasZstdCompressionForDebugSymbols() { return llvm::compression::zstd::isAvailable(); } +extern "C" void LLVMRustSetNoSanitizeAddress(LLVMValueRef Global) { + GlobalValue &GV = *unwrap(Global); + GlobalValue::SanitizerMetadata MD; + if (GV.hasSanitizerMetadata()) + MD = GV.getSanitizerMetadata(); + MD.NoAddress = true; + MD.IsDynInit = false; + GV.setSanitizerMetadata(MD); +} + +extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) { + GlobalValue &GV = *unwrap(Global); + GlobalValue::SanitizerMetadata MD; + if (GV.hasSanitizerMetadata()) + MD = GV.getSanitizerMetadata(); + MD.NoHWAddress = true; + GV.setSanitizerMetadata(MD); +} + // Operations on composite constants. // These are clones of LLVM api functions that will become available in future // releases. They can be removed once Rust's minimum supported LLVM version diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index e5e70ba203384..8cd82e6a372cb 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -555,6 +555,10 @@ passes_no_mangle_foreign = passes_no_patterns = patterns not allowed in naked function parameters +passes_no_sanitize = + `#[no_sanitize({$attr_str})]` should be applied to {$accepted_kind} + .label = not {$accepted_kind} + passes_non_exported_macro_invalid_attrs = attribute should be applied to function or closure .label = not a function or closure diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0a2926c040447..5edba2cf14742 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -126,9 +126,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::inline, ..] => self.check_inline(hir_id, attr, span, target), [sym::coverage, ..] => self.check_coverage(attr, span, target), [sym::optimize, ..] => self.check_optimize(hir_id, attr, span, target), - [sym::no_sanitize, ..] => { - self.check_applied_to_fn_or_method(hir_id, attr, span, target) - } + [sym::no_sanitize, ..] => self.check_no_sanitize(attr, span, target), [sym::non_exhaustive, ..] => self.check_non_exhaustive(hir_id, attr, span, target), [sym::marker, ..] => self.check_marker(hir_id, attr, span, target), [sym::target_feature, ..] => { @@ -450,6 +448,39 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } + fn check_no_sanitize(&self, attr: &Attribute, span: Span, target: Target) { + if let Some(list) = attr.meta_item_list() { + for item in list.iter() { + let sym = item.name_or_empty(); + match sym { + sym::address | sym::hwaddress => { + let is_valid = + matches!(target, Target::Fn | Target::Method(..) | Target::Static); + if !is_valid { + self.dcx().emit_err(errors::NoSanitize { + attr_span: item.span(), + defn_span: span, + accepted_kind: "a function or static", + attr_str: sym.as_str(), + }); + } + } + _ => { + let is_valid = matches!(target, Target::Fn | Target::Method(..)); + if !is_valid { + self.dcx().emit_err(errors::NoSanitize { + attr_span: item.span(), + defn_span: span, + accepted_kind: "a function", + attr_str: sym.as_str(), + }); + } + } + } + } + } + } + fn check_generic_attr( &self, hir_id: HirId, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 8bd767c1243d9..4425155787022 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1848,3 +1848,14 @@ pub(crate) struct AttrCrateLevelOnlySugg { #[primary_span] pub attr: Span, } + +#[derive(Diagnostic)] +#[diag(passes_no_sanitize)] +pub(crate) struct NoSanitize<'a> { + #[primary_span] + pub attr_span: Span, + #[label] + pub defn_span: Span, + pub accepted_kind: &'a str, + pub attr_str: &'a str, +} diff --git a/tests/codegen/sanitizer/no-sanitize.rs b/tests/codegen/sanitizer/no-sanitize.rs index 47d3fd83f1127..2a309f6b9c696 100644 --- a/tests/codegen/sanitizer/no-sanitize.rs +++ b/tests/codegen/sanitizer/no-sanitize.rs @@ -7,6 +7,16 @@ #![crate_type = "lib"] #![feature(no_sanitize)] +// CHECK: @UNSANITIZED = constant{{.*}} no_sanitize_address +// CHECK-NOT: @__asan_global_UNSANITIZED +#[no_mangle] +#[no_sanitize(address)] +pub static UNSANITIZED: u32 = 0; + +// CHECK: @__asan_global_SANITIZED +#[no_mangle] +pub static SANITIZED: u32 = 0; + // CHECK-LABEL: ; no_sanitize::unsanitized // CHECK-NEXT: ; Function Attrs: // CHECK-NOT: sanitize_address diff --git a/tests/ui/attributes/no-sanitize.rs b/tests/ui/attributes/no-sanitize.rs index 82b7a22d5701e..8c79866d5aa31 100644 --- a/tests/ui/attributes/no-sanitize.rs +++ b/tests/ui/attributes/no-sanitize.rs @@ -4,31 +4,37 @@ #![allow(dead_code)] fn invalid() { - #[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition + #[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function { 1 }; } -#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition +#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function type InvalidTy = (); -#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition +#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function mod invalid_module {} fn main() { - let _ = #[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition + let _ = #[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function (|| 1); } -#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition +#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function struct F; -#[no_sanitize(memory)] //~ ERROR attribute should be applied to a function definition +#[no_sanitize(memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function impl F { #[no_sanitize(memory)] fn valid(&self) {} } +#[no_sanitize(address, memory)] //~ ERROR `#[no_sanitize(memory)]` should be applied to a function +static INVALID : i32 = 0; + #[no_sanitize(memory)] fn valid() {} + +#[no_sanitize(address)] +static VALID : i32 = 0; diff --git a/tests/ui/attributes/no-sanitize.stderr b/tests/ui/attributes/no-sanitize.stderr index f742ba0beed18..9b0b76e3f4eba 100644 --- a/tests/ui/attributes/no-sanitize.stderr +++ b/tests/ui/attributes/no-sanitize.stderr @@ -1,55 +1,63 @@ -error: attribute should be applied to a function definition - --> $DIR/no-sanitize.rs:7:5 +error: `#[no_sanitize(memory)]` should be applied to a function + --> $DIR/no-sanitize.rs:7:19 | LL | #[no_sanitize(memory)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ LL | / { LL | | 1 LL | | }; - | |_____- not a function definition + | |_____- not a function -error: attribute should be applied to a function definition - --> $DIR/no-sanitize.rs:13:1 +error: `#[no_sanitize(memory)]` should be applied to a function + --> $DIR/no-sanitize.rs:13:15 | LL | #[no_sanitize(memory)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ LL | type InvalidTy = (); - | -------------------- not a function definition + | -------------------- not a function -error: attribute should be applied to a function definition - --> $DIR/no-sanitize.rs:16:1 +error: `#[no_sanitize(memory)]` should be applied to a function + --> $DIR/no-sanitize.rs:16:15 | LL | #[no_sanitize(memory)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ LL | mod invalid_module {} - | --------------------- not a function definition + | --------------------- not a function -error: attribute should be applied to a function definition - --> $DIR/no-sanitize.rs:20:13 +error: `#[no_sanitize(memory)]` should be applied to a function + --> $DIR/no-sanitize.rs:20:27 | LL | let _ = #[no_sanitize(memory)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ LL | (|| 1); - | ------ not a function definition + | ------ not a function -error: attribute should be applied to a function definition - --> $DIR/no-sanitize.rs:24:1 +error: `#[no_sanitize(memory)]` should be applied to a function + --> $DIR/no-sanitize.rs:24:15 | LL | #[no_sanitize(memory)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ LL | struct F; - | --------- not a function definition + | --------- not a function -error: attribute should be applied to a function definition - --> $DIR/no-sanitize.rs:27:1 +error: `#[no_sanitize(memory)]` should be applied to a function + --> $DIR/no-sanitize.rs:27:15 | LL | #[no_sanitize(memory)] - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^ LL | / impl F { LL | | #[no_sanitize(memory)] LL | | fn valid(&self) {} LL | | } - | |_- not a function definition + | |_- not a function -error: aborting due to 6 previous errors +error: `#[no_sanitize(memory)]` should be applied to a function + --> $DIR/no-sanitize.rs:33:24 + | +LL | #[no_sanitize(address, memory)] + | ^^^^^^ +LL | static INVALID : i32 = 0; + | ------------------------- not a function + +error: aborting due to 7 previous errors From 8522140caafdec5c63308bbe9aa9f5ce5e6b1863 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 12 Nov 2024 14:05:42 +0000 Subject: [PATCH 05/10] Add test for using macro_rules macro as attribute/derive --- ...ro-rules-as-derive-or-attr-issue-132928.rs | 9 ++++ ...ules-as-derive-or-attr-issue-132928.stderr | 52 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.rs create mode 100644 tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr diff --git a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.rs b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.rs new file mode 100644 index 0000000000000..a2e1398c61e66 --- /dev/null +++ b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] + +macro_rules! sample { () => {} } + +#[sample] //~ ERROR cannot find attribute `sample` in this scope +#[derive(sample)] //~ ERROR cannot find derive macro `sample` in this scope + //~| ERROR cannot find derive macro `sample` in this scope + //~| ERROR cannot find derive macro `sample` in this scope +pub struct S {} diff --git a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr new file mode 100644 index 0000000000000..fb7b649d32fa5 --- /dev/null +++ b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr @@ -0,0 +1,52 @@ +error: cannot find derive macro `sample` in this scope + --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10 + | +LL | #[derive(sample)] + | ^^^^^^ consider moving the definition of `sample` before this call + | +note: a macro with the same name exists, but it appears later at here + --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:3:14 + | +LL | macro_rules! sample { () => {} } + | ^^^^^^ + +error: cannot find attribute `sample` in this scope + --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:5:3 + | +LL | #[sample] + | ^^^^^^ consider moving the definition of `sample` before this call + | +note: a macro with the same name exists, but it appears later at here + --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:3:14 + | +LL | macro_rules! sample { () => {} } + | ^^^^^^ + +error: cannot find derive macro `sample` in this scope + --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10 + | +LL | #[derive(sample)] + | ^^^^^^ consider moving the definition of `sample` before this call + | +note: a macro with the same name exists, but it appears later at here + --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:3:14 + | +LL | macro_rules! sample { () => {} } + | ^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: cannot find derive macro `sample` in this scope + --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10 + | +LL | #[derive(sample)] + | ^^^^^^ consider moving the definition of `sample` before this call + | +note: a macro with the same name exists, but it appears later at here + --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:3:14 + | +LL | macro_rules! sample { () => {} } + | ^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + From 5d30436d244d207406ec8e4a2fbeb510555cba20 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 21 Nov 2024 18:40:36 +0800 Subject: [PATCH 06/10] Re-delay a resolve `bug` For the code pattern reported in , ```rs impl Foo { fn fun() { let S { ref Self } = todo!(); } } ``` converted this to a `span_bug` from a `span_delayed_bug` because this specific self-ctor code pattern lacked test coverage. It turns out this can be hit but we just lacked test coverage, so change it back to a `span_delayed_bug` and add a target tested case. --- compiler/rustc_resolve/src/late.rs | 6 +++--- tests/ui/pattern/self-ctor-133272.rs | 21 +++++++++++++++++++++ tests/ui/pattern/self-ctor-133272.stderr | 15 +++++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 tests/ui/pattern/self-ctor-133272.rs create mode 100644 tests/ui/pattern/self-ctor-133272.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 26b345f5941c4..02cb9da6e9ab2 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3940,12 +3940,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } Res::SelfCtor(_) => { // We resolve `Self` in pattern position as an ident sometimes during recovery, - // so delay a bug instead of ICEing. (Note: is this no longer true? We now ICE. If - // this triggers, please convert to a delayed bug and add a test.) - self.r.dcx().span_bug( + // so delay a bug instead of ICEing. + self.r.dcx().span_delayed_bug( ident.span, "unexpected `SelfCtor` in pattern, expected identifier" ); + None } _ => span_bug!( ident.span, diff --git a/tests/ui/pattern/self-ctor-133272.rs b/tests/ui/pattern/self-ctor-133272.rs new file mode 100644 index 0000000000000..ad64d6b88cd91 --- /dev/null +++ b/tests/ui/pattern/self-ctor-133272.rs @@ -0,0 +1,21 @@ +//! Regression test for , where a `ref Self` ctor +//! makes it possible to hit a `delayed_bug` that was converted into a `span_bug` in +//! , and hitting this reveals that we did not have +//! test coverage for this specific code pattern (heh) previously. +//! +//! # References +//! +//! - ICE bug report: . +//! - Previous PR to change `delayed_bug` -> `span_bug`: +//! +#![crate_type = "lib"] + +struct Foo; + +impl Foo { + fn fun() { + let S { ref Self } = todo!(); + //~^ ERROR expected identifier, found keyword `Self` + //~| ERROR cannot find struct, variant or union type `S` in this scope + } +} diff --git a/tests/ui/pattern/self-ctor-133272.stderr b/tests/ui/pattern/self-ctor-133272.stderr new file mode 100644 index 0000000000000..bca55a43d9c08 --- /dev/null +++ b/tests/ui/pattern/self-ctor-133272.stderr @@ -0,0 +1,15 @@ +error: expected identifier, found keyword `Self` + --> $DIR/self-ctor-133272.rs:17:21 + | +LL | let S { ref Self } = todo!(); + | ^^^^ expected identifier, found keyword + +error[E0422]: cannot find struct, variant or union type `S` in this scope + --> $DIR/self-ctor-133272.rs:17:13 + | +LL | let S { ref Self } = todo!(); + | ^ not found in this scope + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0422`. From f98d9dd334b4ff254912533d8b9b3cc4349f6f6a Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 10 Oct 2024 20:45:39 +0200 Subject: [PATCH 07/10] Don't try to use confstr in Miri --- library/std/src/sys/pal/unix/os.rs | 8 +++++--- library/std/src/sys/pal/unix/os/tests.rs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index d26a1bdef74b4..f207131ddf332 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -704,7 +704,9 @@ pub fn page_size() -> usize { // // [posix_confstr]: // https://pubs.opengroup.org/onlinepubs/9699919799/functions/confstr.html -#[cfg(target_vendor = "apple")] +// +// FIXME: Support `confstr` in Miri. +#[cfg(all(target_vendor = "apple", not(miri)))] fn confstr(key: c_int, size_hint: Option) -> io::Result { let mut buf: Vec = Vec::with_capacity(0); let mut bytes_needed_including_nul = size_hint @@ -753,7 +755,7 @@ fn confstr(key: c_int, size_hint: Option) -> io::Result { Ok(OsString::from_vec(buf)) } -#[cfg(target_vendor = "apple")] +#[cfg(all(target_vendor = "apple", not(miri)))] fn darwin_temp_dir() -> PathBuf { confstr(libc::_CS_DARWIN_USER_TEMP_DIR, Some(64)).map(PathBuf::from).unwrap_or_else(|_| { // It failed for whatever reason (there are several possible reasons), @@ -765,7 +767,7 @@ fn darwin_temp_dir() -> PathBuf { pub fn temp_dir() -> PathBuf { crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { cfg_if::cfg_if! { - if #[cfg(target_vendor = "apple")] { + if #[cfg(all(target_vendor = "apple", not(miri)))] { darwin_temp_dir() } else if #[cfg(target_os = "android")] { PathBuf::from("/data/local/tmp") diff --git a/library/std/src/sys/pal/unix/os/tests.rs b/library/std/src/sys/pal/unix/os/tests.rs index a84086037ce0b..63a1cc1e94a1d 100644 --- a/library/std/src/sys/pal/unix/os/tests.rs +++ b/library/std/src/sys/pal/unix/os/tests.rs @@ -25,7 +25,7 @@ fn test_parse_glibc_version() { // Smoke check `confstr`, do it for several hint values, to ensure our resizing // logic is correct. #[test] -#[cfg(target_vendor = "apple")] +#[cfg(all(target_vendor = "apple", not(miri)))] fn test_confstr() { for key in [libc::_CS_DARWIN_USER_TEMP_DIR, libc::_CS_PATH] { let value_nohint = super::confstr(key, None).unwrap_or_else(|e| { From c85a742cb12491b1f138c5d208f9c0cc5434dd77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Bj=C3=B8rnager=20Jensen?= Date: Fri, 22 Nov 2024 09:44:08 +0100 Subject: [PATCH 08/10] Mark '<[T; N]>::as_mut_slice' as 'const'; --- library/core/src/array/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 4764d7f0b0fe0..a9d6a1d6a5daa 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -577,7 +577,8 @@ impl [T; N] { /// Returns a mutable slice containing the entire array. Equivalent to /// `&mut s[..]`. #[stable(feature = "array_as_slice", since = "1.57.0")] - pub fn as_mut_slice(&mut self) -> &mut [T] { + #[rustc_const_unstable(feature = "const_array_as_mut_slice", issue = "133333")] + pub const fn as_mut_slice(&mut self) -> &mut [T] { self } From 4627db2a107891da1999af06729e3422af773b56 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 12 Nov 2024 14:13:58 +0000 Subject: [PATCH 09/10] Diagnostic for using macro_rules macro as attr/derive --- compiler/rustc_resolve/messages.ftl | 8 +++- compiler/rustc_resolve/src/diagnostics.rs | 18 ++++++-- compiler/rustc_resolve/src/errors.rs | 16 +++++++ .../defined-later-issue-121061-2.stderr | 2 +- .../macros/defined-later-issue-121061.stderr | 2 +- ...ules-as-derive-or-attr-issue-132928.stderr | 42 +++++++------------ 6 files changed, 56 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 6602c7889691f..b13de2875bc20 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -257,8 +257,14 @@ resolve_lowercase_self = attempt to use a non-constant value in a constant .suggestion = try using `Self` +resolve_macro_cannot_use_as_attr = + `{$ident}` exists, but a declarative macro cannot be used as an attribute macro + +resolve_macro_cannot_use_as_derive = + `{$ident}` exists, but a declarative macro cannot be used as a derive macro + resolve_macro_defined_later = - a macro with the same name exists, but it appears later at here + a macro with the same name exists, but it appears later resolve_macro_expanded_extern_crate_cannot_shadow_extern_arguments = macro-expanded `extern crate` items cannot shadow names passed with `--extern` diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 5437ca65935f8..7bcab3f1c43d6 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -35,7 +35,8 @@ use tracing::debug; use crate::errors::{ self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive, - ExplicitUnsafeTraits, MacroDefinedLater, MacroSuggMovePosition, MaybeMissingMacroRulesName, + ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition, + MaybeMissingMacroRulesName, }; use crate::imports::{Import, ImportKind}; use crate::late::{PatternSource, Rib}; @@ -1475,8 +1476,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let scope = self.local_macro_def_scopes[&def_id]; let parent_nearest = parent_scope.module.nearest_parent_mod(); if Some(parent_nearest) == scope.opt_def_id() { - err.subdiagnostic(MacroDefinedLater { span: unused_ident.span }); - err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident }); + match macro_kind { + MacroKind::Bang => { + err.subdiagnostic(MacroDefinedLater { span: unused_ident.span }); + err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident }); + } + MacroKind::Attr => { + err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident }); + } + MacroKind::Derive => { + err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident }); + } + } + return; } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index f605b7096f0c2..24f5a812a82cd 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -665,6 +665,22 @@ pub(crate) struct MacroSuggMovePosition { pub(crate) ident: Ident, } +#[derive(Subdiagnostic)] +pub(crate) enum MacroRulesNot { + #[label(resolve_macro_cannot_use_as_attr)] + Attr { + #[primary_span] + span: Span, + ident: Ident, + }, + #[label(resolve_macro_cannot_use_as_derive)] + Derive { + #[primary_span] + span: Span, + ident: Ident, + }, +} + #[derive(Subdiagnostic)] #[note(resolve_missing_macro_rules_name)] pub(crate) struct MaybeMissingMacroRulesName { diff --git a/tests/ui/macros/defined-later-issue-121061-2.stderr b/tests/ui/macros/defined-later-issue-121061-2.stderr index aa6ef33853193..2ec590d46ed2c 100644 --- a/tests/ui/macros/defined-later-issue-121061-2.stderr +++ b/tests/ui/macros/defined-later-issue-121061-2.stderr @@ -4,7 +4,7 @@ error: cannot find macro `something_later` in this scope LL | something_later!(); | ^^^^^^^^^^^^^^^ consider moving the definition of `something_later` before this call | -note: a macro with the same name exists, but it appears later at here +note: a macro with the same name exists, but it appears later --> $DIR/defined-later-issue-121061-2.rs:6:18 | LL | macro_rules! something_later { diff --git a/tests/ui/macros/defined-later-issue-121061.stderr b/tests/ui/macros/defined-later-issue-121061.stderr index 65cb53432a932..7b3496991afec 100644 --- a/tests/ui/macros/defined-later-issue-121061.stderr +++ b/tests/ui/macros/defined-later-issue-121061.stderr @@ -4,7 +4,7 @@ error: cannot find macro `something_later` in this scope LL | something_later!(); | ^^^^^^^^^^^^^^^ consider moving the definition of `something_later` before this call | -note: a macro with the same name exists, but it appears later at here +note: a macro with the same name exists, but it appears later --> $DIR/defined-later-issue-121061.rs:5:14 | LL | macro_rules! something_later { diff --git a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr index fb7b649d32fa5..e5b913b208dca 100644 --- a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr +++ b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr @@ -1,51 +1,41 @@ error: cannot find derive macro `sample` in this scope --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10 | -LL | #[derive(sample)] - | ^^^^^^ consider moving the definition of `sample` before this call - | -note: a macro with the same name exists, but it appears later at here - --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:3:14 - | LL | macro_rules! sample { () => {} } - | ^^^^^^ + | ------ `sample` exists, but a declarative macro cannot be used as a derive macro +... +LL | #[derive(sample)] + | ^^^^^^ error: cannot find attribute `sample` in this scope --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:5:3 | -LL | #[sample] - | ^^^^^^ consider moving the definition of `sample` before this call - | -note: a macro with the same name exists, but it appears later at here - --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:3:14 - | LL | macro_rules! sample { () => {} } - | ^^^^^^ + | ------ `sample` exists, but a declarative macro cannot be used as an attribute macro +LL | +LL | #[sample] + | ^^^^^^ error: cannot find derive macro `sample` in this scope --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10 | +LL | macro_rules! sample { () => {} } + | ------ `sample` exists, but a declarative macro cannot be used as a derive macro +... LL | #[derive(sample)] - | ^^^^^^ consider moving the definition of `sample` before this call + | ^^^^^^ | -note: a macro with the same name exists, but it appears later at here - --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:3:14 - | -LL | macro_rules! sample { () => {} } - | ^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: cannot find derive macro `sample` in this scope --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:6:10 | +LL | macro_rules! sample { () => {} } + | ------ `sample` exists, but a declarative macro cannot be used as a derive macro +... LL | #[derive(sample)] - | ^^^^^^ consider moving the definition of `sample` before this call - | -note: a macro with the same name exists, but it appears later at here - --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:3:14 + | ^^^^^^ | -LL | macro_rules! sample { () => {} } - | ^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors From d294e4746bb1dae054b8e3e195b96e644e271b04 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Nov 2024 04:46:53 +0000 Subject: [PATCH 10/10] Remove unnecessary bool from ExpectedFound --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 4 +- compiler/rustc_infer/src/infer/at.rs | 42 ++++++------------- compiler/rustc_infer/src/infer/mod.rs | 18 ++------ .../rustc_infer/src/infer/opaque_types/mod.rs | 2 +- compiler/rustc_middle/src/ty/relate.rs | 4 +- .../src/error_reporting/infer/mod.rs | 4 +- .../traits/fulfillment_errors.rs | 7 ++-- .../src/solve/fulfill.rs | 4 +- .../src/traits/fulfill.rs | 13 +++--- .../src/traits/select/_match.rs | 4 +- compiler/rustc_type_ir/src/error.rs | 8 +--- compiler/rustc_type_ir/src/relate.rs | 34 +++++++-------- compiler/rustc_type_ir/src/relate/combine.rs | 4 +- 13 files changed, 58 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 961526831fbfd..9c18dbd422d90 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -729,7 +729,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let can_coerce = self.may_coerce(arg_ty, coerced_ty); if !can_coerce { return Compatibility::Incompatible(Some(ty::error::TypeError::Sorts( - ty::error::ExpectedFound::new(true, coerced_ty, arg_ty), + ty::error::ExpectedFound::new(coerced_ty, arg_ty), ))); } @@ -758,7 +758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { expected_ty }; - TypeTrace::types(&self.misc(span), true, mismatched_ty, provided_ty) + TypeTrace::types(&self.misc(span), mismatched_ty, provided_ty) }; // The algorithm here is inspired by levenshtein distance and longest common subsequence. diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 3eda3e9c67e85..12e2bbc968f0f 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -308,17 +308,14 @@ impl<'tcx> ToTrace<'tcx> for Ty<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())), + values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())), } } } impl<'tcx> ToTrace<'tcx> for ty::Region<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { - TypeTrace { - cause: cause.clone(), - values: ValuePairs::Regions(ExpectedFound::new(true, a, b)), - } + TypeTrace { cause: cause.clone(), values: ValuePairs::Regions(ExpectedFound::new(a, b)) } } } @@ -326,7 +323,7 @@ impl<'tcx> ToTrace<'tcx> for Const<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())), + values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())), } } } @@ -337,13 +334,13 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { cause: cause.clone(), values: match (a.unpack(), b.unpack()) { (GenericArgKind::Lifetime(a), GenericArgKind::Lifetime(b)) => { - ValuePairs::Regions(ExpectedFound::new(true, a, b)) + ValuePairs::Regions(ExpectedFound::new(a, b)) } (GenericArgKind::Type(a), GenericArgKind::Type(b)) => { - ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())) + ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())) } (GenericArgKind::Const(a), GenericArgKind::Const(b)) => { - ValuePairs::Terms(ExpectedFound::new(true, a.into(), b.into())) + ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())) } _ => bug!("relating different kinds: {a:?} {b:?}"), }, @@ -353,19 +350,13 @@ impl<'tcx> ToTrace<'tcx> for ty::GenericArg<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::Term<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { - TypeTrace { - cause: cause.clone(), - values: ValuePairs::Terms(ExpectedFound::new(true, a, b)), - } + TypeTrace { cause: cause.clone(), values: ValuePairs::Terms(ExpectedFound::new(a, b)) } } } impl<'tcx> ToTrace<'tcx> for ty::TraitRef<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { - TypeTrace { - cause: cause.clone(), - values: ValuePairs::TraitRefs(ExpectedFound::new(true, a, b)), - } + TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) } } } @@ -373,17 +364,14 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Aliases(ExpectedFound::new(true, a.into(), b.into())), + values: ValuePairs::Aliases(ExpectedFound::new(a.into(), b.into())), } } } impl<'tcx> ToTrace<'tcx> for ty::AliasTerm<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { - TypeTrace { - cause: cause.clone(), - values: ValuePairs::Aliases(ExpectedFound::new(true, a, b)), - } + TypeTrace { cause: cause.clone(), values: ValuePairs::Aliases(ExpectedFound::new(a, b)) } } } @@ -392,7 +380,6 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> { TypeTrace { cause: cause.clone(), values: ValuePairs::PolySigs(ExpectedFound::new( - true, ty::Binder::dummy(a), ty::Binder::dummy(b), )), @@ -402,10 +389,7 @@ impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> { impl<'tcx> ToTrace<'tcx> for ty::PolyFnSig<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { - TypeTrace { - cause: cause.clone(), - values: ValuePairs::PolySigs(ExpectedFound::new(true, a, b)), - } + TypeTrace { cause: cause.clone(), values: ValuePairs::PolySigs(ExpectedFound::new(a, b)) } } } @@ -413,7 +397,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialTraitRef<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(true, a, b)), + values: ValuePairs::ExistentialTraitRef(ExpectedFound::new(a, b)), } } } @@ -422,7 +406,7 @@ impl<'tcx> ToTrace<'tcx> for ty::PolyExistentialProjection<'tcx> { fn to_trace(cause: &ObligationCause<'tcx>, a: Self, b: Self) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::ExistentialProjection(ExpectedFound::new(true, a, b)), + values: ValuePairs::ExistentialProjection(ExpectedFound::new(a, b)), } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b29dc7f909dd5..7345c388c4f20 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1478,39 +1478,29 @@ impl<'tcx> TypeTrace<'tcx> { self.cause.span } - pub fn types( - cause: &ObligationCause<'tcx>, - a_is_expected: bool, - a: Ty<'tcx>, - b: Ty<'tcx>, - ) -> TypeTrace<'tcx> { + pub fn types(cause: &ObligationCause<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), + values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())), } } pub fn trait_refs( cause: &ObligationCause<'tcx>, - a_is_expected: bool, a: ty::TraitRef<'tcx>, b: ty::TraitRef<'tcx>, ) -> TypeTrace<'tcx> { - TypeTrace { - cause: cause.clone(), - values: ValuePairs::TraitRefs(ExpectedFound::new(a_is_expected, a, b)), - } + TypeTrace { cause: cause.clone(), values: ValuePairs::TraitRefs(ExpectedFound::new(a, b)) } } pub fn consts( cause: &ObligationCause<'tcx>, - a_is_expected: bool, a: ty::Const<'tcx>, b: ty::Const<'tcx>, ) -> TypeTrace<'tcx> { TypeTrace { cause: cause.clone(), - values: ValuePairs::Terms(ExpectedFound::new(a_is_expected, a.into(), b.into())), + values: ValuePairs::Terms(ExpectedFound::new(a.into(), b.into())), } } } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 0aff46203144a..5499fed1bdfd6 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -177,7 +177,7 @@ impl<'tcx> InferCtxt<'tcx> { res } else { let (a, b) = self.resolve_vars_if_possible((a, b)); - Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) + Err(TypeError::Sorts(ExpectedFound::new(a, b))) } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 504a3c8a6d832..b06687490d26c 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -92,7 +92,7 @@ impl<'tcx> Relate> for &'tcx ty::List Relate> for &'tcx ty::List Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))), - _ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(true, a, b))), + _ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))), } }); tcx.mk_poly_existential_predicates_from_iter(v) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 929fa559d750c..c7ad14ac0bfce 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -152,7 +152,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err: TypeError<'tcx>, ) -> Diag<'a> { self.report_and_explain_type_error( - TypeTrace::types(cause, true, expected, actual), + TypeTrace::types(cause, expected, actual), param_env, err, ) @@ -167,7 +167,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err: TypeError<'tcx>, ) -> Diag<'a> { self.report_and_explain_type_error( - TypeTrace::consts(cause, true, expected, actual), + TypeTrace::consts(cause, expected, actual), param_env, err, ) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 4e7d7b79ff4de..107ebe8adf03c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -725,7 +725,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &obligation.cause, None, None, - TypeError::Sorts(ty::error::ExpectedFound::new(true, expected_ty, ct_ty)), + TypeError::Sorts(ty::error::ExpectedFound::new(expected_ty, ct_ty)), false, ); diag @@ -1449,7 +1449,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { secondary_span, values.map(|(_, normalized_ty, expected_ty)| { obligation.param_env.and(infer::ValuePairs::Terms(ExpectedFound::new( - true, expected_ty, normalized_ty, ))) @@ -2755,7 +2754,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { (obligation.cause.clone(), terr) }; self.report_and_explain_type_error( - TypeTrace::trait_refs(&cause, true, expected_trait_ref, found_trait_ref), + TypeTrace::trait_refs(&cause, expected_trait_ref, found_trait_ref), obligation.param_env, terr, ) @@ -2846,7 +2845,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() && not_tupled { return Ok(self.report_and_explain_type_error( - TypeTrace::trait_refs(&obligation.cause, true, expected_trait_ref, found_trait_ref), + TypeTrace::trait_refs(&obligation.cause, expected_trait_ref, found_trait_ref), obligation.param_env, ty::error::TypeError::Mismatch, )); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 53e5420d27a5d..311dc214de601 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -264,14 +264,14 @@ fn fulfillment_error_for_no_solution<'tcx>( let (a, b) = infcx.enter_forall_and_leak_universe( obligation.predicate.kind().rebind((pred.a, pred.b)), ); - let expected_found = ExpectedFound::new(true, a, b); + let expected_found = ExpectedFound::new(a, b); FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) } ty::PredicateKind::Coerce(pred) => { let (a, b) = infcx.enter_forall_and_leak_universe( obligation.predicate.kind().rebind((pred.a, pred.b)), ); - let expected_found = ExpectedFound::new(false, a, b); + let expected_found = ExpectedFound::new(b, a); FulfillmentErrorCode::Subtype(expected_found, TypeError::Sorts(expected_found)) } ty::PredicateKind::Clause(_) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 2ec5f0d22496d..581f0c5c7bad2 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -557,8 +557,11 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ProcessResult::Changed(mk_pending(ok.obligations)) } Ok(Err(err)) => { - let expected_found = - ExpectedFound::new(subtype.a_is_expected, subtype.a, subtype.b); + let expected_found = if subtype.a_is_expected { + ExpectedFound::new(subtype.a, subtype.b) + } else { + ExpectedFound::new(subtype.b, subtype.a) + }; ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err)) } } @@ -578,7 +581,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } Ok(Ok(ok)) => ProcessResult::Changed(mk_pending(ok.obligations)), Ok(Err(err)) => { - let expected_found = ExpectedFound::new(false, coerce.a, coerce.b); + let expected_found = ExpectedFound::new(coerce.b, coerce.a); ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err)) } } @@ -703,7 +706,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } Err(err) => { ProcessResult::Error(FulfillmentErrorCode::ConstEquate( - ExpectedFound::new(true, c1, c2), + ExpectedFound::new(c1, c2), err, )) } @@ -727,7 +730,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ProcessResult::Unchanged } else { // Two different constants using generic parameters ~> error. - let expected_found = ExpectedFound::new(true, c1, c2); + let expected_found = ExpectedFound::new(c1, c2); ProcessResult::Error(FulfillmentErrorCode::ConstEquate( expected_found, TypeError::ConstMismatch(expected_found), diff --git a/compiler/rustc_trait_selection/src/traits/select/_match.rs b/compiler/rustc_trait_selection/src/traits/select/_match.rs index 3980d672a11bc..7c19c35a4f784 100644 --- a/compiler/rustc_trait_selection/src/traits/select/_match.rs +++ b/compiler/rustc_trait_selection/src/traits/select/_match.rs @@ -70,7 +70,7 @@ impl<'tcx> TypeRelation> for MatchAgainstFreshVars<'tcx> { ) => Ok(a), (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { - Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) + Err(TypeError::Sorts(ExpectedFound::new(a, b))) } (&ty::Error(guar), _) | (_, &ty::Error(guar)) => Ok(Ty::new_error(self.cx(), guar)), @@ -95,7 +95,7 @@ impl<'tcx> TypeRelation> for MatchAgainstFreshVars<'tcx> { } (ty::ConstKind::Infer(_), _) | (_, ty::ConstKind::Infer(_)) => { - return Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b))); + return Err(TypeError::ConstMismatch(ExpectedFound::new(a, b))); } _ => {} diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index cdff77f742d0a..59dea7695111f 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -12,12 +12,8 @@ pub struct ExpectedFound { } impl ExpectedFound { - pub fn new(a_is_expected: bool, a: T, b: T) -> Self { - if a_is_expected { - ExpectedFound { expected: a, found: b } - } else { - ExpectedFound { expected: b, found: a } - } + pub fn new(expected: T, found: T) -> Self { + ExpectedFound { expected, found } } } diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index ad17911830b3d..6b301b1606050 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -171,16 +171,16 @@ impl Relate for ty::FnSig { return Err(TypeError::VariadicMismatch({ let a = a.c_variadic; let b = b.c_variadic; - ExpectedFound::new(true, a, b) + ExpectedFound::new(a, b) })); } if a.safety != b.safety { - return Err(TypeError::SafetyMismatch(ExpectedFound::new(true, a.safety, b.safety))); + return Err(TypeError::SafetyMismatch(ExpectedFound::new(a.safety, b.safety))); } if a.abi != b.abi { - return Err(TypeError::AbiMismatch(ExpectedFound::new(true, a.abi, b.abi))); + return Err(TypeError::AbiMismatch(ExpectedFound::new(a.abi, b.abi))); }; let a_inputs = a.inputs(); @@ -233,7 +233,7 @@ impl Relate for ty::AliasTy { Err(TypeError::ProjectionMismatched({ let a = a.def_id; let b = b.def_id; - ExpectedFound::new(true, a, b) + ExpectedFound::new(a, b) })) } else { let args = match a.kind(relation.cx()) { @@ -274,7 +274,7 @@ impl Relate for ty::AliasTerm { Err(TypeError::ProjectionMismatched({ let a = a.def_id; let b = b.def_id; - ExpectedFound::new(true, a, b) + ExpectedFound::new(a, b) })) } else { let args = match a.kind(relation.cx()) { @@ -309,7 +309,7 @@ impl Relate for ty::ExistentialProjection { Err(TypeError::ProjectionMismatched({ let a = a.def_id; let b = b.def_id; - ExpectedFound::new(true, a, b) + ExpectedFound::new(a, b) })) } else { let term = relation.relate_with_variance( @@ -340,7 +340,7 @@ impl Relate for ty::TraitRef { Err(TypeError::Traits({ let a = a.def_id; let b = b.def_id; - ExpectedFound::new(true, a, b) + ExpectedFound::new(a, b) })) } else { let args = relate_args_invariantly(relation, a.args, b.args)?; @@ -360,7 +360,7 @@ impl Relate for ty::ExistentialTraitRef { Err(TypeError::Traits({ let a = a.def_id; let b = b.def_id; - ExpectedFound::new(true, a, b) + ExpectedFound::new(a, b) })) } else { let args = relate_args_invariantly(relation, a.args, b.args)?; @@ -508,9 +508,9 @@ pub fn structurally_relate_tys>( let sz_b = sz_b.try_to_target_usize(cx); match (sz_a, sz_b) { - (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => Err( - TypeError::FixedArraySize(ExpectedFound::new(true, sz_a_val, sz_b_val)), - ), + (Some(sz_a_val), Some(sz_b_val)) if sz_a_val != sz_b_val => { + Err(TypeError::FixedArraySize(ExpectedFound::new(sz_a_val, sz_b_val))) + } _ => Err(err), } } @@ -529,9 +529,9 @@ pub fn structurally_relate_tys>( iter::zip(as_.iter(), bs.iter()).map(|(a, b)| relation.relate(a, b)), )?) } else if !(as_.is_empty() || bs.is_empty()) { - Err(TypeError::TupleSize(ExpectedFound::new(true, as_.len(), bs.len()))) + Err(TypeError::TupleSize(ExpectedFound::new(as_.len(), bs.len()))) } else { - Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) + Err(TypeError::Sorts(ExpectedFound::new(a, b))) } } @@ -558,7 +558,7 @@ pub fn structurally_relate_tys>( Ok(Ty::new_pat(cx, ty, pat)) } - _ => Err(TypeError::Sorts(ExpectedFound::new(true, a, b))), + _ => Err(TypeError::Sorts(ExpectedFound::new(a, b))), } } @@ -637,7 +637,7 @@ pub fn structurally_relate_consts>( } _ => false, }; - if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(ExpectedFound::new(true, a, b))) } + if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(ExpectedFound::new(a, b))) } } impl> Relate for ty::Binder { @@ -658,9 +658,7 @@ impl Relate for ty::TraitPredicate { ) -> RelateResult> { let trait_ref = relation.relate(a.trait_ref, b.trait_ref)?; if a.polarity != b.polarity { - return Err(TypeError::PolarityMismatch(ExpectedFound::new( - true, a.polarity, b.polarity, - ))); + return Err(TypeError::PolarityMismatch(ExpectedFound::new(a.polarity, b.polarity))); } Ok(ty::TraitPredicate { trait_ref, polarity: a.polarity }) } diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 53751f7711a71..876da5d19b99a 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -123,9 +123,7 @@ where } // All other cases of inference are errors - (ty::Infer(_), _) | (_, ty::Infer(_)) => { - Err(TypeError::Sorts(ExpectedFound::new(true, a, b))) - } + (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Sorts(ExpectedFound::new(a, b))), (ty::Alias(ty::Opaque, _), _) | (_, ty::Alias(ty::Opaque, _)) => { assert!(!infcx.next_trait_solver());