Skip to content

Commit ad7a1aa

Browse files
committed
Auto merge of rust-lang#3851 - rust-lang:rustup-2024-08-29, r=RalfJung
Automatic Rustup
2 parents 9ad0f65 + b5be3ab commit ad7a1aa

File tree

192 files changed

+1474
-818
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

192 files changed

+1474
-818
lines changed

compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc_middle::mir::coverage::{
2-
CodeRegion, ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind,
2+
ConditionInfo, CounterId, CovTerm, DecisionInfo, ExpressionId, MappingKind, SourceRegion,
33
};
44

55
/// Must match the layout of `LLVMRustCounterKind`.
@@ -236,9 +236,10 @@ impl CounterMappingRegion {
236236
pub(crate) fn from_mapping(
237237
mapping_kind: &MappingKind,
238238
local_file_id: u32,
239-
code_region: &CodeRegion,
239+
source_region: &SourceRegion,
240240
) -> Self {
241-
let &CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region;
241+
let &SourceRegion { file_name: _, start_line, start_col, end_line, end_col } =
242+
source_region;
242243
match *mapping_kind {
243244
MappingKind::Code(term) => Self::code_region(
244245
Counter::from_term(term),

compiler/rustc_codegen_llvm/src/coverageinfo/map_data.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use rustc_data_structures::captures::Captures;
22
use rustc_data_structures::fx::FxIndexSet;
33
use rustc_index::bit_set::BitSet;
44
use rustc_middle::mir::coverage::{
5-
CodeRegion, CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping,
6-
MappingKind, Op,
5+
CounterId, CovTerm, Expression, ExpressionId, FunctionCoverageInfo, Mapping, MappingKind, Op,
6+
SourceRegion,
77
};
88
use rustc_middle::ty::Instance;
99
use rustc_span::Symbol;
@@ -201,7 +201,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
201201

202202
/// Returns an iterator over all filenames used by this function's mappings.
203203
pub(crate) fn all_file_names(&self) -> impl Iterator<Item = Symbol> + Captures<'_> {
204-
self.function_coverage_info.mappings.iter().map(|mapping| mapping.code_region.file_name)
204+
self.function_coverage_info.mappings.iter().map(|mapping| mapping.source_region.file_name)
205205
}
206206

207207
/// Convert this function's coverage expression data into a form that can be
@@ -230,12 +230,12 @@ impl<'tcx> FunctionCoverage<'tcx> {
230230
/// that will be used by `mapgen` when preparing for FFI.
231231
pub(crate) fn counter_regions(
232232
&self,
233-
) -> impl Iterator<Item = (MappingKind, &CodeRegion)> + ExactSizeIterator {
233+
) -> impl Iterator<Item = (MappingKind, &SourceRegion)> + ExactSizeIterator {
234234
self.function_coverage_info.mappings.iter().map(move |mapping| {
235-
let Mapping { kind, code_region } = mapping;
235+
let Mapping { kind, source_region } = mapping;
236236
let kind =
237237
kind.map_terms(|term| if self.is_zero_term(term) { CovTerm::Zero } else { term });
238-
(kind, code_region)
238+
(kind, source_region)
239239
})
240240
}
241241

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+115-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_ast::{ast, attr, MetaItemKind, NestedMetaItem};
22
use rustc_attr::{list_contains_name, InlineAttr, InstructionSetAttr, OptimizeAttr};
3+
use rustc_data_structures::fx::FxHashSet;
34
use rustc_errors::codes::*;
45
use rustc_errors::{struct_span_code_err, DiagMessage, SubdiagMessage};
56
use rustc_hir as hir;
@@ -8,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
89
use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
910
use rustc_hir::{lang_items, LangItem};
1011
use rustc_middle::middle::codegen_fn_attrs::{
11-
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
12+
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, TargetFeature,
1213
};
1314
use rustc_middle::mir::mono::Linkage;
1415
use rustc_middle::query::Providers;
@@ -17,6 +18,7 @@ use rustc_session::lint;
1718
use rustc_session::parse::feature_err;
1819
use rustc_span::symbol::Ident;
1920
use rustc_span::{sym, Span};
21+
use rustc_target::abi::VariantIdx;
2022
use rustc_target::spec::{abi, SanitizerSet};
2123

2224
use crate::errors;
@@ -78,23 +80,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
7880
let mut link_ordinal_span = None;
7981
let mut no_sanitize_span = None;
8082

83+
let fn_sig_outer = || {
84+
use DefKind::*;
85+
86+
let def_kind = tcx.def_kind(did);
87+
if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None }
88+
};
89+
8190
for attr in attrs.iter() {
8291
// In some cases, attribute are only valid on functions, but it's the `check_attr`
8392
// pass that check that they aren't used anywhere else, rather this module.
8493
// In these cases, we bail from performing further checks that are only meaningful for
8594
// functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
8695
// report a delayed bug, just in case `check_attr` isn't doing its job.
8796
let fn_sig = || {
88-
use DefKind::*;
89-
90-
let def_kind = tcx.def_kind(did);
91-
if let Fn | AssocFn | Variant | Ctor(..) = def_kind {
92-
Some(tcx.fn_sig(did))
93-
} else {
97+
let sig = fn_sig_outer();
98+
if sig.is_none() {
9499
tcx.dcx()
95100
.span_delayed_bug(attr.span, "this attribute can only be applied to functions");
96-
None
97101
}
102+
sig
98103
};
99104

100105
let Some(Ident { name, .. }) = attr.ident() else {
@@ -613,7 +618,93 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
613618
}
614619
}
615620

616-
// If a function uses #[target_feature] it can't be inlined into general
621+
if let Some(sig) = fn_sig_outer() {
622+
// Collect target features from types reachable from arguments.
623+
// We define a type as "reachable" if:
624+
// - it is a function argument
625+
// - it is a field of a reachable struct
626+
// - there is a reachable reference to it
627+
// FIXME(struct_target_features): we may want to cache the result of this computation.
628+
let mut visited_types = FxHashSet::default();
629+
let mut reachable_types: Vec<_> = sig.skip_binder().inputs().skip_binder().to_owned();
630+
let mut additional_tf = vec![];
631+
632+
while let Some(ty) = reachable_types.pop() {
633+
if visited_types.contains(&ty) {
634+
continue;
635+
}
636+
visited_types.insert(ty);
637+
match ty.kind() {
638+
ty::Alias(..) => {
639+
if let Ok(t) =
640+
tcx.try_normalize_erasing_regions(tcx.param_env(did.to_def_id()), ty)
641+
{
642+
reachable_types.push(t)
643+
}
644+
}
645+
646+
ty::Ref(_, inner, _) => reachable_types.push(*inner),
647+
ty::Tuple(tys) => reachable_types.extend(tys.iter()),
648+
ty::Adt(adt_def, args) => {
649+
additional_tf.extend_from_slice(tcx.struct_target_features(adt_def.did()));
650+
// This only recurses into structs as i.e. an Option<TargetFeature> is an ADT
651+
// that doesn't actually always contain a TargetFeature.
652+
if adt_def.is_struct() {
653+
reachable_types.extend(
654+
adt_def
655+
.variant(VariantIdx::from_usize(0))
656+
.fields
657+
.iter()
658+
.map(|field| field.ty(tcx, args)),
659+
);
660+
}
661+
}
662+
ty::Bool
663+
| ty::Char
664+
| ty::Int(..)
665+
| ty::Uint(..)
666+
| ty::Float(..)
667+
| ty::Foreign(..)
668+
| ty::Str
669+
| ty::Array(..)
670+
| ty::Pat(..)
671+
| ty::Slice(..)
672+
| ty::RawPtr(..)
673+
| ty::FnDef(..)
674+
| ty::FnPtr(..)
675+
| ty::Dynamic(..)
676+
| ty::Closure(..)
677+
| ty::CoroutineClosure(..)
678+
| ty::Coroutine(..)
679+
| ty::CoroutineWitness(..)
680+
| ty::Never
681+
| ty::Param(..)
682+
| ty::Bound(..)
683+
| ty::Placeholder(..)
684+
| ty::Infer(..)
685+
| ty::Error(..) => (),
686+
}
687+
}
688+
689+
// FIXME(struct_target_features): is this really necessary?
690+
if !additional_tf.is_empty() && sig.skip_binder().abi() != abi::Abi::Rust {
691+
tcx.dcx().span_err(
692+
tcx.hir().span(tcx.local_def_id_to_hir_id(did)),
693+
"cannot use a struct with target features in a function with non-Rust ABI",
694+
);
695+
}
696+
if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always {
697+
tcx.dcx().span_err(
698+
tcx.hir().span(tcx.local_def_id_to_hir_id(did)),
699+
"cannot use a struct with target features in a #[inline(always)] function",
700+
);
701+
}
702+
codegen_fn_attrs
703+
.target_features
704+
.extend(additional_tf.iter().map(|tf| TargetFeature { implied: true, ..*tf }));
705+
}
706+
707+
// If a function uses non-default target_features it can't be inlined into general
617708
// purpose functions as they wouldn't have the right target features
618709
// enabled. For that reason we also forbid #[inline(always)] as it can't be
619710
// respected.
@@ -758,6 +849,20 @@ fn check_link_name_xor_ordinal(
758849
}
759850
}
760851

852+
fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeature] {
853+
let mut features = vec![];
854+
let supported_features = tcx.supported_target_features(LOCAL_CRATE);
855+
for attr in tcx.get_attrs(def_id, sym::target_feature) {
856+
from_target_feature(tcx, attr, supported_features, &mut features);
857+
}
858+
tcx.arena.alloc_slice(&features)
859+
}
860+
761861
pub fn provide(providers: &mut Providers) {
762-
*providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
862+
*providers = Providers {
863+
codegen_fn_attrs,
864+
should_inherit_track_caller,
865+
struct_target_features,
866+
..*providers
867+
};
763868
}

compiler/rustc_const_eval/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -402,9 +402,6 @@ const_eval_unallowed_mutable_refs =
402402
const_eval_unallowed_op_in_const_context =
403403
{$msg}
404404
405-
const_eval_unavailable_target_features_for_fn =
406-
calling a function that requires unavailable target features: {$unavailable_feats}
407-
408405
const_eval_uninhabited_enum_variant_read =
409406
read discriminant of an uninhabited enum variant
410407
const_eval_uninhabited_enum_variant_written =

compiler/rustc_const_eval/src/interpret/call.rs

+7-37
Original file line numberDiff line numberDiff line change
@@ -311,34 +311,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
311311
Ok(())
312312
}
313313

314-
fn check_fn_target_features(&self, instance: ty::Instance<'tcx>) -> InterpResult<'tcx, ()> {
315-
// Calling functions with `#[target_feature]` is not unsafe on WASM, see #84988
316-
let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
317-
if !self.tcx.sess.target.is_like_wasm
318-
&& attrs
319-
.target_features
320-
.iter()
321-
.any(|feature| !self.tcx.sess.target_features.contains(&feature.name))
322-
{
323-
throw_ub_custom!(
324-
fluent::const_eval_unavailable_target_features_for_fn,
325-
unavailable_feats = attrs
326-
.target_features
327-
.iter()
328-
.filter(|&feature| !feature.implied
329-
&& !self.tcx.sess.target_features.contains(&feature.name))
330-
.fold(String::new(), |mut s, feature| {
331-
if !s.is_empty() {
332-
s.push_str(", ");
333-
}
334-
s.push_str(feature.name.as_str());
335-
s
336-
}),
337-
);
338-
}
339-
Ok(())
340-
}
341-
342314
/// The main entry point for creating a new stack frame: performs ABI checks and initializes
343315
/// arguments.
344316
#[instrument(skip(self), level = "trace")]
@@ -360,20 +332,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
360332
throw_unsup_format!("calling a c-variadic function is not supported");
361333
}
362334

363-
if M::enforce_abi(self) {
364-
if caller_fn_abi.conv != callee_fn_abi.conv {
365-
throw_ub_custom!(
366-
fluent::const_eval_incompatible_calling_conventions,
367-
callee_conv = format!("{:?}", callee_fn_abi.conv),
368-
caller_conv = format!("{:?}", caller_fn_abi.conv),
369-
)
370-
}
335+
if caller_fn_abi.conv != callee_fn_abi.conv {
336+
throw_ub_custom!(
337+
fluent::const_eval_incompatible_calling_conventions,
338+
callee_conv = format!("{:?}", callee_fn_abi.conv),
339+
caller_conv = format!("{:?}", caller_fn_abi.conv),
340+
)
371341
}
372342

373343
// Check that all target features required by the callee (i.e., from
374344
// the attribute `#[target_feature(enable = ...)]`) are enabled at
375345
// compile time.
376-
self.check_fn_target_features(instance)?;
346+
M::check_fn_target_features(self, instance)?;
377347

378348
if !callee_fn_abi.can_unwind {
379349
// The callee cannot unwind, so force the `Unreachable` unwind handling.

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -684,19 +684,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
684684
assert!(layout.is_sized());
685685

686686
let get_bytes = |this: &InterpCx<'tcx, M>,
687-
op: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>,
688-
size|
687+
op: &OpTy<'tcx, <M as Machine<'tcx>>::Provenance>|
689688
-> InterpResult<'tcx, &[u8]> {
690689
let ptr = this.read_pointer(op)?;
691-
let Some(alloc_ref) = self.get_ptr_alloc(ptr, size)? else {
690+
this.check_ptr_align(ptr, layout.align.abi)?;
691+
let Some(alloc_ref) = self.get_ptr_alloc(ptr, layout.size)? else {
692692
// zero-sized access
693693
return Ok(&[]);
694694
};
695695
alloc_ref.get_bytes_strip_provenance()
696696
};
697697

698-
let lhs_bytes = get_bytes(self, lhs, layout.size)?;
699-
let rhs_bytes = get_bytes(self, rhs, layout.size)?;
698+
let lhs_bytes = get_bytes(self, lhs)?;
699+
let rhs_bytes = get_bytes(self, rhs)?;
700700
Ok(Scalar::from_bool(lhs_bytes == rhs_bytes))
701701
}
702702
}

compiler/rustc_const_eval/src/interpret/machine.rs

+27-5
Original file line numberDiff line numberDiff line change
@@ -173,11 +173,6 @@ pub trait Machine<'tcx>: Sized {
173173
false
174174
}
175175

176-
/// Whether function calls should be [ABI](CallAbi)-checked.
177-
fn enforce_abi(_ecx: &InterpCx<'tcx, Self>) -> bool {
178-
true
179-
}
180-
181176
/// Whether Assert(OverflowNeg) and Assert(Overflow) MIR terminators should actually
182177
/// check for overflow.
183178
fn ignore_optional_overflow_checks(_ecx: &InterpCx<'tcx, Self>) -> bool;
@@ -238,6 +233,13 @@ pub trait Machine<'tcx>: Sized {
238233
unwind: mir::UnwindAction,
239234
) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>>;
240235

236+
/// Check whether the given function may be executed on the current machine, in terms of the
237+
/// target features is requires.
238+
fn check_fn_target_features(
239+
_ecx: &InterpCx<'tcx, Self>,
240+
_instance: ty::Instance<'tcx>,
241+
) -> InterpResult<'tcx>;
242+
241243
/// Called to evaluate `Assert` MIR terminators that trigger a panic.
242244
fn assert_panic(
243245
ecx: &mut InterpCx<'tcx, Self>,
@@ -280,6 +282,9 @@ pub trait Machine<'tcx>: Sized {
280282
Ok(())
281283
}
282284

285+
/// Determines the result of a `NullaryOp::UbChecks` invocation.
286+
fn ub_checks(_ecx: &InterpCx<'tcx, Self>) -> InterpResult<'tcx, bool>;
287+
283288
/// Called when the interpreter encounters a `StatementKind::ConstEvalCounter` instruction.
284289
/// You can use this to detect long or endlessly running programs.
285290
#[inline]
@@ -614,6 +619,16 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
614619
unreachable!("unwinding cannot happen during compile-time evaluation")
615620
}
616621

622+
#[inline(always)]
623+
fn check_fn_target_features(
624+
_ecx: &InterpCx<$tcx, Self>,
625+
_instance: ty::Instance<$tcx>,
626+
) -> InterpResult<$tcx> {
627+
// For now we don't do any checking here. We can't use `tcx.sess` because that can differ
628+
// between crates, and we need to ensure that const-eval always behaves the same.
629+
Ok(())
630+
}
631+
617632
#[inline(always)]
618633
fn call_extra_fn(
619634
_ecx: &mut InterpCx<$tcx, Self>,
@@ -627,6 +642,13 @@ pub macro compile_time_machine(<$tcx: lifetime>) {
627642
match fn_val {}
628643
}
629644

645+
#[inline(always)]
646+
fn ub_checks(_ecx: &InterpCx<$tcx, Self>) -> InterpResult<$tcx, bool> {
647+
// We can't look at `tcx.sess` here as that can differ across crates, which can lead to
648+
// unsound differences in evaluating the same constant at different instantiation sites.
649+
Ok(true)
650+
}
651+
630652
#[inline(always)]
631653
fn adjust_global_allocation<'b>(
632654
_ecx: &InterpCx<$tcx, Self>,

0 commit comments

Comments
 (0)