Auto merge of #149410 - Zalathar:rollup-wke6axp, r=Zalathar

Rollup of 5 pull requests

Successful merges:

 - rust-lang/rust#149087 (Stabilize `unchecked_neg` and `unchecked_shifts`)
 - rust-lang/rust#149107 (rustc_borrowck: Don't suggest changing closure param type not under user control)
 - rust-lang/rust#149323 (Use cg_llvm's target_config in miri)
 - rust-lang/rust#149380 (Run `eval_config_entry` on all branches so we always emit lints)
 - rust-lang/rust#149394 (add regression test for guard patterns liveness ICE)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-11-28 05:03:10 +00:00
commit 88bd39beb3
27 changed files with 299 additions and 150 deletions

View file

@ -1198,6 +1198,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
);
return;
}
// Do not suggest changing type if that is not under user control.
if self.is_closure_arg_with_non_locally_decided_type(local) {
return;
}
let decl_span = local_decl.source_info.span;
let (amp_mut_sugg, local_var_ty_info) = match *local_decl.local_info() {
@ -1500,6 +1506,60 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
Applicability::HasPlaceholders,
);
}
/// Returns `true` if `local` is an argument in a closure passed to a
/// function defined in another crate.
///
/// For example, in the following code this function returns `true` for `x`
/// since `Option::inspect()` is not defined in the current crate:
///
/// ```text
/// some_option.as_mut().inspect(|x| {
/// ```
fn is_closure_arg_with_non_locally_decided_type(&self, local: Local) -> bool {
// We don't care about regular local variables, only args.
if self.body.local_kind(local) != LocalKind::Arg {
return false;
}
// Make sure we are inside a closure.
let InstanceKind::Item(body_def_id) = self.body.source.instance else {
return false;
};
let Some(Node::Expr(hir::Expr { hir_id: body_hir_id, kind, .. })) =
self.infcx.tcx.hir_get_if_local(body_def_id)
else {
return false;
};
let ExprKind::Closure(hir::Closure { kind: hir::ClosureKind::Closure, .. }) = kind else {
return false;
};
// Check if the method/function that our closure is passed to is defined
// in another crate.
let Node::Expr(closure_parent) = self.infcx.tcx.parent_hir_node(*body_hir_id) else {
return false;
};
match closure_parent.kind {
ExprKind::MethodCall(method, _, _, _) => self
.infcx
.tcx
.typeck(method.hir_id.owner.def_id)
.type_dependent_def_id(closure_parent.hir_id)
.is_some_and(|def_id| !def_id.is_local()),
ExprKind::Call(func, _) => self
.infcx
.tcx
.typeck(func.hir_id.owner.def_id)
.node_type_opt(func.hir_id)
.and_then(|ty| match ty.kind() {
ty::FnDef(def_id, _) => Some(def_id),
_ => None,
})
.is_some_and(|def_id| !def_id.is_local()),
_ => false,
}
}
}
struct BindingFinder {

View file

@ -10,6 +10,7 @@ use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};
/// Selects the first arm whose predicate evaluates to true.
fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> {
let mut result = None;
for (cfg, tt, arm_span) in branches.reachable {
if let EvalConfigResult::True = attr::eval_config_entry(
&ecx.sess,
@ -17,11 +18,13 @@ fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenSt
ecx.current_expansion.lint_node_id,
ShouldEmit::ErrorsAndLints,
) {
return Some((tt, arm_span));
// FIXME(#149215) Ideally we should short-circuit here, but `eval_config_entry` currently emits lints so we cannot do this yet.
result.get_or_insert((tt, arm_span));
}
}
branches.wildcard.map(|(_, tt, span)| (tt, span))
let wildcard = branches.wildcard.map(|(_, tt, span)| (tt, span));
result.or(wildcard)
}
pub(super) fn expand_cfg_select<'cx>(

View file

@ -24,6 +24,7 @@ use rustc_session::parse::ParseSess;
use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, lint};
use rustc_span::source_map::{FileLoader, RealFileLoader, SourceMapInputs};
use rustc_span::{FileName, sym};
use rustc_target::spec::Target;
use tracing::trace;
use crate::util;
@ -385,7 +386,7 @@ pub struct Config {
/// custom driver where the custom codegen backend has arbitrary data."
/// (See #102759.)
pub make_codegen_backend:
Option<Box<dyn FnOnce(&config::Options) -> Box<dyn CodegenBackend> + Send>>,
Option<Box<dyn FnOnce(&config::Options, &Target) -> Box<dyn CodegenBackend> + Send>>,
/// Registry of diagnostics codes.
pub registry: Registry,
@ -453,7 +454,7 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
Some(make_codegen_backend) => {
// N.B. `make_codegen_backend` takes precedence over
// `target.default_codegen_backend`, which is ignored in this case.
make_codegen_backend(&config.opts)
make_codegen_backend(&config.opts, &target)
}
};

View file

@ -339,7 +339,7 @@ pub fn get_codegen_backend(
filename if filename.contains('.') => {
load_backend_from_dylib(early_dcx, filename.as_ref())
}
"dummy" => || Box::new(DummyCodegenBackend),
"dummy" => || Box::new(DummyCodegenBackend { target_config_override: None }),
#[cfg(feature = "llvm")]
"llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
backend_name => get_codegen_sysroot(early_dcx, sysroot, backend_name),
@ -352,7 +352,9 @@ pub fn get_codegen_backend(
unsafe { load() }
}
struct DummyCodegenBackend;
pub struct DummyCodegenBackend {
pub target_config_override: Option<Box<dyn Fn(&Session) -> TargetConfig>>,
}
impl CodegenBackend for DummyCodegenBackend {
fn locale_resource(&self) -> &'static str {
@ -364,6 +366,10 @@ impl CodegenBackend for DummyCodegenBackend {
}
fn target_config(&self, sess: &Session) -> TargetConfig {
if let Some(target_config_override) = &self.target_config_override {
return target_config_override(sess);
}
let abi_required_features = sess.target.abi_required_features();
let (target_features, unstable_target_features) = cfg_target_feature::<0>(
sess,

View file

@ -126,8 +126,6 @@
#![feature(str_split_inclusive_remainder)]
#![feature(str_split_remainder)]
#![feature(ub_checks)]
#![feature(unchecked_neg)]
#![feature(unchecked_shifts)]
#![feature(unsafe_pinned)]
#![feature(utf16_extra)]
#![feature(variant_count)]

View file

@ -1275,11 +1275,8 @@ macro_rules! int_impl {
/// i.e. when [`checked_neg`] would return `None`.
///
#[doc = concat!("[`checked_neg`]: ", stringify!($SelfT), "::checked_neg")]
#[unstable(
feature = "unchecked_neg",
reason = "niche optimization path",
issue = "85122",
)]
#[stable(feature = "unchecked_neg", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "unchecked_neg", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
@ -1395,11 +1392,8 @@ macro_rules! int_impl {
/// i.e. when [`checked_shl`] would return `None`.
///
#[doc = concat!("[`checked_shl`]: ", stringify!($SelfT), "::checked_shl")]
#[unstable(
feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[stable(feature = "unchecked_shifts", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "unchecked_shifts", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
@ -1570,11 +1564,8 @@ macro_rules! int_impl {
/// i.e. when [`checked_shr`] would return `None`.
///
#[doc = concat!("[`checked_shr`]: ", stringify!($SelfT), "::checked_shr")]
#[unstable(
feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[stable(feature = "unchecked_shifts", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "unchecked_shifts", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]

View file

@ -1851,11 +1851,8 @@ macro_rules! uint_impl {
/// i.e. when [`checked_shl`] would return `None`.
///
#[doc = concat!("[`checked_shl`]: ", stringify!($SelfT), "::checked_shl")]
#[unstable(
feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[stable(feature = "unchecked_shifts", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "unchecked_shifts", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
@ -2023,11 +2020,8 @@ macro_rules! uint_impl {
/// i.e. when [`checked_shr`] would return `None`.
///
#[doc = concat!("[`checked_shr`]: ", stringify!($SelfT), "::checked_shr")]
#[unstable(
feature = "unchecked_shifts",
reason = "niche optimization path",
issue = "85122",
)]
#[stable(feature = "unchecked_shifts", since = "CURRENT_RUSTC_VERSION")]
#[rustc_const_stable(feature = "unchecked_shifts", since = "CURRENT_RUSTC_VERSION")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]

View file

@ -10,6 +10,7 @@
// The rustc crates we need
extern crate rustc_abi;
extern crate rustc_codegen_ssa;
extern crate rustc_data_structures;
extern crate rustc_driver;
extern crate rustc_hir;
@ -19,6 +20,7 @@ extern crate rustc_log;
extern crate rustc_middle;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;
/// See docs in https://github.com/rust-lang/rust/blob/HEAD/compiler/rustc/src/main.rs
/// and https://github.com/rust-lang/rust/pull/146627 for why we need this.
@ -36,6 +38,7 @@ use std::num::{NonZero, NonZeroI32};
use std::ops::Range;
use std::rc::Rc;
use std::str::FromStr;
use std::sync::Once;
use std::sync::atomic::{AtomicU32, Ordering};
use miri::{
@ -43,12 +46,14 @@ use miri::{
ProvenanceMode, TreeBorrowsParams, ValidationMode, run_genmc_mode,
};
use rustc_abi::ExternAbi;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::sync::{self, DynSync};
use rustc_driver::Compilation;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::{self as hir, Node};
use rustc_hir_analysis::check::check_function_signature;
use rustc_interface::interface::Config;
use rustc_interface::util::DummyCodegenBackend;
use rustc_log::tracing::debug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::exported_symbols::{
@ -58,8 +63,9 @@ use rustc_middle::query::LocalCrate;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::EarlyDiagCtxt;
use rustc_session::config::{CrateType, ErrorOutputType, OptLevel};
use rustc_session::config::{CrateType, ErrorOutputType, OptLevel, Options};
use rustc_span::def_id::DefId;
use rustc_target::spec::Target;
use crate::log::setup::{deinit_loggers, init_early_loggers, init_late_loggers};
@ -161,7 +167,31 @@ fn run_many_seeds(
}
}
/// Generates the codegen backend for code that Miri will interpret: we basically
/// use the dummy backend, except that we put the LLVM backend in charge of
/// target features.
fn make_miri_codegen_backend(opts: &Options, target: &Target) -> Box<dyn CodegenBackend> {
let early_dcx = EarlyDiagCtxt::new(opts.error_format);
// Use the target_config method of the default codegen backend (eg LLVM) to ensure the
// calculated target features match said backend by respecting eg -Ctarget-cpu.
let target_config_backend =
rustc_interface::util::get_codegen_backend(&early_dcx, &opts.sysroot, None, &target);
let target_config_backend_init = Once::new();
Box::new(DummyCodegenBackend {
target_config_override: Some(Box::new(move |sess| {
target_config_backend_init.call_once(|| target_config_backend.init(sess));
target_config_backend.target_config(sess)
})),
})
}
impl rustc_driver::Callbacks for MiriCompilerCalls {
fn config(&mut self, config: &mut rustc_interface::interface::Config) {
config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend));
}
fn after_analysis<'tcx>(
&mut self,
_: &rustc_interface::interface::Compiler,
@ -244,11 +274,20 @@ struct MiriBeRustCompilerCalls {
impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
#[allow(rustc::potential_query_instability)] // rustc_codegen_ssa (where this code is copied from) also allows this lint
fn config(&mut self, config: &mut Config) {
if config.opts.prints.is_empty() && self.target_crate {
if !self.target_crate {
// For a host crate, we fully behave like rustc.
return;
}
// For a target crate, we emit an rlib that Miri can later consume.
config.make_codegen_backend = Some(Box::new(make_miri_codegen_backend));
// Avoid warnings about unsupported crate types. However, only do that we we are *not* being
// queried by cargo about the supported crate types so that cargo still receives the
// warnings it expects.
if config.opts.prints.is_empty() {
#[allow(rustc::bad_opt_access)] // tcx does not exist yet
{
let any_crate_types = !config.opts.crate_types.is_empty();
// Avoid warnings about unsupported crate types.
config
.opts
.crate_types
@ -259,66 +298,63 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
assert!(!config.opts.crate_types.is_empty());
}
}
// Queries overridden here affect the data stored in `rmeta` files of dependencies,
// which will be used later in non-`MIRI_BE_RUSTC` mode.
config.override_queries = Some(|_, local_providers| {
// We need to add #[used] symbols to exported_symbols for `lookup_link_section`.
// FIXME handle this somehow in rustc itself to avoid this hack.
local_providers.exported_non_generic_symbols = |tcx, LocalCrate| {
let reachable_set = tcx.with_stable_hashing_context(|hcx| {
tcx.reachable_set(()).to_sorted(&hcx, true)
});
tcx.arena.alloc_from_iter(
// This is based on:
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L62-L63
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L174
reachable_set.into_iter().filter_map(|&local_def_id| {
// Do the same filtering that rustc does:
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L84-L102
// Otherwise it may cause unexpected behaviours and ICEs
// (https://github.com/rust-lang/rust/issues/86261).
let is_reachable_non_generic = matches!(
tcx.hir_node_by_def_id(local_def_id),
Node::Item(&hir::Item {
kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn{ .. },
..
}) | Node::ImplItem(&hir::ImplItem {
kind: hir::ImplItemKind::Fn(..),
..
})
if !tcx.generics_of(local_def_id).requires_monomorphization(tcx)
);
if !is_reachable_non_generic {
return None;
}
let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id);
if codegen_fn_attrs.contains_extern_indicator()
|| codegen_fn_attrs
.flags
.contains(CodegenFnAttrFlags::USED_COMPILER)
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
{
Some((
ExportedSymbol::NonGeneric(local_def_id.to_def_id()),
// Some dummy `SymbolExportInfo` here. We only use
// `exported_symbols` in shims/foreign_items.rs and the export info
// is ignored.
SymbolExportInfo {
level: SymbolExportLevel::C,
kind: SymbolExportKind::Text,
used: false,
rustc_std_internal_symbol: false,
},
))
} else {
None
}
}),
)
}
});
}
// Queries overridden here affect the data stored in `rmeta` files of dependencies,
// which will be used later in non-`MIRI_BE_RUSTC` mode.
config.override_queries = Some(|_, local_providers| {
// We need to add #[used] symbols to exported_symbols for `lookup_link_section`.
// FIXME handle this somehow in rustc itself to avoid this hack.
local_providers.exported_non_generic_symbols = |tcx, LocalCrate| {
let reachable_set = tcx
.with_stable_hashing_context(|hcx| tcx.reachable_set(()).to_sorted(&hcx, true));
tcx.arena.alloc_from_iter(
// This is based on:
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L62-L63
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L174
reachable_set.into_iter().filter_map(|&local_def_id| {
// Do the same filtering that rustc does:
// https://github.com/rust-lang/rust/blob/2962e7c0089d5c136f4e9600b7abccfbbde4973d/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L84-L102
// Otherwise it may cause unexpected behaviours and ICEs
// (https://github.com/rust-lang/rust/issues/86261).
let is_reachable_non_generic = matches!(
tcx.hir_node_by_def_id(local_def_id),
Node::Item(&hir::Item {
kind: hir::ItemKind::Static(..) | hir::ItemKind::Fn{ .. },
..
}) | Node::ImplItem(&hir::ImplItem {
kind: hir::ImplItemKind::Fn(..),
..
})
if !tcx.generics_of(local_def_id).requires_monomorphization(tcx)
);
if !is_reachable_non_generic {
return None;
}
let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id);
if codegen_fn_attrs.contains_extern_indicator()
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
{
Some((
ExportedSymbol::NonGeneric(local_def_id.to_def_id()),
// Some dummy `SymbolExportInfo` here. We only use
// `exported_symbols` in shims/foreign_items.rs and the export info
// is ignored.
SymbolExportInfo {
level: SymbolExportLevel::C,
kind: SymbolExportKind::Text,
used: false,
rustc_std_internal_symbol: false,
},
))
} else {
None
}
}),
)
}
});
}
fn after_analysis<'tcx>(

View file

@ -165,7 +165,6 @@ pub use crate::shims::unwind::{CatchUnwindData, EvalContextExt as _};
/// Also disable the MIR pass that inserts an alignment check on every pointer dereference. Miri
/// does that too, and with a better error message.
pub const MIRI_DEFAULT_ARGS: &[&str] = &[
"-Zcodegen-backend=dummy",
"--cfg=miri",
"-Zalways-encode-mir",
"-Zextra-const-ub-checks",

View file

@ -1,5 +1,3 @@
#![feature(unchecked_shifts)]
fn main() {
unsafe {
let _n = 1i8.unchecked_shl(8);

View file

@ -1,5 +1,3 @@
#![feature(unchecked_shifts)]
fn main() {
unsafe {
let _n = 1i64.unchecked_shr(64);

View file

@ -0,0 +1,16 @@
// Test that target-cpu implies the correct target features
//@only-target: x86_64
//@compile-flags: -C target-cpu=x86-64-v4
fn main() {
assert!(cfg!(target_feature = "avx2"));
assert!(cfg!(target_feature = "avx512bw"));
assert!(cfg!(target_feature = "avx512cd"));
assert!(cfg!(target_feature = "avx512dq"));
assert!(cfg!(target_feature = "avx512f"));
assert!(cfg!(target_feature = "avx512vl"));
assert!(is_x86_feature_detected!("avx512bw"));
assert!(cfg!(not(target_feature = "avx512vpopcntdq")));
assert!(!is_x86_feature_detected!("avx512vpopcntdq"));
}

View file

@ -11840,34 +11840,6 @@ extern "rust-call" fn add_args(args: (u32, u32)) -> u32 {
fn main() {}
```
"##,
default_severity: Severity::Allow,
warn_since: None,
deny_since: None,
},
Lint {
label: "unchecked_neg",
description: r##"# `unchecked_neg`
The tracking issue for this feature is: [#85122]
[#85122]: https://github.com/rust-lang/rust/issues/85122
------------------------
"##,
default_severity: Severity::Allow,
warn_since: None,
deny_since: None,
},
Lint {
label: "unchecked_shifts",
description: r##"# `unchecked_shifts`
The tracking issue for this feature is: [#85122]
[#85122]: https://github.com/rust-lang/rust/issues/85122
------------------------
"##,
default_severity: Severity::Allow,
warn_since: None,

View file

@ -1,7 +1,6 @@
//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled
#![crate_type = "lib"]
#![feature(unchecked_shifts)]
// Because the result of something like `u32::checked_sub` can only be used if it
// didn't overflow, make sure that LLVM actually knows that in optimized builds.

View file

@ -4,7 +4,6 @@
// optimizations so it doesn't need to worry about them adding more flags.
#![crate_type = "lib"]
#![feature(unchecked_shifts)]
#![feature(core_intrinsics)]
// CHECK-LABEL: @unchecked_shl_unsigned_same

View file

@ -1,6 +1,5 @@
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
#![crate_type = "lib"]
#![feature(unchecked_shifts)]
//@ compile-flags: -Zmir-opt-level=2 -Zinline-mir

View file

@ -2,9 +2,7 @@ error[E0596]: cannot borrow `**layer` as mutable, as it is behind a `&` referenc
--> $DIR/issue-115259-suggest-iter-mut.rs:15:65
|
LL | self.layers.iter().fold(0, |result, mut layer| result + layer.process())
| --------- ^^^^^ `layer` is a `&` reference, so it cannot be borrowed as mutable
| |
| consider changing this binding's type to be: `&mut Box<dyn Layer>`
| ^^^^^ `layer` is a `&` reference, so it cannot be borrowed as mutable
|
help: you may want to use `iter_mut` here
|

View file

@ -2,9 +2,7 @@ error[E0596]: cannot borrow `*container` as mutable, as it is behind a `&` refer
--> $DIR/issue-62387-suggest-iter-mut-2.rs:30:45
|
LL | vec.iter().flat_map(|container| container.things()).cloned().collect::<Vec<PathBuf>>();
| --------- ^^^^^^^^^ `container` is a `&` reference, so it cannot be borrowed as mutable
| |
| consider changing this binding's type to be: `&mut Container`
| ^^^^^^^^^ `container` is a `&` reference, so it cannot be borrowed as mutable
|
help: you may want to use `iter_mut` here
|

View file

@ -2,9 +2,7 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
--> $DIR/issue-62387-suggest-iter-mut.rs:18:27
|
LL | v.iter().for_each(|a| a.double());
| - ^ `a` is a `&` reference, so it cannot be borrowed as mutable
| |
| consider changing this binding's type to be: `&mut A`
| ^ `a` is a `&` reference, so it cannot be borrowed as mutable
|
help: you may want to use `iter_mut` here
|
@ -15,9 +13,7 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
--> $DIR/issue-62387-suggest-iter-mut.rs:25:39
|
LL | v.iter().rev().rev().for_each(|a| a.double());
| - ^ `a` is a `&` reference, so it cannot be borrowed as mutable
| |
| consider changing this binding's type to be: `&mut A`
| ^ `a` is a `&` reference, so it cannot be borrowed as mutable
|
help: you may want to use `iter_mut` here
|

View file

@ -0,0 +1,18 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/128381>.
struct Struct {
field: u32,
}
fn main() {
let mut some_struct = Some(Struct { field: 42 });
some_struct.as_mut().inspect(|some_struct| {
some_struct.field *= 10; //~ ERROR cannot assign to `some_struct.field`, which is behind a `&` reference
// Users can't change type of `some_struct` param, so above error must not suggest it.
});
// Same check as above but using `hir::ExprKind::Call` instead of `hir::ExprKind::MethodCall`.
Option::inspect(some_struct.as_mut(), |some_struct| {
some_struct.field *= 20; //~ ERROR cannot assign to `some_struct.field`, which is behind a `&` reference
});
}

View file

@ -0,0 +1,15 @@
error[E0594]: cannot assign to `some_struct.field`, which is behind a `&` reference
--> $DIR/option-inspect-mutation.rs:10:9
|
LL | some_struct.field *= 10;
| ^^^^^^^^^^^^^^^^^^^^^^^ `some_struct` is a `&` reference, so it cannot be written to
error[E0594]: cannot assign to `some_struct.field`, which is behind a `&` reference
--> $DIR/option-inspect-mutation.rs:16:9
|
LL | some_struct.field *= 20;
| ^^^^^^^^^^^^^^^^^^^^^^^ `some_struct` is a `&` reference, so it cannot be written to
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0594`.

View file

@ -18,9 +18,7 @@ error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
--> $DIR/suggest-as-ref-on-mut-closure.rs:12:26
|
LL | cb.as_ref().map(|cb| cb());
| -- ^^ `cb` is a `&` reference, so it cannot be borrowed as mutable
| |
| consider changing this binding's type to be: `&mut &mut dyn FnMut()`
| ^^ `cb` is a `&` reference, so it cannot be borrowed as mutable
error: aborting due to 2 previous errors

View file

@ -0,0 +1,18 @@
//@ check-pass
#![feature(cfg_select)]
#![crate_type = "lib"]
cfg_select! {
true => {}
invalid_cfg1 => {}
//~^ WARN unexpected `cfg` condition name
_ => {}
}
cfg_select! {
invalid_cfg2 => {}
//~^ WARN unexpected `cfg` condition name
true => {}
_ => {}
}

View file

@ -0,0 +1,22 @@
warning: unexpected `cfg` condition name: `invalid_cfg1`
--> $DIR/cfg-select.rs:8:5
|
LL | invalid_cfg1 => {}
| ^^^^^^^^^^^^
|
= help: expected names are: `FALSE` and `test` and 31 more
= help: to expect this configuration use `--check-cfg=cfg(invalid_cfg1)`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
= note: `#[warn(unexpected_cfgs)]` on by default
warning: unexpected `cfg` condition name: `invalid_cfg2`
--> $DIR/cfg-select.rs:14:5
|
LL | invalid_cfg2 => {}
| ^^^^^^^^^^^^
|
= help: to expect this configuration use `--check-cfg=cfg(invalid_cfg2)`
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
warning: 2 warnings emitted

View file

@ -0,0 +1,21 @@
//@ check-pass
//! Regression test for issue #146445.
//!
//! This test ensures that liveness linting works correctly with guard patterns
//! and doesn't cause an ICE ("no successor") when using variables without
//! underscore prefixes in guard expressions.
//!
//! Fixed by #142390 which moved liveness analysis to MIR.
#![feature(guard_patterns)]
#![expect(incomplete_features)]
fn main() {
// This used to ICE before liveness analysis was moved to MIR.
// The variable `main` (without underscore prefix) would trigger
// liveness linting which wasn't properly implemented for guard patterns.
match (0,) {
(_ if { let main = false; main },) => {}
_ => {}
}
}

View file

@ -2,8 +2,6 @@
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shl cannot overflow
#![feature(unchecked_shifts)]
fn main() {
unsafe {
0u8.unchecked_shl(u8::BITS);

View file

@ -2,8 +2,6 @@
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shr cannot overflow
#![feature(unchecked_shifts)]
fn main() {
unsafe {
0u8.unchecked_shr(u8::BITS);