Auto merge of #139037 - jhpratt:rollup-4c74y8a, r=jhpratt

Rollup of 6 pull requests

Successful merges:

 - #138720 (Specify a concrete stack size in channel tests)
 - #139010 (Improve `xcrun` error handling)
 - #139021 (std: get rid of pre-Vista fallback code)
 - #139025 (Do not trim paths in MIR validator)
 - #139026 (Use `abs_diff` where applicable)
 - #139030 (saethlin goes on vacation)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-03-28 06:28:48 +00:00
commit e77a8f439c
19 changed files with 384 additions and 147 deletions

View File

@ -10,8 +10,6 @@ codegen_ssa_apple_deployment_target_invalid =
codegen_ssa_apple_deployment_target_too_low = codegen_ssa_apple_deployment_target_too_low =
deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min} deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min}
codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error}
codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error}
codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering
@ -391,8 +389,6 @@ codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic
codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
codegen_ssa_unsupported_instruction_set = target does not support `#[instruction_set]` codegen_ssa_unsupported_instruction_set = target does not support `#[instruction_set]`
codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
@ -402,3 +398,20 @@ codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to sp
codegen_ssa_version_script_write_failure = failed to write version script: {$error} codegen_ssa_version_script_write_failure = failed to write version script: {$error}
codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload codegen_ssa_visual_studio_not_installed = you may need to install Visual Studio build tools with the "C++ build tools" workload
codegen_ssa_xcrun_command_line_tools_insufficient =
when compiling for iOS, tvOS, visionOS or watchOS, you need a full installation of Xcode
codegen_ssa_xcrun_failed_invoking = invoking `{$command_formatted}` to find {$sdk_name}.sdk failed: {$error}
codegen_ssa_xcrun_found_developer_dir = found active developer directory at "{$developer_dir}"
# `xcrun` already outputs a message about missing Xcode installation, so we only augment it with details about env vars.
codegen_ssa_xcrun_no_developer_dir =
pass the path of an Xcode installation via the DEVELOPER_DIR environment variable, or an SDK with the SDKROOT environment variable
codegen_ssa_xcrun_sdk_path_warning = output of `xcrun` while finding {$sdk_name}.sdk
.note = {$stderr}
codegen_ssa_xcrun_unsuccessful = failed running `{$command_formatted}` to find {$sdk_name}.sdk
.note = {$stdout}{$stderr}

View File

@ -1,16 +1,40 @@
use std::env; use std::env;
use std::ffi::OsString;
use std::fmt::{Display, from_fn}; use std::fmt::{Display, from_fn};
use std::num::ParseIntError; use std::num::ParseIntError;
use std::path::PathBuf;
use std::process::Command;
use itertools::Itertools;
use rustc_middle::middle::exported_symbols::SymbolExportKind; use rustc_middle::middle::exported_symbols::SymbolExportKind;
use rustc_session::Session; use rustc_session::Session;
use rustc_target::spec::Target; use rustc_target::spec::Target;
use tracing::debug;
use crate::errors::AppleDeploymentTarget; use crate::errors::{AppleDeploymentTarget, XcrunError, XcrunSdkPathWarning};
use crate::fluent_generated as fluent;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
/// The canonical name of the desired SDK for a given target.
pub(super) fn sdk_name(target: &Target) -> &'static str {
match (&*target.os, &*target.abi) {
("macos", "") => "MacOSX",
("ios", "") => "iPhoneOS",
("ios", "sim") => "iPhoneSimulator",
// Mac Catalyst uses the macOS SDK
("ios", "macabi") => "MacOSX",
("tvos", "") => "AppleTVOS",
("tvos", "sim") => "AppleTVSimulator",
("visionos", "") => "XROS",
("visionos", "sim") => "XRSimulator",
("watchos", "") => "WatchOS",
("watchos", "sim") => "WatchSimulator",
(os, abi) => unreachable!("invalid os '{os}' / abi '{abi}' combination for Apple target"),
}
}
pub(super) fn macho_platform(target: &Target) -> u32 { pub(super) fn macho_platform(target: &Target) -> u32 {
match (&*target.os, &*target.abi) { match (&*target.os, &*target.abi) {
("macos", _) => object::macho::PLATFORM_MACOS, ("macos", _) => object::macho::PLATFORM_MACOS,
@ -253,3 +277,131 @@ pub(super) fn add_version_to_llvm_target(
format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}") format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}")
} }
} }
pub(super) fn get_sdk_root(sess: &Session) -> Option<PathBuf> {
let sdk_name = sdk_name(&sess.target);
match xcrun_show_sdk_path(sdk_name, sess.verbose_internals()) {
Ok((path, stderr)) => {
// Emit extra stderr, such as if `-verbose` was passed, or if `xcrun` emitted a warning.
if !stderr.is_empty() {
sess.dcx().emit_warn(XcrunSdkPathWarning { sdk_name, stderr });
}
Some(path)
}
Err(err) => {
let mut diag = sess.dcx().create_err(err);
// Recognize common error cases, and give more Rust-specific error messages for those.
if let Some(developer_dir) = xcode_select_developer_dir() {
diag.arg("developer_dir", &developer_dir);
diag.note(fluent::codegen_ssa_xcrun_found_developer_dir);
if developer_dir.as_os_str().to_string_lossy().contains("CommandLineTools") {
if sdk_name != "MacOSX" {
diag.help(fluent::codegen_ssa_xcrun_command_line_tools_insufficient);
}
}
} else {
diag.help(fluent::codegen_ssa_xcrun_no_developer_dir);
}
diag.emit();
None
}
}
}
/// Invoke `xcrun --sdk $sdk_name --show-sdk-path` to get the SDK path.
///
/// The exact logic that `xcrun` uses is unspecified (see `man xcrun` for a few details), and may
/// change between macOS and Xcode versions, but it roughly boils down to finding the active
/// developer directory, and then invoking `xcodebuild -sdk $sdk_name -version` to get the SDK
/// details.
///
/// Finding the developer directory is roughly done by looking at, in order:
/// - The `DEVELOPER_DIR` environment variable.
/// - The `/var/db/xcode_select_link` symlink (set by `xcode-select --switch`).
/// - `/Applications/Xcode.app` (hardcoded fallback path).
/// - `/Library/Developer/CommandLineTools` (hardcoded fallback path).
///
/// Note that `xcrun` caches its result, but with a cold cache this whole operation can be quite
/// slow, especially so the first time it's run after a reboot.
fn xcrun_show_sdk_path(
sdk_name: &'static str,
verbose: bool,
) -> Result<(PathBuf, String), XcrunError> {
let mut cmd = Command::new("xcrun");
if verbose {
cmd.arg("--verbose");
}
// The `--sdk` parameter is the same as in xcodebuild, namely either an absolute path to an SDK,
// or the (lowercase) canonical name of an SDK.
cmd.arg("--sdk");
cmd.arg(&sdk_name.to_lowercase());
cmd.arg("--show-sdk-path");
// We do not stream stdout/stderr lines directly to the user, since whether they are warnings or
// errors depends on the status code at the end.
let output = cmd.output().map_err(|error| XcrunError::FailedInvoking {
sdk_name,
command_formatted: format!("{cmd:?}"),
error,
})?;
// It is fine to do lossy conversion here, non-UTF-8 paths are quite rare on macOS nowadays
// (only possible with the HFS+ file system), and we only use it for error messages.
let stderr = String::from_utf8_lossy_owned(output.stderr);
if !stderr.is_empty() {
debug!(stderr, "original xcrun stderr");
}
// Some versions of `xcodebuild` output beefy errors when invoked via `xcrun`,
// but these are usually red herrings.
let stderr = stderr
.lines()
.filter(|line| {
!line.contains("Writing error result bundle")
&& !line.contains("Requested but did not find extension point with identifier")
})
.join("\n");
if output.status.success() {
Ok((stdout_to_path(output.stdout), stderr))
} else {
// Output both stdout and stderr, since shims of `xcrun` (such as the one provided by
// nixpkgs), do not always use stderr for errors.
let stdout = String::from_utf8_lossy_owned(output.stdout).trim().to_string();
Err(XcrunError::Unsuccessful {
sdk_name,
command_formatted: format!("{cmd:?}"),
stdout,
stderr,
})
}
}
/// Invoke `xcode-select --print-path`, and return the current developer directory.
///
/// NOTE: We don't do any error handling here, this is only used as a canary in diagnostics (`xcrun`
/// will have already emitted the relevant error information).
fn xcode_select_developer_dir() -> Option<PathBuf> {
let mut cmd = Command::new("xcode-select");
cmd.arg("--print-path");
let output = cmd.output().ok()?;
if !output.status.success() {
return None;
}
Some(stdout_to_path(output.stdout))
}
fn stdout_to_path(mut stdout: Vec<u8>) -> PathBuf {
// Remove trailing newline.
if let Some(b'\n') = stdout.last() {
let _ = stdout.pop().unwrap();
}
#[cfg(unix)]
let path = <OsString as std::os::unix::ffi::OsStringExt>::from_vec(stdout);
#[cfg(not(unix))] // Unimportant, this is only used on macOS
let path = OsString::from(String::from_utf8(stdout).unwrap());
PathBuf::from(path)
}

View File

@ -1,4 +1,4 @@
use super::{add_version_to_llvm_target, parse_version}; use super::*;
#[test] #[test]
fn test_add_version_to_llvm_target() { fn test_add_version_to_llvm_target() {
@ -19,3 +19,69 @@ fn test_parse_version() {
assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6))); assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6)));
assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99))); assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99)));
} }
#[test]
#[cfg_attr(not(target_os = "macos"), ignore = "xcode-select is only available on macOS")]
fn lookup_developer_dir() {
let _developer_dir = xcode_select_developer_dir().unwrap();
}
#[test]
#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")]
fn lookup_sdk() {
let (sdk_path, stderr) = xcrun_show_sdk_path("MacOSX", false).unwrap();
// Check that the found SDK is valid.
assert!(sdk_path.join("SDKSettings.plist").exists());
assert_eq!(stderr, "");
// Test that the SDK root is a subdir of the developer directory.
if let Some(developer_dir) = xcode_select_developer_dir() {
// Only run this test if SDKROOT is not set (otherwise xcrun may look up via. that).
if std::env::var_os("SDKROOT").is_some() {
assert!(sdk_path.starts_with(&developer_dir));
}
}
}
#[test]
#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")]
fn lookup_sdk_verbose() {
let (_, stderr) = xcrun_show_sdk_path("MacOSX", true).unwrap();
// Newer xcrun versions should emit something like this:
//
// xcrun: note: looking up SDK with 'xcodebuild -sdk macosx -version Path'
// xcrun: note: xcrun_db = '/var/.../xcrun_db'
// xcrun: note: lookup resolved to: '...'
// xcrun: note: database key is: ...
//
// Or if the value is already cached, something like this:
//
// xcrun: note: database key is: ...
// xcrun: note: lookup resolved in '/var/.../xcrun_db' : '...'
assert!(
stderr.contains("xcrun: note: lookup resolved"),
"stderr should contain lookup note: {stderr}",
);
}
#[test]
#[cfg_attr(not(target_os = "macos"), ignore = "xcrun is only available on macOS")]
fn try_lookup_invalid_sdk() {
// As a proxy for testing all the different ways that `xcrun` can fail,
// test the case where an SDK was not found.
let err = xcrun_show_sdk_path("invalid", false).unwrap_err();
let XcrunError::Unsuccessful { stderr, .. } = err else {
panic!("unexpected error kind: {err:?}");
};
// Either one of (depending on if using Command Line Tools or full Xcode):
// xcrun: error: SDK "invalid" cannot be located
// xcodebuild: error: SDK "invalid" cannot be located.
assert!(
stderr.contains(r#"error: SDK "invalid" cannot be located"#),
"stderr should contain xcodebuild note: {stderr}",
);
assert!(
stderr.contains("xcrun: error: unable to lookup item 'Path' in SDK 'invalid'"),
"stderr should contain xcrun note: {stderr}",
);
}

View File

@ -3201,9 +3201,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
} }
fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option<PathBuf> { fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) -> Option<PathBuf> {
let arch = &sess.target.arch;
let os = &sess.target.os; let os = &sess.target.os;
let llvm_target = &sess.target.llvm_target;
if sess.target.vendor != "apple" if sess.target.vendor != "apple"
|| !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos") || !matches!(os.as_ref(), "ios" | "tvos" | "watchos" | "visionos" | "macos")
|| !matches!(flavor, LinkerFlavor::Darwin(..)) || !matches!(flavor, LinkerFlavor::Darwin(..))
@ -3215,37 +3213,7 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) ->
return None; return None;
} }
let sdk_name = match (arch.as_ref(), os.as_ref()) { let sdk_root = sess.time("get_apple_sdk_root", || get_apple_sdk_root(sess))?;
("aarch64", "tvos") if llvm_target.ends_with("-simulator") => "appletvsimulator",
("aarch64", "tvos") => "appletvos",
("x86_64", "tvos") => "appletvsimulator",
("arm", "ios") => "iphoneos",
("aarch64", "ios") if llvm_target.contains("macabi") => "macosx",
("aarch64", "ios") if llvm_target.ends_with("-simulator") => "iphonesimulator",
("aarch64", "ios") => "iphoneos",
("x86", "ios") => "iphonesimulator",
("x86_64", "ios") if llvm_target.contains("macabi") => "macosx",
("x86_64", "ios") => "iphonesimulator",
("x86_64", "watchos") => "watchsimulator",
("arm64_32", "watchos") => "watchos",
("aarch64", "watchos") if llvm_target.ends_with("-simulator") => "watchsimulator",
("aarch64", "watchos") => "watchos",
("aarch64", "visionos") if llvm_target.ends_with("-simulator") => "xrsimulator",
("aarch64", "visionos") => "xros",
("arm", "watchos") => "watchos",
(_, "macos") => "macosx",
_ => {
sess.dcx().emit_err(errors::UnsupportedArch { arch, os });
return None;
}
};
let sdk_root = match get_apple_sdk_root(sdk_name) {
Ok(s) => s,
Err(e) => {
sess.dcx().emit_err(e);
return None;
}
};
match flavor { match flavor {
LinkerFlavor::Darwin(Cc::Yes, _) => { LinkerFlavor::Darwin(Cc::Yes, _) => {
@ -3255,28 +3223,32 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) ->
// This is admittedly a bit strange, as on most targets // This is admittedly a bit strange, as on most targets
// `-isysroot` only applies to include header files, but on Apple // `-isysroot` only applies to include header files, but on Apple
// targets this also applies to libraries and frameworks. // targets this also applies to libraries and frameworks.
cmd.cc_args(&["-isysroot", &sdk_root]); cmd.cc_arg("-isysroot");
cmd.cc_arg(&sdk_root);
} }
LinkerFlavor::Darwin(Cc::No, _) => { LinkerFlavor::Darwin(Cc::No, _) => {
cmd.link_args(&["-syslibroot", &sdk_root]); cmd.link_arg("-syslibroot");
cmd.link_arg(&sdk_root);
} }
_ => unreachable!(), _ => unreachable!(),
} }
Some(sdk_root.into()) Some(sdk_root)
} }
fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootError<'_>> { fn get_apple_sdk_root(sess: &Session) -> Option<PathBuf> {
// Following what clang does
// (https://github.com/llvm/llvm-project/blob/
// 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
// to allow the SDK path to be set. (For clang, xcrun sets
// SDKROOT; for rustc, the user or build system can set it, or we
// can fall back to checking for xcrun on PATH.)
if let Ok(sdkroot) = env::var("SDKROOT") { if let Ok(sdkroot) = env::var("SDKROOT") {
let p = Path::new(&sdkroot); let p = PathBuf::from(&sdkroot);
match sdk_name {
// Ignore `SDKROOT` if it's clearly set for the wrong platform. // Ignore invalid SDKs, similar to what clang does:
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.6/clang/lib/Driver/ToolChains/Darwin.cpp#L2212-L2229
//
// NOTE: Things are complicated here by the fact that `rustc` can be run by Cargo to compile
// build scripts and proc-macros for the host, and thus we need to ignore SDKROOT if it's
// clearly set for the wrong platform.
//
// FIXME(madsmtm): Make this more robust (maybe read `SDKSettings.json` like Clang does?).
match &*apple::sdk_name(&sess.target).to_lowercase() {
"appletvos" "appletvos"
if sdkroot.contains("TVSimulator.platform") if sdkroot.contains("TVSimulator.platform")
|| sdkroot.contains("MacOSX.platform") => {} || sdkroot.contains("MacOSX.platform") => {}
@ -3303,26 +3275,11 @@ fn get_apple_sdk_root(sdk_name: &str) -> Result<String, errors::AppleSdkRootErro
if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {} if sdkroot.contains("XROS.platform") || sdkroot.contains("MacOSX.platform") => {}
// Ignore `SDKROOT` if it's not a valid path. // Ignore `SDKROOT` if it's not a valid path.
_ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {} _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
_ => return Ok(sdkroot), _ => return Some(p),
} }
} }
let res =
Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
|output| {
if output.status.success() {
Ok(String::from_utf8(output.stdout).unwrap())
} else {
let error = String::from_utf8(output.stderr);
let error = format!("process exit with error: {}", error.unwrap());
Err(io::Error::new(io::ErrorKind::Other, &error[..]))
}
},
);
match res { apple::get_sdk_root(sess)
Ok(output) => Ok(output.trim().to_string()),
Err(error) => Err(errors::AppleSdkRootError::SdkPath { sdk_name, error }),
}
} }
/// When using the linker flavors opting in to `lld`, add the necessary paths and arguments to /// When using the linker flavors opting in to `lld`, add the necessary paths and arguments to

View File

@ -738,13 +738,6 @@ pub enum ExtractBundledLibsError<'a> {
ExtractSection { rlib: &'a Path, error: Box<dyn std::error::Error> }, ExtractSection { rlib: &'a Path, error: Box<dyn std::error::Error> },
} }
#[derive(Diagnostic)]
#[diag(codegen_ssa_unsupported_arch)]
pub(crate) struct UnsupportedArch<'a> {
pub arch: &'a str,
pub os: &'a str,
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
pub(crate) enum AppleDeploymentTarget { pub(crate) enum AppleDeploymentTarget {
#[diag(codegen_ssa_apple_deployment_target_invalid)] #[diag(codegen_ssa_apple_deployment_target_invalid)]
@ -753,12 +746,6 @@ pub(crate) enum AppleDeploymentTarget {
TooLow { env_var: &'static str, version: String, os_min: String }, TooLow { env_var: &'static str, version: String, os_min: String },
} }
#[derive(Diagnostic)]
pub(crate) enum AppleSdkRootError<'a> {
#[diag(codegen_ssa_apple_sdk_error_sdk_path)]
SdkPath { sdk_name: &'a str, error: Error },
}
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(codegen_ssa_read_file)] #[diag(codegen_ssa_read_file)]
pub(crate) struct ReadFileError { pub(crate) struct ReadFileError {
@ -1334,3 +1321,26 @@ pub(crate) struct MixedExportNameAndNoMangle {
#[suggestion(style = "verbose", code = "", applicability = "machine-applicable")] #[suggestion(style = "verbose", code = "", applicability = "machine-applicable")]
pub removal_span: Span, pub removal_span: Span,
} }
#[derive(Diagnostic, Debug)]
pub(crate) enum XcrunError {
#[diag(codegen_ssa_xcrun_failed_invoking)]
FailedInvoking { sdk_name: &'static str, command_formatted: String, error: std::io::Error },
#[diag(codegen_ssa_xcrun_unsuccessful)]
#[note]
Unsuccessful {
sdk_name: &'static str,
command_formatted: String,
stdout: String,
stderr: String,
},
}
#[derive(Diagnostic, Debug)]
#[diag(codegen_ssa_xcrun_sdk_path_warning)]
#[note]
pub(crate) struct XcrunSdkPathWarning {
pub sdk_name: &'static str,
pub stderr: String,
}

View File

@ -13,6 +13,7 @@
#![feature(let_chains)] #![feature(let_chains)]
#![feature(negative_impls)] #![feature(negative_impls)]
#![feature(rustdoc_internals)] #![feature(rustdoc_internals)]
#![feature(string_from_utf8_lossy_owned)]
#![feature(trait_alias)] #![feature(trait_alias)]
#![feature(try_blocks)] #![feature(try_blocks)]
// tidy-alphabetical-end // tidy-alphabetical-end

View File

@ -159,11 +159,7 @@ impl Annotation {
/// Length of this annotation as displayed in the stderr output /// Length of this annotation as displayed in the stderr output
pub(crate) fn len(&self) -> usize { pub(crate) fn len(&self) -> usize {
// Account for usize underflows // Account for usize underflows
if self.end_col.display > self.start_col.display { self.end_col.display.abs_diff(self.start_col.display)
self.end_col.display - self.start_col.display
} else {
self.start_col.display - self.end_col.display
}
} }
pub(crate) fn has_label(&self) -> bool { pub(crate) fn has_label(&self) -> bool {

View File

@ -12,6 +12,7 @@ use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*; use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Upcast, Variance, self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Upcast, Variance,
}; };
@ -56,7 +57,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
ty::Coroutine(..) => ExternAbi::Rust, ty::Coroutine(..) => ExternAbi::Rust,
// No need to do MIR validation on error bodies // No need to do MIR validation on error bodies
ty::Error(_) => return, ty::Error(_) => return,
_ => span_bug!(body.span, "unexpected body ty: {body_ty:?}"), _ => span_bug!(body.span, "unexpected body ty: {body_ty}"),
}; };
ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi) ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi)
@ -543,7 +544,13 @@ pub(super) fn validate_types<'tcx>(
caller_body: &Body<'tcx>, caller_body: &Body<'tcx>,
) -> Vec<(Location, String)> { ) -> Vec<(Location, String)> {
let mut type_checker = TypeChecker { body, caller_body, tcx, typing_env, failures: Vec::new() }; let mut type_checker = TypeChecker { body, caller_body, tcx, typing_env, failures: Vec::new() };
// The type checker formats a bunch of strings with type names in it, but these strings
// are not always going to be encountered on the error path since the inliner also uses
// the validator, and there are certain kinds of inlining (even for valid code) that
// can cause validation errors (mostly around where clauses and rigid projections).
with_no_trimmed_paths!({
type_checker.visit_body(body); type_checker.visit_body(body);
});
type_checker.failures type_checker.failures
} }
@ -655,7 +662,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
ProjectionElem::Index(index) => { ProjectionElem::Index(index) => {
let index_ty = self.body.local_decls[index].ty; let index_ty = self.body.local_decls[index].ty;
if index_ty != self.tcx.types.usize { if index_ty != self.tcx.types.usize {
self.fail(location, format!("bad index ({index_ty:?} != usize)")) self.fail(location, format!("bad index ({index_ty} != usize)"))
} }
} }
ProjectionElem::Deref ProjectionElem::Deref
@ -664,10 +671,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty; let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;
if base_ty.is_box() { if base_ty.is_box() {
self.fail( self.fail(location, format!("{base_ty} dereferenced after ElaborateBoxDerefs"))
location,
format!("{base_ty:?} dereferenced after ElaborateBoxDerefs"),
)
} }
} }
ProjectionElem::Field(f, ty) => { ProjectionElem::Field(f, ty) => {
@ -680,7 +684,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
this.fail( this.fail(
location, location,
format!( format!(
"Field projection `{place_ref:?}.{f:?}` specified type `{ty:?}`, but actual type is `{f_ty:?}`" "Field projection `{place_ref:?}.{f:?}` specified type `{ty}`, but actual type is `{f_ty}`"
) )
) )
} }
@ -806,7 +810,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail( self.fail(
location, location,
format!( format!(
"Failed subtyping {ty:#?} and {:#?}", "Failed subtyping {ty} and {}",
place_ref.ty(&self.body.local_decls, self.tcx).ty place_ref.ty(&self.body.local_decls, self.tcx).ty
), ),
) )
@ -826,7 +830,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail( self.fail(
location, location,
format!( format!(
"Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty:?}" "Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty}"
), ),
); );
} }
@ -841,7 +845,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if ty.is_union() || ty.is_enum() { if ty.is_union() || ty.is_enum() {
self.fail( self.fail(
START_BLOCK.start_location(), START_BLOCK.start_location(),
format!("invalid type {ty:?} in debuginfo for {:?}", debuginfo.name), format!("invalid type {ty} in debuginfo for {:?}", debuginfo.name),
); );
} }
if projection.is_empty() { if projection.is_empty() {
@ -1064,15 +1068,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if !self.mir_assign_valid_types(a, b) { if !self.mir_assign_valid_types(a, b) {
self.fail( self.fail(
location, location,
format!("Cannot {op:?} compare incompatible types {a:?} and {b:?}"), format!("Cannot {op:?} compare incompatible types {a} and {b}"),
); );
} }
} else if a != b { } else if a != b {
self.fail( self.fail(
location, location,
format!( format!("Cannot perform binary op {op:?} on unequal types {a} and {b}"),
"Cannot perform binary op {op:?} on unequal types {a:?} and {b:?}"
),
); );
} }
} }
@ -1081,7 +1083,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
Offset => { Offset => {
check_kinds!(a, "Cannot offset non-pointer type {:?}", ty::RawPtr(..)); check_kinds!(a, "Cannot offset non-pointer type {:?}", ty::RawPtr(..));
if b != self.tcx.types.isize && b != self.tcx.types.usize { if b != self.tcx.types.isize && b != self.tcx.types.usize {
self.fail(location, format!("Cannot offset by non-isize type {b:?}")); self.fail(location, format!("Cannot offset by non-isize type {b}"));
} }
} }
Eq | Lt | Le | Ne | Ge | Gt => { Eq | Lt | Le | Ne | Ge | Gt => {
@ -1313,7 +1315,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
{ {
self.fail( self.fail(
location, location,
format!("Cannot transmute from non-`Sized` type {op_ty:?}"), format!("Cannot transmute from non-`Sized` type {op_ty}"),
); );
} }
if !self if !self
@ -1340,7 +1342,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
} }
Rvalue::NullaryOp(NullOp::OffsetOf(indices), container) => { Rvalue::NullaryOp(NullOp::OffsetOf(indices), container) => {
let fail_out_of_bounds = |this: &mut Self, location, field, ty| { let fail_out_of_bounds = |this: &mut Self, location, field, ty| {
this.fail(location, format!("Out of bounds field {field:?} for {ty:?}")); this.fail(location, format!("Out of bounds field {field:?} for {ty}"));
}; };
let mut current_ty = *container; let mut current_ty = *container;
@ -1374,7 +1376,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
_ => { _ => {
self.fail( self.fail(
location, location,
format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty:?}"), format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty}"),
); );
return; return;
} }
@ -1403,7 +1405,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if !self.mir_assign_valid_types(unwrapped_ty, binder_inner_ty) { if !self.mir_assign_valid_types(unwrapped_ty, binder_inner_ty) {
self.fail( self.fail(
location, location,
format!("Cannot wrap {unwrapped_ty:?} into unsafe binder {binder_ty:?}"), format!("Cannot wrap {unwrapped_ty} into unsafe binder {binder_ty:?}"),
); );
} }
} }
@ -1489,24 +1491,27 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// since CopyNonOverlapping is parametrized by 1 type, // since CopyNonOverlapping is parametrized by 1 type,
// we only need to check that they are equal and not keep an extra parameter. // we only need to check that they are equal and not keep an extra parameter.
if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) { if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) {
self.fail(location, format!("bad arg ({op_src_ty:?} != {op_dst_ty:?})")); self.fail(location, format!("bad arg ({op_src_ty} != {op_dst_ty})"));
} }
let op_cnt_ty = count.ty(&self.body.local_decls, self.tcx); let op_cnt_ty = count.ty(&self.body.local_decls, self.tcx);
if op_cnt_ty != self.tcx.types.usize { if op_cnt_ty != self.tcx.types.usize {
self.fail(location, format!("bad arg ({op_cnt_ty:?} != usize)")) self.fail(location, format!("bad arg ({op_cnt_ty} != usize)"))
} }
} }
StatementKind::SetDiscriminant { place, .. } => { StatementKind::SetDiscriminant { place, .. } => {
if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) { if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location, "`SetDiscriminant`is not allowed until deaggregation"); self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
} }
let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind(); let pty = place.ty(&self.body.local_decls, self.tcx).ty;
if !matches!(pty, ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..)) { if !matches!(
pty.kind(),
ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..)
) {
self.fail( self.fail(
location, location,
format!( format!(
"`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty:?}" "`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty}"
), ),
); );
} }
@ -1555,7 +1560,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
if ScalarInt::try_from_uint(value, size).is_none() { if ScalarInt::try_from_uint(value, size).is_none() {
self.fail( self.fail(
location, location,
format!("the value {value:#x} is not a proper {switch_ty:?}"), format!("the value {value:#x} is not a proper {switch_ty}"),
) )
} }
} }

View File

@ -118,7 +118,7 @@ pub fn edit_distance_with_substrings(a: &str, b: &str, limit: usize) -> Option<u
// Check one isn't less than half the length of the other. If this is true then there is a // Check one isn't less than half the length of the other. If this is true then there is a
// big difference in length. // big difference in length.
let big_len_diff = (n * 2) < m || (m * 2) < n; let big_len_diff = (n * 2) < m || (m * 2) < n;
let len_diff = if n < m { m - n } else { n - m }; let len_diff = m.abs_diff(n);
let distance = edit_distance(a, b, limit + len_diff)?; let distance = edit_distance(a, b, limit + len_diff)?;
// This is the crux, subtracting length difference means exact substring matches will now be 0 // This is the crux, subtracting length difference means exact substring matches will now be 0

View File

@ -74,7 +74,6 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
let ours; let ours;
let mut name; let mut name;
let mut tries = 0; let mut tries = 0;
let mut reject_remote_clients_flag = c::PIPE_REJECT_REMOTE_CLIENTS;
loop { loop {
tries += 1; tries += 1;
name = format!( name = format!(
@ -96,7 +95,7 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
c::PIPE_TYPE_BYTE c::PIPE_TYPE_BYTE
| c::PIPE_READMODE_BYTE | c::PIPE_READMODE_BYTE
| c::PIPE_WAIT | c::PIPE_WAIT
| reject_remote_clients_flag, | c::PIPE_REJECT_REMOTE_CLIENTS,
1, 1,
PIPE_BUFFER_CAPACITY, PIPE_BUFFER_CAPACITY,
PIPE_BUFFER_CAPACITY, PIPE_BUFFER_CAPACITY,
@ -112,30 +111,15 @@ pub fn anon_pipe(ours_readable: bool, their_handle_inheritable: bool) -> io::Res
// //
// Don't try again too much though as this could also perhaps be a // Don't try again too much though as this could also perhaps be a
// legit error. // legit error.
// If `ERROR_INVALID_PARAMETER` is returned, this probably means we're
// running on pre-Vista version where `PIPE_REJECT_REMOTE_CLIENTS` is
// not supported, so we continue retrying without it. This implies
// reduced security on Windows versions older than Vista by allowing
// connections to this pipe from remote machines.
// Proper fix would increase the number of FFI imports and introduce
// significant amount of Windows XP specific code with no clean
// testing strategy
// For more info, see https://github.com/rust-lang/rust/pull/37677.
if handle == c::INVALID_HANDLE_VALUE { if handle == c::INVALID_HANDLE_VALUE {
let error = api::get_last_error(); let error = api::get_last_error();
if tries < 10 { if tries < 10 && error == WinError::ACCESS_DENIED {
if error == WinError::ACCESS_DENIED {
continue; continue;
} else if reject_remote_clients_flag != 0 } else {
&& error == WinError::INVALID_PARAMETER
{
reject_remote_clients_flag = 0;
tries -= 1;
continue;
}
}
return Err(io::Error::from_raw_os_error(error.code as i32)); return Err(io::Error::from_raw_os_error(error.code as i32));
} }
}
ours = Handle::from_raw_handle(handle); ours = Handle::from_raw_handle(handle);
break; break;
} }

View File

@ -70,4 +70,5 @@ the `-mmacosx-version-min=...`, `-miphoneos-version-min=...` or similar flags
to disambiguate. to disambiguate.
The path to the SDK can be passed to `rustc` using the common `SDKROOT` The path to the SDK can be passed to `rustc` using the common `SDKROOT`
environment variable. environment variable, or will be inferred when compiling on host macOS using
roughly the same logic as `xcrun --sdk macosx --show-sdk-path`.

View File

@ -20,7 +20,8 @@ These targets are cross-compiled, and require the corresponding macOS SDK
iOS-specific headers, as provided by Xcode 11 or higher. iOS-specific headers, as provided by Xcode 11 or higher.
The path to the SDK can be passed to `rustc` using the common `SDKROOT` The path to the SDK can be passed to `rustc` using the common `SDKROOT`
environment variable. environment variable, or will be inferred when compiling on host macOS using
roughly the same logic as `xcrun --sdk macosx --show-sdk-path`.
### OS version ### OS version

View File

@ -26,7 +26,8 @@ These targets are cross-compiled, and require the corresponding iOS SDK
ARM64 targets, Xcode 12 or higher is required. ARM64 targets, Xcode 12 or higher is required.
The path to the SDK can be passed to `rustc` using the common `SDKROOT` The path to the SDK can be passed to `rustc` using the common `SDKROOT`
environment variable. environment variable, or will be inferred when compiling on host macOS using
roughly the same logic as `xcrun --sdk iphoneos --show-sdk-path`.
### OS version ### OS version

View File

@ -20,7 +20,8 @@ These targets are cross-compiled, and require the corresponding tvOS SDK
ARM64 targets, Xcode 12 or higher is required. ARM64 targets, Xcode 12 or higher is required.
The path to the SDK can be passed to `rustc` using the common `SDKROOT` The path to the SDK can be passed to `rustc` using the common `SDKROOT`
environment variable. environment variable, or will be inferred when compiling on host macOS using
roughly the same logic as `xcrun --sdk appletvos --show-sdk-path`.
### OS version ### OS version

View File

@ -18,7 +18,8 @@ These targets are cross-compiled, and require the corresponding visionOS SDK
(`XROS.sdk` or `XRSimulator.sdk`), as provided by Xcode 15 or newer. (`XROS.sdk` or `XRSimulator.sdk`), as provided by Xcode 15 or newer.
The path to the SDK can be passed to `rustc` using the common `SDKROOT` The path to the SDK can be passed to `rustc` using the common `SDKROOT`
environment variable. environment variable, or will be inferred when compiling on host macOS using
roughly the same logic as `xcrun --sdk xros --show-sdk-path`.
### OS version ### OS version

View File

@ -24,7 +24,8 @@ These targets are cross-compiled, and require the corresponding watchOS SDK
ARM64 targets, Xcode 12 or higher is required. ARM64 targets, Xcode 12 or higher is required.
The path to the SDK can be passed to `rustc` using the common `SDKROOT` The path to the SDK can be passed to `rustc` using the common `SDKROOT`
environment variable. environment variable, or will be inferred when compiling on host macOS using
roughly the same logic as `xcrun --sdk watchos --show-sdk-path`.
### OS version ### OS version

View File

@ -0,0 +1,36 @@
//@ build-pass
//@ compile-flags: -Zinline-mir
trait Storage {
type Buffer: ?Sized;
}
struct Array<const N: usize>;
impl<const N: usize> Storage for Array<N> {
type Buffer = [(); N];
}
struct Slice;
impl Storage for Slice {
type Buffer = [()];
}
struct Wrap<S: Storage> {
_b: S::Buffer,
}
fn coerce<const N: usize>(this: &Wrap<Array<N>>) -> &Wrap<Slice>
where
Array<N>: Storage,
{
coerce_again(this)
}
fn coerce_again<const N: usize>(this: &Wrap<Array<N>>) -> &Wrap<Slice> {
this
}
fn main() {
let inner: Wrap<Array<1>> = Wrap { _b: [(); 1] };
let _: &Wrap<Slice> = coerce(&inner);
}

View File

@ -10,9 +10,16 @@
// Ref: https://github.com/rust-lang/rust/issues/102246 // Ref: https://github.com/rust-lang/rust/issues/102246
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use std::thread; use std::thread::Builder;
const N: usize = 32_768; const N: usize = 32_768;
const SLOTS: usize = 32;
// Use a stack size that's smaller than N * SLOTS, proving the allocation is on the heap.
//
// The test explicitly specifies the stack size, because not all platforms have the same default
// size.
const STACK_SIZE: usize = (N*SLOTS) - 1;
struct BigStruct { struct BigStruct {
_data: [u8; N], _data: [u8; N],
} }
@ -20,10 +27,13 @@ struct BigStruct {
fn main() { fn main() {
let (sender, receiver) = channel::<BigStruct>(); let (sender, receiver) = channel::<BigStruct>();
let thread1 = thread::spawn(move || { let thread1 = Builder::new().stack_size(STACK_SIZE).spawn(move || {
sender.send(BigStruct { _data: [0u8; N] }).unwrap(); sender.send(BigStruct { _data: [0u8; N] }).unwrap();
}); }).expect("thread1 should spawn successfully");
thread1.join().unwrap(); thread1.join().unwrap();
let thread2 = Builder::new().stack_size(STACK_SIZE).spawn(move || {
for _data in receiver.try_iter() {} for _data in receiver.try_iter() {}
}).expect("thread2 should spawn successfully");
thread2.join().unwrap();
} }

View File

@ -1098,6 +1098,7 @@ contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
users_on_vacation = [ users_on_vacation = [
"jyn514", "jyn514",
"ChrisDenton", "ChrisDenton",
"saethlin",
] ]
[[assign.warn_non_default_branch.exceptions]] [[assign.warn_non_default_branch.exceptions]]