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:
commit
88bd39beb3
27 changed files with 299 additions and 150 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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>(
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![feature(unchecked_shifts)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _n = 1i8.unchecked_shl(8);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![feature(unchecked_shifts)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let _n = 1i64.unchecked_shr(64);
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
|
||||
#![crate_type = "lib"]
|
||||
#![feature(unchecked_shifts)]
|
||||
|
||||
//@ compile-flags: -Zmir-opt-level=2 -Zinline-mir
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
||||
|
|
|
|||
18
tests/ui/borrowck/option-inspect-mutation.rs
Normal file
18
tests/ui/borrowck/option-inspect-mutation.rs
Normal 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
|
||||
});
|
||||
}
|
||||
15
tests/ui/borrowck/option-inspect-mutation.stderr
Normal file
15
tests/ui/borrowck/option-inspect-mutation.stderr
Normal 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`.
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
18
tests/ui/check-cfg/cfg-select.rs
Normal file
18
tests/ui/check-cfg/cfg-select.rs
Normal 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 => {}
|
||||
_ => {}
|
||||
}
|
||||
22
tests/ui/check-cfg/cfg-select.stderr
Normal file
22
tests/ui/check-cfg/cfg-select.stderr
Normal 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
|
||||
|
||||
|
|
@ -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 },) => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue