diff --git a/RELEASES.md b/RELEASES.md
index 74b0d4424c163..b14cc499b46d0 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,11 @@
+Version 1.91.1 (2025-11-10)
+===========================
+
+
+
+- [Enable file locking support in illumos](https://github.com/rust-lang/rust/pull/148322). This fixes Cargo not locking the build directory on illumos.
+- [Fix `wasm_import_module` attribute cross-crate](https://github.com/rust-lang/rust/pull/148363). This fixes linker errors on WASM targets.
+
Version 1.91.0 (2025-10-30)
==========================
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 5e498bf98fb55..c9dd92ff2f243 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -156,6 +156,7 @@ builtin_macros_duplicate_macro_attribute = duplicated attribute
builtin_macros_env_not_defined = environment variable `{$var}` not defined at compile time
.cargo = Cargo sets build script variables at run time. Use `std::env::var({$var_expr})` instead
+ .cargo_typo = there is a similar Cargo environment variable: `{$suggested_var}`
.custom = use `std::env::var({$var_expr})` to read the variable at run time
builtin_macros_env_not_unicode = environment variable `{$var}` is not a valid Unicode string
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index f3ac932e1b7e9..af78db156a221 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -10,6 +10,7 @@ use rustc_ast::token::{self, LitKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{ExprKind, GenericArg, Mutability};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult};
+use rustc_span::edit_distance::edit_distance;
use rustc_span::{Ident, Span, Symbol, kw, sym};
use thin_vec::thin_vec;
@@ -144,6 +145,12 @@ pub(crate) fn expand_env<'cx>(
if let Some(msg_from_user) = custom_msg {
cx.dcx()
.emit_err(errors::EnvNotDefinedWithUserMessage { span, msg_from_user })
+ } else if let Some(suggested_var) = find_similar_cargo_var(var.as_str()) {
+ cx.dcx().emit_err(errors::EnvNotDefined::CargoEnvVarTypo {
+ span,
+ var: *symbol,
+ suggested_var: Symbol::intern(suggested_var),
+ })
} else if is_cargo_env_var(var.as_str()) {
cx.dcx().emit_err(errors::EnvNotDefined::CargoEnvVar {
span,
@@ -176,3 +183,49 @@ fn is_cargo_env_var(var: &str) -> bool {
|| var.starts_with("DEP_")
|| matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
}
+
+const KNOWN_CARGO_VARS: &[&str] = &[
+ // List of known Cargo environment variables that are set for crates (not build scripts, OUT_DIR etc).
+ // See: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates
+ "CARGO_PKG_VERSION",
+ "CARGO_PKG_VERSION_MAJOR",
+ "CARGO_PKG_VERSION_MINOR",
+ "CARGO_PKG_VERSION_PATCH",
+ "CARGO_PKG_VERSION_PRE",
+ "CARGO_PKG_AUTHORS",
+ "CARGO_PKG_NAME",
+ "CARGO_PKG_DESCRIPTION",
+ "CARGO_PKG_HOMEPAGE",
+ "CARGO_PKG_REPOSITORY",
+ "CARGO_PKG_LICENSE",
+ "CARGO_PKG_LICENSE_FILE",
+ "CARGO_PKG_RUST_VERSION",
+ "CARGO_PKG_README",
+ "CARGO_MANIFEST_DIR",
+ "CARGO_MANIFEST_PATH",
+ "CARGO_CRATE_NAME",
+ "CARGO_BIN_NAME",
+ "CARGO_PRIMARY_PACKAGE",
+];
+
+fn find_similar_cargo_var(var: &str) -> Option<&'static str> {
+ if !var.starts_with("CARGO_") {
+ return None;
+ }
+
+ let lookup_len = var.chars().count();
+ let max_dist = std::cmp::max(lookup_len, 3) / 3;
+ let mut best_match = None;
+ let mut best_distance = usize::MAX;
+
+ for &known_var in KNOWN_CARGO_VARS {
+ if let Some(distance) = edit_distance(var, known_var, max_dist) {
+ if distance < best_distance {
+ best_distance = distance;
+ best_match = Some(known_var);
+ }
+ }
+ }
+
+ best_match
+}
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index d6ffbb5a4101d..dd6a5a20ccebc 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -535,6 +535,14 @@ pub(crate) enum EnvNotDefined<'a> {
var_expr: &'a rustc_ast::Expr,
},
#[diag(builtin_macros_env_not_defined)]
+ #[help(builtin_macros_cargo_typo)]
+ CargoEnvVarTypo {
+ #[primary_span]
+ span: Span,
+ var: Symbol,
+ suggested_var: Symbol,
+ },
+ #[diag(builtin_macros_env_not_defined)]
#[help(builtin_macros_custom)]
CustomEnvVar {
#[primary_span]
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 02b50fa8a6971..b820b992105fd 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -616,7 +616,8 @@ pub(crate) fn run_pass_manager(
write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage);
}
- if enable_gpu && !thin {
+ // Here we only handle the GPU host (=cpu) code.
+ if enable_gpu && !thin && !cgcx.target_is_like_gpu {
let cx =
SimpleCx::new(module.module_llvm.llmod(), &module.module_llvm.llcx, cgcx.pointer_size);
crate::builder::gpu_offload::handle_gpu_code(cgcx, &cx);
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index b582d587d9f8a..5b71d6b6ba8e0 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -43,7 +43,7 @@ use crate::errors::{
use crate::llvm::diagnostic::OptimizationDiagnosticKind::*;
use crate::llvm::{self, DiagnosticInfo};
use crate::type_::llvm_type_ptr;
-use crate::{LlvmCodegenBackend, ModuleLlvm, base, common, llvm_util};
+use crate::{LlvmCodegenBackend, ModuleLlvm, SimpleCx, base, common, llvm_util};
pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> ! {
match llvm::last_error() {
@@ -645,6 +645,74 @@ pub(crate) unsafe fn llvm_optimize(
None
};
+ fn handle_offload<'ll>(cx: &'ll SimpleCx<'_>, old_fn: &llvm::Value) {
+ let old_fn_ty = cx.get_type_of_global(old_fn);
+ let old_param_types = cx.func_params_types(old_fn_ty);
+ let old_param_count = old_param_types.len();
+ if old_param_count == 0 {
+ return;
+ }
+
+ let first_param = llvm::get_param(old_fn, 0);
+ let c_name = llvm::get_value_name(first_param);
+ let first_arg_name = str::from_utf8(&c_name).unwrap();
+ // We might call llvm_optimize (and thus this code) multiple times on the same IR,
+ // but we shouldn't add this helper ptr multiple times.
+ // FIXME(offload): This could break if the user calls his first argument `dyn_ptr`.
+ if first_arg_name == "dyn_ptr" {
+ return;
+ }
+
+ // Create the new parameter list, with ptr as the first argument
+ let mut new_param_types = Vec::with_capacity(old_param_count as usize + 1);
+ new_param_types.push(cx.type_ptr());
+ new_param_types.extend(old_param_types);
+
+ // Create the new function type
+ let ret_ty = unsafe { llvm::LLVMGetReturnType(old_fn_ty) };
+ let new_fn_ty = cx.type_func(&new_param_types, ret_ty);
+
+ // Create the new function, with a temporary .offload name to avoid a name collision.
+ let old_fn_name = String::from_utf8(llvm::get_value_name(old_fn)).unwrap();
+ let new_fn_name = format!("{}.offload", &old_fn_name);
+ let new_fn = cx.add_func(&new_fn_name, new_fn_ty);
+ let a0 = llvm::get_param(new_fn, 0);
+ llvm::set_value_name(a0, CString::new("dyn_ptr").unwrap().as_bytes());
+
+ // Here we map the old arguments to the new arguments, with an offset of 1 to make sure
+ // that we don't use the newly added `%dyn_ptr`.
+ unsafe {
+ llvm::LLVMRustOffloadMapper(cx.llmod(), old_fn, new_fn);
+ }
+
+ llvm::set_linkage(new_fn, llvm::get_linkage(old_fn));
+ llvm::set_visibility(new_fn, llvm::get_visibility(old_fn));
+
+ // Replace all uses of old_fn with new_fn (RAUW)
+ unsafe {
+ llvm::LLVMReplaceAllUsesWith(old_fn, new_fn);
+ }
+ let name = llvm::get_value_name(old_fn);
+ unsafe {
+ llvm::LLVMDeleteFunction(old_fn);
+ }
+ // Now we can re-use the old name, without name collision.
+ llvm::set_value_name(new_fn, &name);
+ }
+
+ if cgcx.target_is_like_gpu && config.offload.contains(&config::Offload::Enable) {
+ let cx =
+ SimpleCx::new(module.module_llvm.llmod(), module.module_llvm.llcx, cgcx.pointer_size);
+ // For now we only support up to 10 kernels named kernel_0 ... kernel_9, a follow-up PR is
+ // introducing a proper offload intrinsic to solve this limitation.
+ for num in 0..9 {
+ let name = format!("kernel_{num}");
+ if let Some(kernel) = cx.get_function(&name) {
+ handle_offload(&cx, kernel);
+ }
+ }
+ }
+
let mut llvm_profiler = cgcx
.prof
.llvm_recording_enabled()
diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
index 3d55064ea1304..5c2f8f700627e 100644
--- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
@@ -19,6 +19,9 @@ pub(crate) fn handle_gpu_code<'ll>(
let mut memtransfer_types = vec![];
let mut region_ids = vec![];
let offload_entry_ty = TgtOffloadEntry::new_decl(&cx);
+ // This is a temporary hack, we only search for kernel_0 to kernel_9 functions.
+ // There is a draft PR in progress which will introduce a proper offload intrinsic to remove
+ // this limitation.
for num in 0..9 {
let kernel = cx.get_function(&format!("kernel_{num}"));
if let Some(kernel) = kernel {
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 9a391d57d6fb4..74d268ad5dd2e 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1127,6 +1127,11 @@ unsafe extern "C" {
// Operations on functions
pub(crate) fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint);
+ pub(crate) fn LLVMAddFunction<'a>(
+ Mod: &'a Module,
+ Name: *const c_char,
+ FunctionTy: &'a Type,
+ ) -> &'a Value;
pub(crate) fn LLVMDeleteFunction(Fn: &Value);
// Operations about llvm intrinsics
@@ -2017,6 +2022,7 @@ unsafe extern "C" {
) -> &Attribute;
// Operations on functions
+ pub(crate) fn LLVMRustOffloadMapper<'a>(M: &'a Module, Fn: &'a Value, Fn: &'a Value);
pub(crate) fn LLVMRustGetOrInsertFunction<'a>(
M: &'a Module,
Name: *const c_char,
diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs
index 81bb70c958790..55f053f4fad3f 100644
--- a/compiler/rustc_codegen_llvm/src/type_.rs
+++ b/compiler/rustc_codegen_llvm/src/type_.rs
@@ -68,6 +68,11 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> {
unsafe { llvm::LLVMVectorType(ty, len as c_uint) }
}
+ pub(crate) fn add_func(&self, name: &str, ty: &'ll Type) -> &'ll Value {
+ let name = SmallCStr::new(name);
+ unsafe { llvm::LLVMAddFunction(self.llmod(), name.as_ptr(), ty) }
+ }
+
pub(crate) fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> {
unsafe {
let n_args = llvm::LLVMCountParamTypes(ty) as usize;
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index c1e80e08a0eb4..fc1edec8de843 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -342,6 +342,7 @@ pub struct CodegenContext {
pub target_arch: String,
pub target_is_like_darwin: bool,
pub target_is_like_aix: bool,
+ pub target_is_like_gpu: bool,
pub split_debuginfo: rustc_target::spec::SplitDebuginfo,
pub split_dwarf_kind: rustc_session::config::SplitDwarfKind,
pub pointer_size: Size,
@@ -1309,6 +1310,7 @@ fn start_executing_work(
target_arch: tcx.sess.target.arch.to_string(),
target_is_like_darwin: tcx.sess.target.is_like_darwin,
target_is_like_aix: tcx.sess.target.is_like_aix,
+ target_is_like_gpu: tcx.sess.target.is_like_gpu,
split_debuginfo: tcx.sess.split_debuginfo(),
split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 78b16ffee81cf..e533ee78cc824 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -77,6 +77,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
false
};
+
+ // Special case: range expressions are desugared to struct literals in HIR,
+ // so they would normally return `Unambiguous` precedence in expr.precedence.
+ // we should return `Range` precedence for correct parenthesization in suggestions.
+ if is_range_literal(expr) {
+ return ExprPrecedence::Range;
+ }
+
expr.precedence(&has_attr)
}
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 2d87ea232eea2..df811ddd8d4fc 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -35,6 +35,8 @@
#include "llvm/Support/Signals.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/ValueMapper.h"
#include
// for raw `write` in the bad-alloc handler
@@ -142,6 +144,28 @@ extern "C" void LLVMRustPrintStatistics(RustStringRef OutBuf) {
llvm::PrintStatistics(OS);
}
+extern "C" void LLVMRustOffloadMapper(LLVMModuleRef M, LLVMValueRef OldFn,
+ LLVMValueRef NewFn) {
+ llvm::Module *module = llvm::unwrap(M);
+ llvm::Function *oldFn = llvm::unwrap(OldFn);
+ llvm::Function *newFn = llvm::unwrap(NewFn);
+
+ // Map old arguments to new arguments. We skip the first dyn_ptr argument,
+ // since it can't be used directly by user code.
+ llvm::ValueToValueMapTy vmap;
+ auto newArgIt = newFn->arg_begin();
+ newArgIt->setName("dyn_ptr");
+ ++newArgIt; // skip %dyn_ptr
+ for (auto &oldArg : oldFn->args()) {
+ vmap[&oldArg] = &*newArgIt++;
+ }
+
+ llvm::SmallVector returns;
+ llvm::CloneFunctionInto(newFn, oldFn, vmap,
+ llvm::CloneFunctionChangeType::LocalChangesOnly,
+ returns);
+}
+
extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
size_t NameLen) {
return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
diff --git a/compiler/rustc_query_system/src/dep_graph/README.md b/compiler/rustc_query_system/src/dep_graph/README.md
index b9d91cd35a8dd..3dd107f2feabe 100644
--- a/compiler/rustc_query_system/src/dep_graph/README.md
+++ b/compiler/rustc_query_system/src/dep_graph/README.md
@@ -1,4 +1,3 @@
-To learn more about how dependency tracking works in rustc, see the [rustc
-guide].
+To learn more about how dependency tracking works in rustc, see the [rustc dev guide].
[rustc dev guide]: https://rustc-dev-guide.rust-lang.org/query.html
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 43e1ca3ef9cee..147b17b24bb57 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -578,6 +578,7 @@ impl RiscvInterruptKind {
///
/// The signature represented by this type may not match the MIR function signature.
/// Certain attributes, like `#[track_caller]` can introduce additional arguments, which are present in [`FnAbi`], but not in `FnSig`.
+/// The std::offload module also adds an addition dyn_ptr argument to the GpuKernel ABI.
/// While this difference is rarely relevant, it should still be kept in mind.
///
/// I will do my best to describe this structure, but these
diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs
index 9f9c8d5221df2..ab2879f6c6ea8 100644
--- a/compiler/rustc_target/src/spec/json.rs
+++ b/compiler/rustc_target/src/spec/json.rs
@@ -147,6 +147,7 @@ impl Target {
forward!(is_like_darwin);
forward!(is_like_solaris);
forward!(is_like_windows);
+ forward!(is_like_gpu);
forward!(is_like_msvc);
forward!(is_like_wasm);
forward!(is_like_android);
@@ -342,6 +343,7 @@ impl ToJson for Target {
target_option_val!(is_like_darwin);
target_option_val!(is_like_solaris);
target_option_val!(is_like_windows);
+ target_option_val!(is_like_gpu);
target_option_val!(is_like_msvc);
target_option_val!(is_like_wasm);
target_option_val!(is_like_android);
@@ -562,6 +564,7 @@ struct TargetSpecJson {
is_like_darwin: Option,
is_like_solaris: Option,
is_like_windows: Option,
+ is_like_gpu: Option,
is_like_msvc: Option,
is_like_wasm: Option,
is_like_android: Option,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 023c62812c865..dd565c3b666f2 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2180,6 +2180,8 @@ pub struct TargetOptions {
/// Also indicates whether to use Apple-specific ABI changes, such as extending function
/// parameters to 32-bits.
pub is_like_darwin: bool,
+ /// Whether the target is a GPU (e.g. NVIDIA, AMD, Intel).
+ pub is_like_gpu: bool,
/// Whether the target toolchain is like Solaris's.
/// Only useful for compiling against Illumos/Solaris,
/// as they have a different set of linker flags. Defaults to false.
@@ -2590,6 +2592,7 @@ impl Default for TargetOptions {
abi_return_struct_as_int: false,
is_like_aix: false,
is_like_darwin: false,
+ is_like_gpu: false,
is_like_solaris: false,
is_like_windows: false,
is_like_msvc: false,
@@ -2756,6 +2759,11 @@ impl Target {
self.os == "solaris" || self.os == "illumos",
"`is_like_solaris` must be set if and only if `os` is `solaris` or `illumos`"
);
+ check_eq!(
+ self.is_like_gpu,
+ self.arch == Arch::Nvptx64 || self.arch == Arch::AmdGpu,
+ "`is_like_gpu` must be set if and only if `target` is `nvptx64` or `amdgcn`"
+ );
check_eq!(
self.is_like_windows,
self.os == "windows" || self.os == "uefi" || self.os == "cygwin",
diff --git a/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs b/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
index 07772c7573377..d80a3ffd0c7fd 100644
--- a/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
+++ b/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
@@ -34,6 +34,9 @@ pub(crate) fn target() -> Target {
no_builtins: true,
simd_types_indirect: false,
+ // Clearly a GPU
+ is_like_gpu: true,
+
// Allow `cdylib` crate type.
dynamic_linking: true,
only_cdylib: true,
diff --git a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
index ac2d31a0d61aa..5bbf40b5fadd7 100644
--- a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
+++ b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
@@ -42,6 +42,9 @@ pub(crate) fn target() -> Target {
// Let the `ptx-linker` to handle LLVM lowering into MC / assembly.
obj_is_bitcode: true,
+ // Clearly a GPU
+ is_like_gpu: true,
+
// Convenient and predicable naming scheme.
dll_prefix: "".into(),
dll_suffix: ".ptx".into(),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index cd0dbb4d87f99..1094f00e42f29 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -937,6 +937,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
err.span_label(block.span, "this empty block is missing a tail expression");
return;
};
+ // FIXME expr and stmt have the same span if expr comes from expansion
+ // cc: https://github.com/rust-lang/rust/pull/147416#discussion_r2499407523
+ if stmt.span.from_expansion() {
+ return;
+ }
let hir::StmtKind::Semi(tail_expr) = stmt.kind else {
return;
};
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 6e6996bcbd69b..cb3e14252f8a3 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -427,39 +427,35 @@ impl BTreeSet {
where
T: Ord,
{
- let (self_min, self_max) =
- if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) {
- (self_min, self_max)
- } else {
- return Difference { inner: DifferenceInner::Iterate(self.iter()) };
- };
- let (other_min, other_max) =
- if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) {
- (other_min, other_max)
- } else {
- return Difference { inner: DifferenceInner::Iterate(self.iter()) };
- };
- Difference {
- inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) {
- (Greater, _) | (_, Less) => DifferenceInner::Iterate(self.iter()),
- (Equal, _) => {
- let mut self_iter = self.iter();
- self_iter.next();
- DifferenceInner::Iterate(self_iter)
- }
- (_, Equal) => {
- let mut self_iter = self.iter();
- self_iter.next_back();
- DifferenceInner::Iterate(self_iter)
- }
- _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
- DifferenceInner::Search { self_iter: self.iter(), other_set: other }
- }
- _ => DifferenceInner::Stitch {
- self_iter: self.iter(),
- other_iter: other.iter().peekable(),
+ if let Some(self_min) = self.first()
+ && let Some(self_max) = self.last()
+ && let Some(other_min) = other.first()
+ && let Some(other_max) = other.last()
+ {
+ Difference {
+ inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) {
+ (Greater, _) | (_, Less) => DifferenceInner::Iterate(self.iter()),
+ (Equal, _) => {
+ let mut self_iter = self.iter();
+ self_iter.next();
+ DifferenceInner::Iterate(self_iter)
+ }
+ (_, Equal) => {
+ let mut self_iter = self.iter();
+ self_iter.next_back();
+ DifferenceInner::Iterate(self_iter)
+ }
+ _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
+ DifferenceInner::Search { self_iter: self.iter(), other_set: other }
+ }
+ _ => DifferenceInner::Stitch {
+ self_iter: self.iter(),
+ other_iter: other.iter().peekable(),
+ },
},
- },
+ }
+ } else {
+ Difference { inner: DifferenceInner::Iterate(self.iter()) }
}
}
@@ -519,31 +515,27 @@ impl BTreeSet {
where
T: Ord,
{
- let (self_min, self_max) =
- if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) {
- (self_min, self_max)
- } else {
- return Intersection { inner: IntersectionInner::Answer(None) };
- };
- let (other_min, other_max) =
- if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) {
- (other_min, other_max)
- } else {
- return Intersection { inner: IntersectionInner::Answer(None) };
- };
- Intersection {
- inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) {
- (Greater, _) | (_, Less) => IntersectionInner::Answer(None),
- (Equal, _) => IntersectionInner::Answer(Some(self_min)),
- (_, Equal) => IntersectionInner::Answer(Some(self_max)),
- _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
- IntersectionInner::Search { small_iter: self.iter(), large_set: other }
- }
- _ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
- IntersectionInner::Search { small_iter: other.iter(), large_set: self }
- }
- _ => IntersectionInner::Stitch { a: self.iter(), b: other.iter() },
- },
+ if let Some(self_min) = self.first()
+ && let Some(self_max) = self.last()
+ && let Some(other_min) = other.first()
+ && let Some(other_max) = other.last()
+ {
+ Intersection {
+ inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) {
+ (Greater, _) | (_, Less) => IntersectionInner::Answer(None),
+ (Equal, _) => IntersectionInner::Answer(Some(self_min)),
+ (_, Equal) => IntersectionInner::Answer(Some(self_max)),
+ _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
+ IntersectionInner::Search { small_iter: self.iter(), large_set: other }
+ }
+ _ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => {
+ IntersectionInner::Search { small_iter: other.iter(), large_set: self }
+ }
+ _ => IntersectionInner::Stitch { a: self.iter(), b: other.iter() },
+ },
+ }
+ } else {
+ Intersection { inner: IntersectionInner::Answer(None) }
}
}
@@ -694,55 +686,56 @@ impl BTreeSet {
// Same result as self.difference(other).next().is_none()
// but the code below is faster (hugely in some cases).
if self.len() > other.len() {
- return false;
+ return false; // self has more elements than other
}
- let (self_min, self_max) =
- if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) {
- (self_min, self_max)
- } else {
- return true; // self is empty
- };
- let (other_min, other_max) =
- if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) {
- (other_min, other_max)
- } else {
- return false; // other is empty
- };
+ let (Some(self_min), Some(self_max)) = (self.first(), self.last()) else {
+ return true; // self is empty
+ };
+ let (Some(other_min), Some(other_max)) = (other.first(), other.last()) else {
+ return false; // other is empty
+ };
let mut self_iter = self.iter();
match self_min.cmp(other_min) {
- Less => return false,
+ Less => return false, // other does not contain self_min
Equal => {
- self_iter.next();
+ self_iter.next(); // self_min is contained in other, so remove it from consideration
+ // other_min is now not in self_iter (used below)
}
- Greater => (),
- }
+ Greater => {} // other_min is not in self_iter (used below)
+ };
+
match self_max.cmp(other_max) {
- Greater => return false,
+ Greater => return false, // other does not contain self_max
Equal => {
- self_iter.next_back();
+ self_iter.next_back(); // self_max is contained in other, so remove it from consideration
+ // other_max is now not in self_iter (used below)
}
- Less => (),
- }
+ Less => {} // other_max is not in self_iter (used below)
+ };
if self_iter.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF {
- for next in self_iter {
- if !other.contains(next) {
- return false;
- }
- }
+ self_iter.all(|e| other.contains(e))
} else {
let mut other_iter = other.iter();
- other_iter.next();
- other_iter.next_back();
- let mut self_next = self_iter.next();
- while let Some(self1) = self_next {
- match other_iter.next().map_or(Less, |other1| self1.cmp(other1)) {
- Less => return false,
- Equal => self_next = self_iter.next(),
- Greater => (),
- }
+ {
+ // remove other_min and other_max as they are not in self_iter (see above)
+ other_iter.next();
+ other_iter.next_back();
}
+ // custom `self_iter.all(|e| other.contains(e))`
+ self_iter.all(|self1| {
+ while let Some(other1) = other_iter.next() {
+ match other1.cmp(self1) {
+ // happens up to `ITER_PERFORMANCE_TIPPING_SIZE_DIFF * self.len() - 1` times
+ Less => continue, // skip over elements that are smaller
+ // happens `self.len()` times
+ Equal => return true, // self1 is in other
+ // happens only once
+ Greater => return false, // self1 is not in other
+ }
+ }
+ false
+ })
}
- true
}
/// Returns `true` if the set is a superset of another,
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index a85c874d54de1..1d4b3b558c010 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -2041,7 +2041,6 @@ impl VecDeque {
/// # Examples
///
/// ```
- /// #![feature(vec_deque_pop_if)]
/// use std::collections::VecDeque;
///
/// let mut deque: VecDeque = vec![0, 1, 2, 3, 4].into();
@@ -2051,7 +2050,7 @@ impl VecDeque {
/// assert_eq!(deque, [1, 2, 3, 4]);
/// assert_eq!(deque.pop_front_if(pred), None);
/// ```
- #[unstable(feature = "vec_deque_pop_if", issue = "135889")]
+ #[stable(feature = "vec_deque_pop_if", since = "CURRENT_RUSTC_VERSION")]
pub fn pop_front_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option {
let first = self.front_mut()?;
if predicate(first) { self.pop_front() } else { None }
@@ -2064,7 +2063,6 @@ impl VecDeque {
/// # Examples
///
/// ```
- /// #![feature(vec_deque_pop_if)]
/// use std::collections::VecDeque;
///
/// let mut deque: VecDeque = vec![0, 1, 2, 3, 4].into();
@@ -2074,10 +2072,10 @@ impl VecDeque {
/// assert_eq!(deque, [0, 1, 2, 3]);
/// assert_eq!(deque.pop_back_if(pred), None);
/// ```
- #[unstable(feature = "vec_deque_pop_if", issue = "135889")]
+ #[stable(feature = "vec_deque_pop_if", since = "CURRENT_RUSTC_VERSION")]
pub fn pop_back_if(&mut self, predicate: impl FnOnce(&mut T) -> bool) -> Option {
- let first = self.back_mut()?;
- if predicate(first) { self.pop_back() } else { None }
+ let last = self.back_mut()?;
+ if predicate(last) { self.pop_back() } else { None }
}
/// Prepends an element to the deque.
diff --git a/library/alloctests/Cargo.toml b/library/alloctests/Cargo.toml
index 07c45d1b82484..3b522bf80a217 100644
--- a/library/alloctests/Cargo.toml
+++ b/library/alloctests/Cargo.toml
@@ -6,7 +6,7 @@ repository = "https://github.com/rust-lang/rust.git"
description = "Tests for the Rust Allocation Library"
autotests = false
autobenches = false
-edition = "2021"
+edition = "2024"
[lib]
path = "lib.rs"
diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs
index c2649be0558a1..52124495f8c36 100644
--- a/library/alloctests/tests/lib.rs
+++ b/library/alloctests/tests/lib.rs
@@ -38,7 +38,6 @@
#![feature(str_as_str)]
#![feature(strict_provenance_lints)]
#![feature(string_replace_in_place)]
-#![feature(vec_deque_pop_if)]
#![feature(vec_deque_truncate_front)]
#![feature(unique_rc_arc)]
#![feature(macro_metavar_expr_concat)]
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 16f85c71403ab..7d395eb780346 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -217,10 +217,10 @@ macro_rules! int_impl {
/// ```
/// #![feature(int_lowest_highest_one)]
///
- #[doc = concat!("assert_eq!(0x0_", stringify!($SelfT), ".highest_one(), None);")]
- #[doc = concat!("assert_eq!(0x1_", stringify!($SelfT), ".highest_one(), Some(0));")]
- #[doc = concat!("assert_eq!(0x10_", stringify!($SelfT), ".highest_one(), Some(4));")]
- #[doc = concat!("assert_eq!(0x1f_", stringify!($SelfT), ".highest_one(), Some(4));")]
+ #[doc = concat!("assert_eq!(0b0_", stringify!($SelfT), ".highest_one(), None);")]
+ #[doc = concat!("assert_eq!(0b1_", stringify!($SelfT), ".highest_one(), Some(0));")]
+ #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".highest_one(), Some(4));")]
+ #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".highest_one(), Some(4));")]
/// ```
#[unstable(feature = "int_lowest_highest_one", issue = "145203")]
#[must_use = "this returns the result of the operation, \
@@ -238,10 +238,10 @@ macro_rules! int_impl {
/// ```
/// #![feature(int_lowest_highest_one)]
///
- #[doc = concat!("assert_eq!(0x0_", stringify!($SelfT), ".lowest_one(), None);")]
- #[doc = concat!("assert_eq!(0x1_", stringify!($SelfT), ".lowest_one(), Some(0));")]
- #[doc = concat!("assert_eq!(0x10_", stringify!($SelfT), ".lowest_one(), Some(4));")]
- #[doc = concat!("assert_eq!(0x1f_", stringify!($SelfT), ".lowest_one(), Some(0));")]
+ #[doc = concat!("assert_eq!(0b0_", stringify!($SelfT), ".lowest_one(), None);")]
+ #[doc = concat!("assert_eq!(0b1_", stringify!($SelfT), ".lowest_one(), Some(0));")]
+ #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".lowest_one(), Some(4));")]
+ #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".lowest_one(), Some(0));")]
/// ```
#[unstable(feature = "int_lowest_highest_one", issue = "145203")]
#[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index efb0665b7f461..92bca0eebfd93 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -708,9 +708,9 @@ macro_rules! nonzero_integer {
/// # use core::num::NonZero;
/// # fn main() { test().unwrap(); }
/// # fn test() -> Option<()> {
- #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0x1)?.highest_one(), 0);")]
- #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0x10)?.highest_one(), 4);")]
- #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0x1f)?.highest_one(), 4);")]
+ #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0b1)?.highest_one(), 0);")]
+ #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0b1_0000)?.highest_one(), 4);")]
+ #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0b1_1111)?.highest_one(), 4);")]
/// # Some(())
/// # }
/// ```
@@ -732,9 +732,9 @@ macro_rules! nonzero_integer {
/// # use core::num::NonZero;
/// # fn main() { test().unwrap(); }
/// # fn test() -> Option<()> {
- #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0x1)?.lowest_one(), 0);")]
- #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0x10)?.lowest_one(), 4);")]
- #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0x1f)?.lowest_one(), 0);")]
+ #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0b1)?.lowest_one(), 0);")]
+ #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0b1_0000)?.lowest_one(), 4);")]
+ #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(0b1_1111)?.lowest_one(), 0);")]
/// # Some(())
/// # }
/// ```
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 1efc551d670ab..2996e7b00da4e 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -272,10 +272,10 @@ macro_rules! uint_impl {
/// ```
/// #![feature(int_lowest_highest_one)]
///
- #[doc = concat!("assert_eq!(0x0_", stringify!($SelfT), ".highest_one(), None);")]
- #[doc = concat!("assert_eq!(0x1_", stringify!($SelfT), ".highest_one(), Some(0));")]
- #[doc = concat!("assert_eq!(0x10_", stringify!($SelfT), ".highest_one(), Some(4));")]
- #[doc = concat!("assert_eq!(0x1f_", stringify!($SelfT), ".highest_one(), Some(4));")]
+ #[doc = concat!("assert_eq!(0b0_", stringify!($SelfT), ".highest_one(), None);")]
+ #[doc = concat!("assert_eq!(0b1_", stringify!($SelfT), ".highest_one(), Some(0));")]
+ #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".highest_one(), Some(4));")]
+ #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".highest_one(), Some(4));")]
/// ```
#[unstable(feature = "int_lowest_highest_one", issue = "145203")]
#[must_use = "this returns the result of the operation, \
@@ -296,10 +296,10 @@ macro_rules! uint_impl {
/// ```
/// #![feature(int_lowest_highest_one)]
///
- #[doc = concat!("assert_eq!(0x0_", stringify!($SelfT), ".lowest_one(), None);")]
- #[doc = concat!("assert_eq!(0x1_", stringify!($SelfT), ".lowest_one(), Some(0));")]
- #[doc = concat!("assert_eq!(0x10_", stringify!($SelfT), ".lowest_one(), Some(4));")]
- #[doc = concat!("assert_eq!(0x1f_", stringify!($SelfT), ".lowest_one(), Some(0));")]
+ #[doc = concat!("assert_eq!(0b0_", stringify!($SelfT), ".lowest_one(), None);")]
+ #[doc = concat!("assert_eq!(0b1_", stringify!($SelfT), ".lowest_one(), Some(0));")]
+ #[doc = concat!("assert_eq!(0b1_0000_", stringify!($SelfT), ".lowest_one(), Some(4));")]
+ #[doc = concat!("assert_eq!(0b1_1111_", stringify!($SelfT), ".lowest_one(), Some(0));")]
/// ```
#[unstable(feature = "int_lowest_highest_one", issue = "145203")]
#[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 37dc401ed0098..45308c4b3e9c5 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -1953,6 +1953,7 @@ impl str {
///
/// ```
/// assert_eq!("cfg".rsplit_once('='), None);
+ /// assert_eq!("cfg=".rsplit_once('='), Some(("cfg", "")));
/// assert_eq!("cfg=foo".rsplit_once('='), Some(("cfg", "foo")));
/// assert_eq!("cfg=foo=bar".rsplit_once('='), Some(("cfg=foo", "bar")));
/// ```
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 30a42d4eb5e64..a3ceac89ef128 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -1558,6 +1558,8 @@ impl AtomicPtr {
/// Gets atomic access to a pointer.
///
+ /// **Note:** This function is only available on targets where `AtomicPtr` has the same alignment as `*const T`
+ ///
/// # Examples
///
/// ```
@@ -1625,6 +1627,8 @@ impl AtomicPtr {
/// Gets atomic access to a slice of pointers.
///
+ /// **Note:** This function is only available on targets where `AtomicPtr` has the same alignment as `*const T`
+ ///
/// # Examples
///
/// ```ignore-wasm
@@ -2804,6 +2808,14 @@ macro_rules! atomic_int {
#[doc = concat!("Get atomic access to a `&mut [", stringify!($int_type), "]` slice.")]
///
+ #[doc = if_8_bit! {
+ $int_type,
+ no = [
+ "**Note:** This function is only available on targets where `",
+ stringify!($atomic_type), "` has the same alignment as `", stringify!($int_type), "`."
+ ],
+ }]
+ ///
/// # Examples
///
/// ```ignore-wasm
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index 4b0080f1c80a4..380c774b143c6 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -587,7 +587,7 @@ Select which editor you would like to set up [default: None]: ";
"631c837b0e98ae35fd48b0e5f743b1ca60adadf2d0a2b23566ba25df372cf1a9",
"080955765db84bb6cbf178879f489c4e2369397626a6ecb3debedb94a9d0b3ce",
"f501475c6654187091c924ae26187fa5791d74d4a8ab3fb61fbbe4c0275aade1",
- "e260553b71e4773c30a63c4b23b42b279fc73e72f95b775c47b7b7c511c51595",
+ "54bc48fe1996177f5eef86d7231b33978e6d8b737cb0a899e622b7e975c95308",
],
EditorKind::Helix => &[
"2d3069b8cf1b977e5d4023965eb6199597755e6c96c185ed5f2854f98b83d233",
diff --git a/src/etc/rust_analyzer_eglot.el b/src/etc/rust_analyzer_eglot.el
index e5abf67235a5d..d33760007c325 100644
--- a/src/etc/rust_analyzer_eglot.el
+++ b/src/etc/rust_analyzer_eglot.el
@@ -28,7 +28,7 @@
"--build-dir"
"build-rust-analyzer"
"--json-output"
- "--compile-time-deps"])]
+ "--compile-time-deps"])
:sysrootSrc "./library"
:extraEnv (:RUSTC_BOOTSTRAP "1"))
:rustc ( :source "./Cargo.toml" )))))))
diff --git a/tests/ui/env-macro/env-cargo-var-typo-issue-148439.rs b/tests/ui/env-macro/env-cargo-var-typo-issue-148439.rs
new file mode 100644
index 0000000000000..f859decd09ecb
--- /dev/null
+++ b/tests/ui/env-macro/env-cargo-var-typo-issue-148439.rs
@@ -0,0 +1,50 @@
+//@ edition: 2021
+
+// Regression test for issue #148439
+// Ensure that when using misspelled Cargo environment variables in env!(),
+
+fn test_cargo_package_version() {
+ let _ = env!("CARGO_PACKAGE_VERSION");
+ //~^ ERROR environment variable `CARGO_PACKAGE_VERSION` not defined at compile time
+ //~| HELP there is a similar Cargo environment variable: `CARGO_PKG_VERSION`
+}
+
+fn test_cargo_package_name() {
+ let _ = env!("CARGO_PACKAGE_NAME");
+ //~^ ERROR environment variable `CARGO_PACKAGE_NAME` not defined at compile time
+ //~| HELP there is a similar Cargo environment variable: `CARGO_PKG_NAME`
+}
+
+fn test_cargo_package_authors() {
+ let _ = env!("CARGO_PACKAGE_AUTHORS");
+ //~^ ERROR environment variable `CARGO_PACKAGE_AUTHORS` not defined at compile time
+ //~| HELP there is a similar Cargo environment variable: `CARGO_PKG_AUTHORS`
+}
+
+fn test_cargo_manifest_directory() {
+ let _ = env!("CARGO_MANIFEST_DIRECTORY");
+ //~^ ERROR environment variable `CARGO_MANIFEST_DIRECTORY` not defined at compile time
+ //~| HELP there is a similar Cargo environment variable: `CARGO_MANIFEST_DIR`
+}
+
+fn test_cargo_pkg_version_typo() {
+ let _ = env!("CARGO_PKG_VERSIO");
+ //~^ ERROR environment variable `CARGO_PKG_VERSIO` not defined at compile time
+ //~| HELP there is a similar Cargo environment variable: `CARGO_PKG_VERSION`
+}
+
+fn test_non_cargo_var() {
+ // Non-Cargo variable should get different help message
+ let _ = env!("MY_CUSTOM_VAR");
+ //~^ ERROR environment variable `MY_CUSTOM_VAR` not defined at compile time
+ //~| HELP use `std::env::var("MY_CUSTOM_VAR")` to read the variable at run time
+}
+
+fn test_cargo_unknown_var() {
+ // Cargo-prefixed but not similar to any known variable
+ let _ = env!("CARGO_SOMETHING_TOTALLY_UNKNOWN");
+ //~^ ERROR environment variable `CARGO_SOMETHING_TOTALLY_UNKNOWN` not defined at compile time
+ //~| HELP Cargo sets build script variables at run time. Use `std::env::var("CARGO_SOMETHING_TOTALLY_UNKNOWN")` instead
+}
+
+fn main() {}
diff --git a/tests/ui/env-macro/env-cargo-var-typo-issue-148439.stderr b/tests/ui/env-macro/env-cargo-var-typo-issue-148439.stderr
new file mode 100644
index 0000000000000..e16c4d9a1f4c2
--- /dev/null
+++ b/tests/ui/env-macro/env-cargo-var-typo-issue-148439.stderr
@@ -0,0 +1,58 @@
+error: environment variable `CARGO_PACKAGE_VERSION` not defined at compile time
+ --> $DIR/env-cargo-var-typo-issue-148439.rs:7:13
+ |
+LL | let _ = env!("CARGO_PACKAGE_VERSION");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: there is a similar Cargo environment variable: `CARGO_PKG_VERSION`
+
+error: environment variable `CARGO_PACKAGE_NAME` not defined at compile time
+ --> $DIR/env-cargo-var-typo-issue-148439.rs:13:13
+ |
+LL | let _ = env!("CARGO_PACKAGE_NAME");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: there is a similar Cargo environment variable: `CARGO_PKG_NAME`
+
+error: environment variable `CARGO_PACKAGE_AUTHORS` not defined at compile time
+ --> $DIR/env-cargo-var-typo-issue-148439.rs:19:13
+ |
+LL | let _ = env!("CARGO_PACKAGE_AUTHORS");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: there is a similar Cargo environment variable: `CARGO_PKG_AUTHORS`
+
+error: environment variable `CARGO_MANIFEST_DIRECTORY` not defined at compile time
+ --> $DIR/env-cargo-var-typo-issue-148439.rs:25:13
+ |
+LL | let _ = env!("CARGO_MANIFEST_DIRECTORY");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: there is a similar Cargo environment variable: `CARGO_MANIFEST_DIR`
+
+error: environment variable `CARGO_PKG_VERSIO` not defined at compile time
+ --> $DIR/env-cargo-var-typo-issue-148439.rs:31:13
+ |
+LL | let _ = env!("CARGO_PKG_VERSIO");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: there is a similar Cargo environment variable: `CARGO_PKG_VERSION`
+
+error: environment variable `MY_CUSTOM_VAR` not defined at compile time
+ --> $DIR/env-cargo-var-typo-issue-148439.rs:38:13
+ |
+LL | let _ = env!("MY_CUSTOM_VAR");
+ | ^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: use `std::env::var("MY_CUSTOM_VAR")` to read the variable at run time
+
+error: environment variable `CARGO_SOMETHING_TOTALLY_UNKNOWN` not defined at compile time
+ --> $DIR/env-cargo-var-typo-issue-148439.rs:45:13
+ |
+LL | let _ = env!("CARGO_SOMETHING_TOTALLY_UNKNOWN");
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = help: Cargo sets build script variables at run time. Use `std::env::var("CARGO_SOMETHING_TOTALLY_UNKNOWN")` instead
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/feature-gates/feature-gate-new_range.stderr b/tests/ui/feature-gates/feature-gate-new_range.stderr
index c4241390418b6..b7f70d30bfa0b 100644
--- a/tests/ui/feature-gates/feature-gate-new_range.stderr
+++ b/tests/ui/feature-gates/feature-gate-new_range.stderr
@@ -10,8 +10,8 @@ LL | let a: core::range::RangeFrom = 1..;
found struct `std::ops::RangeFrom<{integer}>`
help: call `Into::into` on this expression to convert `std::ops::RangeFrom<{integer}>` into `std::range::RangeFrom`
|
-LL | let a: core::range::RangeFrom = 1...into();
- | +++++++
+LL | let a: core::range::RangeFrom = (1..).into();
+ | + ++++++++
error[E0308]: mismatched types
--> $DIR/feature-gate-new_range.rs:6:37
@@ -25,8 +25,8 @@ LL | let b: core::range::Range = 2..3;
found struct `std::ops::Range<{integer}>`
help: call `Into::into` on this expression to convert `std::ops::Range<{integer}>` into `std::range::Range`
|
-LL | let b: core::range::Range = 2..3.into();
- | +++++++
+LL | let b: core::range::Range = (2..3).into();
+ | + ++++++++
error[E0308]: mismatched types
--> $DIR/feature-gate-new_range.rs:8:46
@@ -40,8 +40,8 @@ LL | let c: core::range::RangeInclusive = 4..=5;
found struct `std::ops::RangeInclusive<{integer}>`
help: call `Into::into` on this expression to convert `std::ops::RangeInclusive<{integer}>` into `std::range::RangeInclusive`
|
-LL | let c: core::range::RangeInclusive = 4..=5.into();
- | +++++++
+LL | let c: core::range::RangeInclusive = (4..=5).into();
+ | + ++++++++
error: aborting due to 3 previous errors
diff --git a/tests/ui/macros/macro-expansion-empty-span-147255.rs b/tests/ui/macros/macro-expansion-empty-span-147255.rs
new file mode 100644
index 0000000000000..311cf5bf9b1bd
--- /dev/null
+++ b/tests/ui/macros/macro-expansion-empty-span-147255.rs
@@ -0,0 +1,10 @@
+//! Regression test for
+
+fn main() {
+ let mut x = 4;
+ let x_str = {
+ format!("{}", x);
+ //()
+ };
+ println!("{}", x_str); //~ ERROR `()` doesn't implement `std::fmt::Display`
+}
diff --git a/tests/ui/macros/macro-expansion-empty-span-147255.stderr b/tests/ui/macros/macro-expansion-empty-span-147255.stderr
new file mode 100644
index 0000000000000..99396622b34eb
--- /dev/null
+++ b/tests/ui/macros/macro-expansion-empty-span-147255.stderr
@@ -0,0 +1,15 @@
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+ --> $DIR/macro-expansion-empty-span-147255.rs:9:20
+ |
+LL | println!("{}", x_str);
+ | -- ^^^^^ `()` cannot be formatted with the default formatter
+ | |
+ | required by this formatting parameter
+ |
+ = help: the trait `std::fmt::Display` is not implemented for `()`
+ = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+ = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/suggestions/into-convert-range-issue-148344.fixed b/tests/ui/suggestions/into-convert-range-issue-148344.fixed
new file mode 100644
index 0000000000000..5bf0e8e3063bf
--- /dev/null
+++ b/tests/ui/suggestions/into-convert-range-issue-148344.fixed
@@ -0,0 +1,15 @@
+//@ run-rustfix
+use std::ops::Range;
+
+struct Strange;
+impl From> for Strange {
+ fn from(_: Range) -> Self {
+ Self
+ }
+}
+
+fn main() {
+ let _: Strange = (0..10).into();
+ //~^ ERROR mismatched types
+ //~| HELP call `Into::into` on this expression
+}
diff --git a/tests/ui/suggestions/into-convert-range-issue-148344.rs b/tests/ui/suggestions/into-convert-range-issue-148344.rs
new file mode 100644
index 0000000000000..aa1df2d4103ac
--- /dev/null
+++ b/tests/ui/suggestions/into-convert-range-issue-148344.rs
@@ -0,0 +1,15 @@
+//@ run-rustfix
+use std::ops::Range;
+
+struct Strange;
+impl From> for Strange {
+ fn from(_: Range) -> Self {
+ Self
+ }
+}
+
+fn main() {
+ let _: Strange = 0..10;
+ //~^ ERROR mismatched types
+ //~| HELP call `Into::into` on this expression
+}
diff --git a/tests/ui/suggestions/into-convert-range-issue-148344.stderr b/tests/ui/suggestions/into-convert-range-issue-148344.stderr
new file mode 100644
index 0000000000000..ce5342f5789b9
--- /dev/null
+++ b/tests/ui/suggestions/into-convert-range-issue-148344.stderr
@@ -0,0 +1,18 @@
+error[E0308]: mismatched types
+ --> $DIR/into-convert-range-issue-148344.rs:12:22
+ |
+LL | let _: Strange = 0..10;
+ | ------- ^^^^^ expected `Strange`, found `Range<{integer}>`
+ | |
+ | expected due to this
+ |
+ = note: expected struct `Strange`
+ found struct `std::ops::Range<{integer}>`
+help: call `Into::into` on this expression to convert `std::ops::Range<{integer}>` into `Strange`
+ |
+LL | let _: Strange = (0..10).into();
+ | + ++++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.