Skip to content

Commit 10d9ecd

Browse files
committed
Auto merge of rust-lang#96800 - nbdd0121:const, r=nagisa
Permit `asm_const` and `asm_sym` to reference generic params Related rust-lang#96557 These constructs will be allowed: ```rust fn foofoo<const N: usize>() {} unsafe fn foo<const N: usize>() { asm!("/* {0} */", const N); asm!("/* {0} */", const N + 1); asm!("/* {0} */", sym foofoo::<N>); } fn barbar<T>() {} unsafe fn bar<T>() { asm!("/* {0} */", const std::mem::size_of::<T>()); asm!("/* {0} */", const std::mem::size_of::<(T, T)>()); asm!("/* {0} */", sym barbar::<T>); asm!("/* {0} */", sym barbar::<(T, T)>); } ``` `@Amanieu,` I didn't switch inline asms to use `DefKind::InlineAsm`, as I see little value doing that; given that no type inference is needed, it will only make typecking slower and more complex but will have no real gains. I did switch them to follow the same code path as inline asm during symbol resolution, though. The `error: unconstrained generic constant` you mentioned in rust-lang#76001 is due to the fact that `to_const` will actually add a wfness obligation to the constant, which we don't need for `asm_const`, so I have that removed. `@rustbot` label: +A-inline-assembly +F-asm
2 parents 936eba3 + 441d98f commit 10d9ecd

File tree

12 files changed

+116
-58
lines changed

12 files changed

+116
-58
lines changed

compiler/rustc_ast/src/visit.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
326326
ItemKind::ForeignMod(ref foreign_module) => {
327327
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
328328
}
329-
ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
329+
ItemKind::GlobalAsm(ref asm) => visitor.visit_inline_asm(asm),
330330
ItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
331331
visitor.visit_generics(generics);
332332
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
@@ -897,7 +897,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
897897
}
898898
ExprKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
899899
ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression),
900-
ExprKind::InlineAsm(ref asm) => walk_inline_asm(visitor, asm),
900+
ExprKind::InlineAsm(ref asm) => visitor.visit_inline_asm(asm),
901901
ExprKind::Yield(ref optional_expression) => {
902902
walk_list!(visitor, visit_expr, optional_expression);
903903
}

compiler/rustc_resolve/src/ident.rs

+2-32
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,7 @@ impl<'a> Resolver<'a> {
11711171
| AssocItemRibKind
11721172
| ModuleRibKind(..)
11731173
| MacroDefinition(..)
1174+
| InlineAsmSymRibKind
11741175
| ForwardGenericParamBanRibKind => {
11751176
// Nothing to do. Continue.
11761177
continue;
@@ -1216,22 +1217,6 @@ impl<'a> Resolver<'a> {
12161217
}
12171218
return Res::Err;
12181219
}
1219-
InlineAsmSymRibKind => {
1220-
let features = self.session.features_untracked();
1221-
if !features.generic_const_exprs {
1222-
if let Some(span) = finalize {
1223-
self.report_error(
1224-
span,
1225-
ResolutionError::ParamInNonTrivialAnonConst {
1226-
name: rib_ident.name,
1227-
is_type: true,
1228-
},
1229-
);
1230-
}
1231-
return Res::Err;
1232-
}
1233-
continue;
1234-
}
12351220
};
12361221

12371222
if let Some(span) = finalize {
@@ -1262,6 +1247,7 @@ impl<'a> Resolver<'a> {
12621247
| AssocItemRibKind
12631248
| ModuleRibKind(..)
12641249
| MacroDefinition(..)
1250+
| InlineAsmSymRibKind
12651251
| ForwardGenericParamBanRibKind => continue,
12661252

12671253
ConstantItemRibKind(trivial, _) => {
@@ -1296,22 +1282,6 @@ impl<'a> Resolver<'a> {
12961282
}
12971283
return Res::Err;
12981284
}
1299-
InlineAsmSymRibKind => {
1300-
let features = self.session.features_untracked();
1301-
if !features.generic_const_exprs {
1302-
if let Some(span) = finalize {
1303-
self.report_error(
1304-
span,
1305-
ResolutionError::ParamInNonTrivialAnonConst {
1306-
name: rib_ident.name,
1307-
is_type: false,
1308-
},
1309-
);
1310-
}
1311-
return Res::Err;
1312-
}
1313-
continue;
1314-
}
13151285
};
13161286

13171287
// This was an attempt to use a const parameter outside its scope.

compiler/rustc_resolve/src/late.rs

+23
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,29 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
918918
self.diagnostic_metadata.current_where_predicate = previous_value;
919919
}
920920

921+
fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
922+
for (op, _) in &asm.operands {
923+
match op {
924+
InlineAsmOperand::In { expr, .. }
925+
| InlineAsmOperand::Out { expr: Some(expr), .. }
926+
| InlineAsmOperand::InOut { expr, .. } => self.visit_expr(expr),
927+
InlineAsmOperand::Out { expr: None, .. } => {}
928+
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
929+
self.visit_expr(in_expr);
930+
if let Some(out_expr) = out_expr {
931+
self.visit_expr(out_expr);
932+
}
933+
}
934+
InlineAsmOperand::Const { anon_const, .. } => {
935+
// Although this is `DefKind::AnonConst`, it is allowed to reference outer
936+
// generic parameters like an inline const.
937+
self.resolve_inline_const(anon_const);
938+
}
939+
InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
940+
}
941+
}
942+
}
943+
921944
fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
922945
// This is similar to the code for AnonConst.
923946
self.with_rib(ValueNS, InlineAsmSymRibKind, |this| {

compiler/rustc_typeck/src/check/expr.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -2641,10 +2641,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26412641
self.check_expr_asm_operand(out_expr, false);
26422642
}
26432643
}
2644-
hir::InlineAsmOperand::Const { anon_const }
2645-
| hir::InlineAsmOperand::SymFn { anon_const } => {
2646-
self.to_const(anon_const);
2647-
}
2644+
// `AnonConst`s have their own body and is type-checked separately.
2645+
// As they don't flow into the type system we don't need them to
2646+
// be well-formed.
2647+
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
26482648
hir::InlineAsmOperand::SymStatic { .. } => {}
26492649
}
26502650
}

compiler/rustc_typeck/src/collect.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,18 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
15561556
Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
15571557
Some(tcx.typeck_root_def_id(def_id))
15581558
}
1559+
// Exclude `GlobalAsm` here which cannot have generics.
1560+
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
1561+
if asm.operands.iter().any(|(op, _op_sp)| match op {
1562+
hir::InlineAsmOperand::Const { anon_const }
1563+
| hir::InlineAsmOperand::SymFn { anon_const } => {
1564+
anon_const.hir_id == hir_id
1565+
}
1566+
_ => false,
1567+
}) =>
1568+
{
1569+
Some(parent_def_id.to_def_id())
1570+
}
15591571
_ => None,
15601572
}
15611573
}

src/test/ui/asm/generic-const.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// needs-asm-support
2+
// build-pass
3+
4+
#![feature(asm_const, asm_sym)]
5+
6+
use std::arch::asm;
7+
8+
fn foofoo<const N: usize>() {}
9+
10+
unsafe fn foo<const N: usize>() {
11+
asm!("/* {0} */", const N);
12+
asm!("/* {0} */", const N + 1);
13+
asm!("/* {0} */", sym foofoo::<N>);
14+
}
15+
16+
fn barbar<T>() {}
17+
18+
unsafe fn bar<T>() {
19+
asm!("/* {0} */", const std::mem::size_of::<T>());
20+
asm!("/* {0} */", const std::mem::size_of::<(T, T)>());
21+
asm!("/* {0} */", sym barbar::<T>);
22+
asm!("/* {0} */", sym barbar::<(T, T)>);
23+
}
24+
25+
fn main() {
26+
unsafe {
27+
foo::<0>();
28+
bar::<usize>();
29+
}
30+
}

src/test/ui/asm/type-check-1.rs

-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ fn main() {
6363

6464
unsafe fn generic<T>() {
6565
asm!("{}", sym generic::<T>);
66-
//~^ generic parameters may not be used in const operations
6766
}
6867

6968
// Const operands must be integers and must be constants.

src/test/ui/asm/type-check-1.stderr

+3-12
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,6 @@ LL | asm!("{}", sym x);
3333
|
3434
= help: `sym` operands must refer to either a function or a static
3535

36-
error: generic parameters may not be used in const operations
37-
--> $DIR/type-check-1.rs:65:30
38-
|
39-
LL | asm!("{}", sym generic::<T>);
40-
| ^ cannot perform const operation using `T`
41-
|
42-
= note: type parameters may not be used in const expressions
43-
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
44-
4536
error[E0308]: mismatched types
4637
--> $DIR/type-check-1.rs:55:26
4738
|
@@ -109,21 +100,21 @@ LL | asm!("{}", inout(reg) v[..]);
109100
= note: all inline asm arguments must have a statically known size
110101

111102
error[E0308]: mismatched types
112-
--> $DIR/type-check-1.rs:74:25
103+
--> $DIR/type-check-1.rs:73:25
113104
|
114105
LL | global_asm!("{}", const 0f32);
115106
| ^^^^ expected integer, found `f32`
116107

117108
error[E0308]: mismatched types
118-
--> $DIR/type-check-1.rs:76:25
109+
--> $DIR/type-check-1.rs:75:25
119110
|
120111
LL | global_asm!("{}", const 0 as *mut u8);
121112
| ^^^^^^^^^^^^ expected integer, found *-ptr
122113
|
123114
= note: expected type `{integer}`
124115
found raw pointer `*mut u8`
125116

126-
error: aborting due to 15 previous errors
117+
error: aborting due to 14 previous errors
127118

128119
Some errors have detailed explanations: E0277, E0308, E0435.
129120
For more information about an error, try `rustc --explain E0277`.

src/test/ui/feature-gates/feature-gate-asm_const.rs

+6
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,14 @@
22

33
use std::arch::asm;
44

5+
unsafe fn foo<const N: usize>() {
6+
asm!("mov eax, {}", const N + 1);
7+
//~^ ERROR const operands for inline assembly are unstable
8+
}
9+
510
fn main() {
611
unsafe {
12+
foo::<0>();
713
asm!("mov eax, {}", const 123);
814
//~^ ERROR const operands for inline assembly are unstable
915
}
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
error[E0658]: const operands for inline assembly are unstable
2-
--> $DIR/feature-gate-asm_const.rs:7:29
2+
--> $DIR/feature-gate-asm_const.rs:6:25
3+
|
4+
LL | asm!("mov eax, {}", const N + 1);
5+
| ^^^^^^^^^^^
6+
|
7+
= note: see issue #93332 <https://github.com/rust-lang/rust/issues/93332> for more information
8+
= help: add `#![feature(asm_const)]` to the crate attributes to enable
9+
10+
error[E0658]: const operands for inline assembly are unstable
11+
--> $DIR/feature-gate-asm_const.rs:13:29
312
|
413
LL | asm!("mov eax, {}", const 123);
514
| ^^^^^^^^^
615
|
716
= note: see issue #93332 <https://github.com/rust-lang/rust/issues/93332> for more information
817
= help: add `#![feature(asm_const)]` to the crate attributes to enable
918

10-
error: aborting due to previous error
19+
error: aborting due to 2 previous errors
1120

1221
For more information about this error, try `rustc --explain E0658`.

src/test/ui/feature-gates/feature-gate-asm_sym.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,18 @@
22

33
use std::arch::asm;
44

5+
fn bar<const N: usize>() {}
6+
7+
fn foo<const N: usize>() {
8+
unsafe {
9+
asm!("mov eax, {}", sym bar::<N>);
10+
//~^ ERROR sym operands for inline assembly are unstable
11+
}
12+
}
13+
514
fn main() {
615
unsafe {
7-
asm!("mov eax, {}", sym main);
16+
asm!("mov eax, {}", sym foo::<0>);
817
//~^ ERROR sym operands for inline assembly are unstable
918
}
1019
}
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
11
error[E0658]: sym operands for inline assembly are unstable
2-
--> $DIR/feature-gate-asm_sym.rs:7:29
2+
--> $DIR/feature-gate-asm_sym.rs:9:29
33
|
4-
LL | asm!("mov eax, {}", sym main);
5-
| ^^^^^^^^
4+
LL | asm!("mov eax, {}", sym bar::<N>);
5+
| ^^^^^^^^^^^^
66
|
77
= note: see issue #93333 <https://github.com/rust-lang/rust/issues/93333> for more information
88
= help: add `#![feature(asm_sym)]` to the crate attributes to enable
99

10-
error: aborting due to previous error
10+
error[E0658]: sym operands for inline assembly are unstable
11+
--> $DIR/feature-gate-asm_sym.rs:16:29
12+
|
13+
LL | asm!("mov eax, {}", sym foo::<0>);
14+
| ^^^^^^^^^^^^
15+
|
16+
= note: see issue #93333 <https://github.com/rust-lang/rust/issues/93333> for more information
17+
= help: add `#![feature(asm_sym)]` to the crate attributes to enable
18+
19+
error: aborting due to 2 previous errors
1120

1221
For more information about this error, try `rustc --explain E0658`.

0 commit comments

Comments
 (0)