Skip to content

Commit 11e10a4

Browse files
committed
Auto merge of #148458 - Zalathar:rollup-2xmquy0, r=Zalathar
Rollup of 10 pull requests Successful merges: - #133149 (Provide more context on `Fn` closure modifying binding) - #143037 (Make named asm_labels lint not trigger on hexagon register spans) - #144529 (Add `#[rustc_pass_indirectly_in_non_rustic_abis]`) - #145915 (Stabilize `fmt::from_fn`) - #145974 (Stabilize -Zno-jump-tables into -Cjump-tables=bool) - #146057 (feat: add `from_fn_ptr` to `Waker` and `LocalWaker`) - #146301 (library: std: sys: net: uefi: tcp: Implement write_vectored) - #148437 (Regression test for undefined `__chkstk` on `aarch64-unknown-uefi`) - #148448 (Update books) - #148451 (tidy: Fix false positives with absolute repo paths in `pal.rs` `check()`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 5f9dd05 + 161ba70 commit 11e10a4

File tree

83 files changed

+1070
-140
lines changed

Some content is hidden

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

83 files changed

+1070
-140
lines changed

compiler/rustc_abi/src/layout/ty.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ pub trait TyAbiInterface<'a, C>: Sized + std::fmt::Debug {
172172
fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
173173
fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
174174
fn is_transparent(this: TyAndLayout<'a, Self>) -> bool;
175+
/// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details.
176+
fn is_pass_indirectly_in_non_rustic_abis_flag_set(this: TyAndLayout<'a, Self>) -> bool;
175177
}
176178

177179
impl<'a, Ty> TyAndLayout<'a, Ty> {
@@ -269,6 +271,30 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
269271
Ty::is_transparent(self)
270272
}
271273

274+
/// If this method returns `true`, then this type should always have a `PassMode` of
275+
/// `Indirect { on_stack: false, .. }` when being used as the argument type of a function with a
276+
/// non-Rustic ABI (this is true for structs annotated with the
277+
/// `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute).
278+
///
279+
/// This is used to replicate some of the behaviour of C array-to-pointer decay; however unlike
280+
/// C any changes the caller makes to the passed value will not be reflected in the callee, so
281+
/// the attribute is only useful for types where observing the value in the caller after the
282+
/// function call isn't allowed (a.k.a. `va_list`).
283+
///
284+
/// This function handles transparent types automatically.
285+
pub fn pass_indirectly_in_non_rustic_abis<C>(mut self, cx: &C) -> bool
286+
where
287+
Ty: TyAbiInterface<'a, C> + Copy,
288+
{
289+
while self.is_transparent()
290+
&& let Some((_, field)) = self.non_1zst_field(cx)
291+
{
292+
self = field;
293+
}
294+
295+
Ty::is_pass_indirectly_in_non_rustic_abis_flag_set(self)
296+
}
297+
272298
/// Finds the one field that is not a 1-ZST.
273299
/// Returns `None` if there are multiple non-1-ZST fields or only 1-ZST-fields.
274300
pub fn non_1zst_field<C>(&self, cx: &C) -> Option<(FieldIdx, Self)>

compiler/rustc_abi/src/lib.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,17 @@ bitflags! {
8888
const IS_C = 1 << 0;
8989
const IS_SIMD = 1 << 1;
9090
const IS_TRANSPARENT = 1 << 2;
91-
// Internal only for now. If true, don't reorder fields.
92-
// On its own it does not prevent ABI optimizations.
91+
/// Internal only for now. If true, don't reorder fields.
92+
/// On its own it does not prevent ABI optimizations.
9393
const IS_LINEAR = 1 << 3;
94-
// If true, the type's crate has opted into layout randomization.
95-
// Other flags can still inhibit reordering and thus randomization.
96-
// The seed stored in `ReprOptions.field_shuffle_seed`.
94+
/// If true, the type's crate has opted into layout randomization.
95+
/// Other flags can still inhibit reordering and thus randomization.
96+
/// The seed stored in `ReprOptions.field_shuffle_seed`.
9797
const RANDOMIZE_LAYOUT = 1 << 4;
98-
// Any of these flags being set prevent field reordering optimisation.
98+
/// If true, the type is always passed indirectly by non-Rustic ABIs.
99+
/// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details.
100+
const PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS = 1 << 5;
101+
/// Any of these flags being set prevent field reordering optimisation.
99102
const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits()
100103
| ReprFlags::IS_SIMD.bits()
101104
| ReprFlags::IS_LINEAR.bits();

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,3 +676,12 @@ impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
676676
Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span })
677677
}
678678
}
679+
680+
pub(crate) struct RustcPassIndirectlyInNonRusticAbisParser;
681+
682+
impl<S: Stage> NoArgsAttributeParser<S> for RustcPassIndirectlyInNonRusticAbisParser {
683+
const PATH: &[Symbol] = &[sym::rustc_pass_indirectly_in_non_rustic_abis];
684+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
685+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
686+
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPassIndirectlyInNonRusticAbis;
687+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ use crate::attributes::allow_unstable::{
2020
use crate::attributes::body::CoroutineParser;
2121
use crate::attributes::codegen_attrs::{
2222
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
23-
NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser, SanitizeParser,
24-
TargetFeatureParser, TrackCallerParser, UsedParser,
23+
NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
24+
RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser, TargetFeatureParser,
25+
TrackCallerParser, UsedParser,
2526
};
2627
use crate::attributes::confusables::ConfusablesParser;
2728
use crate::attributes::crate_level::{
@@ -243,6 +244,7 @@ attribute_parsers!(
243244
Single<WithoutArgs<PubTransparentParser>>,
244245
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
245246
Single<WithoutArgs<RustcMainParser>>,
247+
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,
246248
Single<WithoutArgs<SpecializationTraitParser>>,
247249
Single<WithoutArgs<StdInternalSymbolParser>>,
248250
Single<WithoutArgs<TrackCallerParser>>,

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
150150
}
151151
}
152152
}
153-
PlaceRef { local: _, projection: [proj_base @ .., ProjectionElem::Deref] } => {
154-
if the_place_err.local == ty::CAPTURE_STRUCT_LOCAL
153+
PlaceRef { local, projection: [proj_base @ .., ProjectionElem::Deref] } => {
154+
if local == ty::CAPTURE_STRUCT_LOCAL
155155
&& proj_base.is_empty()
156156
&& !self.upvars.is_empty()
157157
{
@@ -165,10 +165,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
165165
", as `Fn` closures cannot mutate their captured variables".to_string()
166166
}
167167
} else {
168-
let source = self.borrowed_content_source(PlaceRef {
169-
local: the_place_err.local,
170-
projection: proj_base,
171-
});
168+
let source =
169+
self.borrowed_content_source(PlaceRef { local, projection: proj_base });
172170
let pointer_type = source.describe_for_immutable_place(self.infcx.tcx);
173171
opt_source = Some(source);
174172
if let Some(desc) = self.describe_place(access_place.as_ref()) {
@@ -540,6 +538,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
540538
PlaceRef { local, projection: [ProjectionElem::Deref] }
541539
if local == ty::CAPTURE_STRUCT_LOCAL && !self.upvars.is_empty() =>
542540
{
541+
self.point_at_binding_outside_closure(&mut err, local, access_place);
543542
self.expected_fn_found_fn_mut_call(&mut err, span, act);
544543
}
545544

@@ -958,6 +957,50 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
958957
}
959958
}
960959

960+
/// When modifying a binding from inside of an `Fn` closure, point at the binding definition.
961+
fn point_at_binding_outside_closure(
962+
&self,
963+
err: &mut Diag<'_>,
964+
local: Local,
965+
access_place: Place<'tcx>,
966+
) {
967+
let place = access_place.as_ref();
968+
for (index, elem) in place.projection.into_iter().enumerate() {
969+
if let ProjectionElem::Deref = elem {
970+
if index == 0 {
971+
if self.body.local_decls[local].is_ref_for_guard() {
972+
continue;
973+
}
974+
if let LocalInfo::StaticRef { .. } = *self.body.local_decls[local].local_info()
975+
{
976+
continue;
977+
}
978+
}
979+
if let Some(field) = self.is_upvar_field_projection(PlaceRef {
980+
local,
981+
projection: place.projection.split_at(index + 1).0,
982+
}) {
983+
let var_index = field.index();
984+
let upvar = self.upvars[var_index];
985+
if let Some(hir_id) = upvar.info.capture_kind_expr_id {
986+
let node = self.infcx.tcx.hir_node(hir_id);
987+
if let hir::Node::Expr(expr) = node
988+
&& let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
989+
&& let hir::def::Res::Local(hir_id) = path.res
990+
&& let hir::Node::Pat(pat) = self.infcx.tcx.hir_node(hir_id)
991+
{
992+
let name = upvar.to_string(self.infcx.tcx);
993+
err.span_label(
994+
pat.span,
995+
format!("`{name}` declared here, outside the closure"),
996+
);
997+
break;
998+
}
999+
}
1000+
}
1001+
}
1002+
}
1003+
}
9611004
/// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected.
9621005
fn expected_fn_found_fn_mut_call(&self, err: &mut Diag<'_>, sp: Span, act: &str) {
9631006
err.span_label(sp, format!("cannot {act}"));
@@ -970,6 +1013,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
9701013
let def_id = tcx.hir_enclosing_body_owner(fn_call_id);
9711014
let mut look_at_return = true;
9721015

1016+
err.span_label(closure_span, "in this closure");
9731017
// If the HIR node is a function or method call, get the DefId
9741018
// of the callee function or method, the span, and args of the call expr
9751019
let get_call_details = || {
@@ -1040,7 +1084,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
10401084
if let Some(span) = arg {
10411085
err.span_label(span, "change this to accept `FnMut` instead of `Fn`");
10421086
err.span_label(call_span, "expects `Fn` instead of `FnMut`");
1043-
err.span_label(closure_span, "in this closure");
10441087
look_at_return = false;
10451088
}
10461089
}
@@ -1067,7 +1110,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
10671110
sig.decl.output.span(),
10681111
"change this to return `FnMut` instead of `Fn`",
10691112
);
1070-
err.span_label(closure_span, "in this closure");
10711113
}
10721114
_ => {}
10731115
}

compiler/rustc_codegen_llvm/src/attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ fn instrument_function_attr<'ll>(
229229
}
230230

231231
fn nojumptables_attr<'ll>(cx: &SimpleCx<'ll>, sess: &Session) -> Option<&'ll Attribute> {
232-
if !sess.opts.unstable_opts.no_jump_tables {
232+
if sess.opts.cg.jump_tables {
233233
return None;
234234
}
235235

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
657657
template!(Word, "https://doc.rust-lang.org/reference/attributes/codegen.html#the-naked-attribute"),
658658
WarnFollowing, EncodeCrossCrate::No
659659
),
660+
// See `TyAndLayout::pass_indirectly_in_non_rustic_abis` for details.
661+
rustc_attr!(
662+
rustc_pass_indirectly_in_non_rustic_abis, Normal, template!(Word), ErrorFollowing,
663+
EncodeCrossCrate::No,
664+
"types marked with `#[rustc_pass_indirectly_in_non_rustic_abis]` are always passed indirectly by non-Rustic abis."
665+
),
660666

661667
// Limits:
662668
ungated!(

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,9 @@ pub enum AttributeKind {
679679
/// Represents `#[rustc_object_lifetime_default]`.
680680
RustcObjectLifetimeDefault,
681681

682+
/// Represents `#[rustc_pass_indirectly_in_non_rustic_abis]`
683+
RustcPassIndirectlyInNonRusticAbis(Span),
684+
682685
/// Represents `#[rustc_simd_monomorphize_lane_limit = "N"]`.
683686
RustcSimdMonomorphizeLaneLimit(Limit),
684687

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ impl AttributeKind {
9191
RustcLayoutScalarValidRangeStart(..) => Yes,
9292
RustcMain => No,
9393
RustcObjectLifetimeDefault => No,
94+
RustcPassIndirectlyInNonRusticAbis(..) => No,
9495
RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate
9596
Sanitize { .. } => No,
9697
ShouldPanic { .. } => No,

compiler/rustc_hir/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
44
55
// tidy-alphabetical-start
6+
#![cfg_attr(bootstrap, feature(debug_closure_helpers))]
67
#![feature(associated_type_defaults)]
78
#![feature(closure_track_caller)]
8-
#![feature(debug_closure_helpers)]
99
#![feature(exhaustive_patterns)]
1010
#![feature(never_type)]
1111
#![feature(variant_count)]

0 commit comments

Comments
 (0)