Skip to content

Commit 923f7fc

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

File tree

4 files changed

+70
-18
lines changed

4 files changed

+70
-18
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: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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)]
@@ -25,27 +25,60 @@ impl A {
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+
// CHECK-LABEL: trait_method_inherit_default
37+
// CHECK-SAME: align 32
38+
#[align(32)]
39+
#[no_mangle]
40+
fn trait_method_inherit_default(self) {}
41+
}
42+
43+
pub struct InstantiateDefaultMethods;
44+
45+
impl T for InstantiateDefaultMethods {
46+
fn trait_method_inherit_low(self) {}
47+
fn trait_method_inherit_high(self) {}
3148
}
3249

3350
impl T for A {
34-
// CHECK: align 16
51+
// CHECK-LABEL: trait_fn
52+
// CHECK-SAME: align 16
3553
#[no_mangle]
3654
#[align(16)]
3755
fn trait_fn() {}
3856

39-
// CHECK: align 16
57+
// CHECK-LABEL: trait_method
58+
// CHECK-SAME: align 16
4059
#[no_mangle]
4160
#[align(16)]
4261
fn trait_method(self) {}
43-
}
4462

45-
impl T for () {}
63+
// The prototype's align is ignored because the align here is higher.
64+
// CHECK-LABEL: trait_method_inherit_low
65+
// CHECK-SAME: align 16
66+
#[no_mangle]
67+
#[align(16)]
68+
fn trait_method_inherit_low(self) {}
69+
70+
// The prototype's align is used because it is higher.
71+
// CHECK-LABEL: trait_method_inherit_high
72+
// CHECK-SAME: align 32
73+
#[no_mangle]
74+
#[align(16)]
75+
fn trait_method_inherit_high(self) {}
4676

47-
pub fn foo() {
48-
().trait_method();
77+
// The prototype's align inherited.
78+
// CHECK-LABEL: trait_method_inherit_default_impl
79+
// CHECK-SAME: align 32
80+
#[export_name = "trait_method_inherit_default_impl"]
81+
fn trait_method_inherit_default(self) {}
4982
}
5083

5184
// CHECK-LABEL: align_specified_twice_1

0 commit comments

Comments
 (0)