Skip to content

Commit e029104

Browse files
authored
Unrolled build for #152837
Rollup merge of #152837 - TKanX:bugfix/152340-codegen-fn-attrs-const-caller, r=dingxiangfei2009 fix(codegen): Use `body_codegen_attrs` For Caller In `adjust_target_feature_sig` ### Summary: #### Problem: Coercing a `#[target_feature]` `const fn` to a function pointer inside a `const` body triggers an ICE (debug builds only): ```rust #[target_feature(enable = "sse2")] const fn with_target_feature() {} const X: () = unsafe { let _: unsafe fn() = with_target_feature; // ICE }; ``` ```text assertion failed: def_kind.has_codegen_attrs() unexpected `def_kind` in `codegen_fn_attrs`: Const ``` #### Root Cause: Introduced in #135504 (2025-01-14, commit `8fee6a77394`). `adjust_target_feature_sig` unconditionally calls `codegen_fn_attrs(caller)` to get the caller's target features. `codegen_fn_attrs` requires that the `DefId` satisfies `has_codegen_attrs()`. `DefKind::Const`, `AssocConst`, and `InlineConst` do not — they have no codegen attributes by design. The debug assertion fires. In release builds the call "worked" accidentally: `codegen_fn_attrs` on a const would reach the query machinery and happen to return empty attributes, producing a correct (but unguaranteed) result. The bug was latent until debug builds exposed it. #### Solution: Replace `codegen_fn_attrs(caller)` with `body_codegen_attrs(caller)`. `body_codegen_attrs` exists precisely for this case: it delegates to `codegen_fn_attrs` for function-like `DefKind`s and returns `CodegenFnAttrs::EMPTY` for const items. A const body has no target features, so returning empty is semantically correct. Also fix the pre-existing variable name `callee_features` → `caller_features` (the variable holds the *caller*'s features, not the callee's). ### Changes: - `compiler/rustc_middle/src/ty/context.rs`: `adjust_target_feature_sig` — use `body_codegen_attrs` for `caller`; rename `callee_features` → `caller_features`. - `tests/ui/target-feature/const-target-feature-fn-ptr-coercion.rs`: regression test covering `Const`, `AssocConst`, and `InlineConst` caller contexts. Fixes #152340.
2 parents d8b2222 + 034f7f0 commit e029104

2 files changed

Lines changed: 35 additions & 2 deletions

File tree

compiler/rustc_middle/src/ty/context.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,8 +1331,8 @@ impl<'tcx> TyCtxt<'tcx> {
13311331
caller: DefId,
13321332
) -> Option<ty::Binder<'tcx, ty::FnSig<'tcx>>> {
13331333
let fun_features = &self.codegen_fn_attrs(fun_def).target_features;
1334-
let callee_features = &self.codegen_fn_attrs(caller).target_features;
1335-
if self.is_target_feature_call_safe(&fun_features, &callee_features) {
1334+
let caller_features = &self.body_codegen_attrs(caller).target_features;
1335+
if self.is_target_feature_call_safe(&fun_features, &caller_features) {
13361336
return Some(fun_sig.map_bound(|sig| ty::FnSig { safety: hir::Safety::Safe, ..sig }));
13371337
}
13381338
None
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ only-x86_64
2+
//@ check-pass
3+
//
4+
// Regression test for <https://github.com/rust-lang/rust/issues/152340>.
5+
6+
#![allow(dead_code)]
7+
8+
#[target_feature(enable = "sse2")]
9+
const fn foo() {}
10+
11+
// DefKind::Const
12+
const _: () = unsafe {
13+
let _: unsafe fn() = foo;
14+
};
15+
16+
// DefKind::AssocConst
17+
struct S;
18+
impl S {
19+
const C: () = unsafe {
20+
let _: unsafe fn() = foo;
21+
};
22+
}
23+
24+
// DefKind::InlineConst
25+
fn bar() {
26+
let _ = const {
27+
unsafe {
28+
let _: unsafe fn() = foo;
29+
}
30+
};
31+
}
32+
33+
fn main() {}

0 commit comments

Comments
 (0)