Skip to content

Commit 3bc59cd

Browse files
committed
inherit #[align] from trait method prototypes
1 parent d41e12f commit 3bc59cd

File tree

4 files changed

+94
-26
lines changed

4 files changed

+94
-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::{
@@ -402,6 +402,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
402402
codegen_fn_attrs.alignment =
403403
Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment);
404404

405+
// On trait methods, inherit the `#[align]` of the trait's method prototype.
406+
codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.inherited_align(did));
407+
405408
let inline_span;
406409
(codegen_fn_attrs.inline, inline_span) = if let Some((inline_attr, span)) =
407410
find_attr!(attrs, AttributeKind::Inline(i, span) => (*i, *span))
@@ -556,17 +559,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
556559
codegen_fn_attrs
557560
}
558561

562+
/// If the provided DefId is a method in a trait impl, return the DefId of the method prototype.
563+
fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
564+
let impl_item = tcx.opt_associated_item(def_id)?;
565+
match impl_item.container {
566+
ty::AssocItemContainer::Impl => impl_item.trait_item_def_id,
567+
_ => None,
568+
}
569+
}
570+
559571
/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
560572
/// applied to the method prototype.
561573
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
562-
if let Some(impl_item) = tcx.opt_associated_item(def_id)
563-
&& let ty::AssocItemContainer::Impl = impl_item.container
564-
&& let Some(trait_item) = impl_item.trait_item_def_id
565-
{
566-
return tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER);
567-
}
574+
let Some(trait_item) = opt_trait_item(tcx, def_id) else { return false };
575+
tcx.codegen_fn_attrs(trait_item).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
576+
}
568577

569-
false
578+
/// If the provided DefId is a method in a trait impl, return the value of the `#[align]`
579+
/// attribute on the method prototype (if any).
580+
fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Align> {
581+
tcx.codegen_fn_attrs(opt_trait_item(tcx, def_id)?).alignment
570582
}
571583

572584
fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Option<u16> {
@@ -734,5 +746,6 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
734746
}
735747

736748
pub(crate) fn provide(providers: &mut Providers) {
737-
*providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };
749+
*providers =
750+
Providers { codegen_fn_attrs, should_inherit_track_caller, inherited_align, ..*providers };
738751
}

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: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,119 @@
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+
#[unsafe(no_mangle)]
38+
fn trait_method_inherit_default(self) {}
39+
40+
#[align(4)]
41+
#[align(128)]
42+
#[align(8)]
43+
fn inherit_highest(self) {}
3144
}
3245

3346
impl T for A {
34-
// CHECK: align 16
35-
#[no_mangle]
47+
// CHECK-LABEL: trait_fn
48+
// CHECK-SAME: align 16
49+
#[unsafe(no_mangle)]
3650
#[align(16)]
3751
fn trait_fn() {}
3852

39-
// CHECK: align 16
40-
#[no_mangle]
53+
// CHECK-LABEL: trait_method
54+
// CHECK-SAME: align 16
55+
#[unsafe(no_mangle)]
4156
#[align(16)]
4257
fn trait_method(self) {}
43-
}
4458

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

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

96+
pub struct InstantiateDefaultMethods;
97+
98+
impl HasDefaultImpl for InstantiateDefaultMethods {}
99+
51100
// CHECK-LABEL: align_specified_twice_1
52101
// CHECK-SAME: align 64
53-
#[no_mangle]
102+
#[unsafe(no_mangle)]
54103
#[align(32)]
55104
#[align(64)]
56105
pub fn align_specified_twice_1() {}
57106

58107
// CHECK-LABEL: align_specified_twice_2
59108
// CHECK-SAME: align 128
60-
#[no_mangle]
109+
#[unsafe(no_mangle)]
61110
#[align(128)]
62111
#[align(32)]
63112
pub fn align_specified_twice_2() {}
64113

65114
// CHECK-LABEL: align_specified_twice_3
66115
// CHECK-SAME: align 256
67-
#[no_mangle]
116+
#[unsafe(no_mangle)]
68117
#[align(32)]
69118
#[align(256)]
70119
pub fn align_specified_twice_3() {}

0 commit comments

Comments
 (0)