Skip to content

Commit b65ad53

Browse files
authored
Unrolled build for #143156
Rollup merge of #143156 - folkertdev:fn-align-inherit-from-trait, r=workingjubilee inherit `#[align]` from trait method prototypes ````@workingjubilee```` this seems straightforward enough. Now that we're planning to make `-Cmin-function-alignment` a target modifier, I don't think there are any cross-crate complications here? ````@Jules-Bertholet```` is this the behavior you had in mind? In particular the inheritance of the attribute of a default impl is maybe a bit unintuitive at first? (but I think it's ok if that behavior is explicitly documented). r? ghost
2 parents 6988a8f + bcf5105 commit b65ad53

File tree

4 files changed

+93
-26
lines changed

4 files changed

+93
-26
lines changed

‎compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::str::FromStr;
22

3-
use rustc_abi::ExternAbi;
3+
use rustc_abi::{Align, ExternAbi};
44
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
55
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
66
use rustc_attr_data_structures::{
@@ -395,6 +395,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
395395
codegen_fn_attrs.alignment =
396396
Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment);
397397

398+
// On trait methods, inherit the `#[align]` of the trait's method prototype.
399+
codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.inherited_align(did));
400+
398401
let inline_span;
399402
(codegen_fn_attrs.inline, inline_span) = if let Some((inline_attr, span)) =
400403
find_attr!(attrs, AttributeKind::Inline(i, span) => (*i, *span))
@@ -549,17 +552,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
549552
codegen_fn_attrs
550553
}
551554

555+
/// If the provided DefId is a method in a trait impl, return the DefId of the method prototype.
556+
fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
557+
let impl_item = tcx.opt_associated_item(def_id)?;
558+
match impl_item.container {
559+
ty::AssocItemContainer::Impl => impl_item.trait_item_def_id,
560+
_ => None,
561+
}
562+
}
563+
552564
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
553565
/// applied to the method prototype.
554566
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
555-
if let Some(impl_item) = tcx.opt_associated_item(def_id)
556-
&& let ty::AssocItemContainer::Impl = impl_item.container
557-
&& let Some(trait_item) = impl_item.trait_item_def_id
558-
{
559-
return tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER);
560-
}
567+
let Some(trait_item) = opt_trait_item(tcx, def_id) else { return false };
568+
tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
569+
}
561570

562-
false
571+
/// If the provided DefId is a method in a trait impl, return the value of the `#[align]`
572+
/// attribute on the method prototype (if any).
573+
fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Align> {
574+
tcx.codegen_fn_attrs(opt_trait_item(tcx, def_id)?).alignment
563575
}
564576

565577
fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Option<u16> {
@@ -727,5 +739,6 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
727739
}
728740

729741
pub(crate) fn provide(providers: &mut Providers) {
730-
*providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
742+
*providers =
743+
Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..*providers };
731744
}

‎compiler/rustc_middle/src/query/erase.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ trivial! {
266266
Option<rustc_target::spec::PanicStrategy>,
267267
Option<usize>,
268268
Option<rustc_middle::ty::IntrinsicDef>,
269+
Option<rustc_abi::Align>,
269270
Result<(), rustc_errors::ErrorGuaranteed>,
270271
Result<(), rustc_middle::traits::query::NoSolution>,
271272
Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>,

‎compiler/rustc_middle/src/query/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ use std::mem;
6767
use std::path::PathBuf;
6868
use std::sync::Arc;
6969

70+
use rustc_abi::Align;
7071
use rustc_arena::TypedArena;
7172
use rustc_ast::expand::StrippedCfgItem;
7273
use rustc_ast::expand::allocator::AllocatorKind;
@@ -1481,6 +1482,10 @@ rustc_queries! {
14811482
desc { |tcx| "computing should_inherit_track_caller of `{}`", tcx.def_path_str(def_id) }
14821483
}
14831484

1485+
query inherited_align(def_id: DefId) -> Option<Align> {
1486+
desc { |tcx| "computing inherited_align of `{}`", tcx.def_path_str(def_id) }
1487+
}
1488+
14841489
query lookup_deprecation_entry(def_id: DefId) -> Option<DeprecationEntry> {
14851490
desc { |tcx| "checking whether `{}` is deprecated", tcx.def_path_str(def_id) }
14861491
cache_on_disk_if { def_id.is_local() }

‎tests/codegen/align-fn.rs

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,118 @@
1-
//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
1+
//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0 -Clink-dead-code
22

33
#![crate_type = "lib"]
44
#![feature(fn_align)]
55

66
// CHECK: align 16
7-
#[no_mangle]
7+
#[unsafe(no_mangle)]
88
#[align(16)]
99
pub fn fn_align() {}
1010

1111
pub struct A;
1212

1313
impl A {
1414
// CHECK: align 16
15-
#[no_mangle]
15+
#[unsafe(no_mangle)]
1616
#[align(16)]
1717
pub fn method_align(self) {}
1818

1919
// CHECK: align 16
20-
#[no_mangle]
20+
#[unsafe(no_mangle)]
2121
#[align(16)]
2222
pub fn associated_fn() {}
2323
}
2424

2525
trait T: Sized {
2626
fn trait_fn() {}
2727

28-
// CHECK: align 32
29-
#[align(32)]
3028
fn trait_method(self) {}
29+
30+
#[align(8)]
31+
fn trait_method_inherit_low(self);
32+
33+
#[align(32)]
34+
fn trait_method_inherit_high(self);
35+
36+
#[align(32)]
37+
fn trait_method_inherit_default(self) {}
38+
39+
#[align(4)]
40+
#[align(128)]
41+
#[align(8)]
42+
fn inherit_highest(self) {}
3143
}
3244

3345
impl T for A {
34-
// CHECK: align 16
35-
#[no_mangle]
46+
// CHECK-LABEL: trait_fn
47+
// CHECK-SAME: align 16
48+
#[unsafe(no_mangle)]
3649
#[align(16)]
3750
fn trait_fn() {}
3851

39-
// CHECK: align 16
40-
#[no_mangle]
52+
// CHECK-LABEL: trait_method
53+
// CHECK-SAME: align 16
54+
#[unsafe(no_mangle)]
4155
#[align(16)]
4256
fn trait_method(self) {}
43-
}
4457

45-
impl T for () {}
58+
// The prototype's align is ignored because the align here is higher.
59+
// CHECK-LABEL: trait_method_inherit_low
60+
// CHECK-SAME: align 16
61+
#[unsafe(no_mangle)]
62+
#[align(16)]
63+
fn trait_method_inherit_low(self) {}
64+
65+
// The prototype's align is used because it is higher.
66+
// CHECK-LABEL: trait_method_inherit_high
67+
// CHECK-SAME: align 32
68+
#[unsafe(no_mangle)]
69+
#[align(16)]
70+
fn trait_method_inherit_high(self) {}
71+
72+
// The prototype's align inherited.
73+
// CHECK-LABEL: trait_method_inherit_default
74+
// CHECK-SAME: align 32
75+
#[unsafe(no_mangle)]
76+
fn trait_method_inherit_default(self) {}
77+
78+
// The prototype's highest align inherited.
79+
// CHECK-LABEL: inherit_highest
80+
// CHECK-SAME: align 128
81+
#[unsafe(no_mangle)]
82+
#[align(32)]
83+
#[align(64)]
84+
fn inherit_highest(self) {}
85+
}
4686

47-
pub fn foo() {
48-
().trait_method();
87+
trait HasDefaultImpl: Sized {
88+
// CHECK-LABEL: inherit_from_default_method
89+
// CHECK-LABEL: inherit_from_default_method
90+
// CHECK-SAME: align 32
91+
#[align(32)]
92+
fn inherit_from_default_method(self) {}
4993
}
5094

95+
pub struct InstantiateDefaultMethods;
96+
97+
impl HasDefaultImpl for InstantiateDefaultMethods {}
98+
5199
// CHECK-LABEL: align_specified_twice_1
52100
// CHECK-SAME: align 64
53-
#[no_mangle]
101+
#[unsafe(no_mangle)]
54102
#[align(32)]
55103
#[align(64)]
56104
pub fn align_specified_twice_1() {}
57105

58106
// CHECK-LABEL: align_specified_twice_2
59107
// CHECK-SAME: align 128
60-
#[no_mangle]
108+
#[unsafe(no_mangle)]
61109
#[align(128)]
62110
#[align(32)]
63111
pub fn align_specified_twice_2() {}
64112

65113
// CHECK-LABEL: align_specified_twice_3
66114
// CHECK-SAME: align 256
67-
#[no_mangle]
115+
#[unsafe(no_mangle)]
68116
#[align(32)]
69117
#[align(256)]
70118
pub fn align_specified_twice_3() {}

0 commit comments

Comments
 (0)