Auto merge of #96800 - nbdd0121:const, r=nagisa
Permit `asm_const` and `asm_sym` to reference generic params Related #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 #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
This commit is contained in:
commit
10d9ecda48
@ -326,7 +326,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
|
|||||||
ItemKind::ForeignMod(ref foreign_module) => {
|
ItemKind::ForeignMod(ref foreign_module) => {
|
||||||
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
|
walk_list!(visitor, visit_foreign_item, &foreign_module.items);
|
||||||
}
|
}
|
||||||
ItemKind::GlobalAsm(ref asm) => walk_inline_asm(visitor, asm),
|
ItemKind::GlobalAsm(ref asm) => visitor.visit_inline_asm(asm),
|
||||||
ItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
|
ItemKind::TyAlias(box TyAlias { ref generics, ref bounds, ref ty, .. }) => {
|
||||||
visitor.visit_generics(generics);
|
visitor.visit_generics(generics);
|
||||||
walk_list!(visitor, visit_param_bound, bounds, BoundKind::Bound);
|
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) {
|
|||||||
}
|
}
|
||||||
ExprKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
|
ExprKind::MacCall(ref mac) => visitor.visit_mac_call(mac),
|
||||||
ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression),
|
ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression),
|
||||||
ExprKind::InlineAsm(ref asm) => walk_inline_asm(visitor, asm),
|
ExprKind::InlineAsm(ref asm) => visitor.visit_inline_asm(asm),
|
||||||
ExprKind::Yield(ref optional_expression) => {
|
ExprKind::Yield(ref optional_expression) => {
|
||||||
walk_list!(visitor, visit_expr, optional_expression);
|
walk_list!(visitor, visit_expr, optional_expression);
|
||||||
}
|
}
|
||||||
|
@ -1171,6 +1171,7 @@ impl<'a> Resolver<'a> {
|
|||||||
| AssocItemRibKind
|
| AssocItemRibKind
|
||||||
| ModuleRibKind(..)
|
| ModuleRibKind(..)
|
||||||
| MacroDefinition(..)
|
| MacroDefinition(..)
|
||||||
|
| InlineAsmSymRibKind
|
||||||
| ForwardGenericParamBanRibKind => {
|
| ForwardGenericParamBanRibKind => {
|
||||||
// Nothing to do. Continue.
|
// Nothing to do. Continue.
|
||||||
continue;
|
continue;
|
||||||
@ -1216,22 +1217,6 @@ impl<'a> Resolver<'a> {
|
|||||||
}
|
}
|
||||||
return Res::Err;
|
return Res::Err;
|
||||||
}
|
}
|
||||||
InlineAsmSymRibKind => {
|
|
||||||
let features = self.session.features_untracked();
|
|
||||||
if !features.generic_const_exprs {
|
|
||||||
if let Some(span) = finalize {
|
|
||||||
self.report_error(
|
|
||||||
span,
|
|
||||||
ResolutionError::ParamInNonTrivialAnonConst {
|
|
||||||
name: rib_ident.name,
|
|
||||||
is_type: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Res::Err;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(span) = finalize {
|
if let Some(span) = finalize {
|
||||||
@ -1262,6 +1247,7 @@ impl<'a> Resolver<'a> {
|
|||||||
| AssocItemRibKind
|
| AssocItemRibKind
|
||||||
| ModuleRibKind(..)
|
| ModuleRibKind(..)
|
||||||
| MacroDefinition(..)
|
| MacroDefinition(..)
|
||||||
|
| InlineAsmSymRibKind
|
||||||
| ForwardGenericParamBanRibKind => continue,
|
| ForwardGenericParamBanRibKind => continue,
|
||||||
|
|
||||||
ConstantItemRibKind(trivial, _) => {
|
ConstantItemRibKind(trivial, _) => {
|
||||||
@ -1296,22 +1282,6 @@ impl<'a> Resolver<'a> {
|
|||||||
}
|
}
|
||||||
return Res::Err;
|
return Res::Err;
|
||||||
}
|
}
|
||||||
InlineAsmSymRibKind => {
|
|
||||||
let features = self.session.features_untracked();
|
|
||||||
if !features.generic_const_exprs {
|
|
||||||
if let Some(span) = finalize {
|
|
||||||
self.report_error(
|
|
||||||
span,
|
|
||||||
ResolutionError::ParamInNonTrivialAnonConst {
|
|
||||||
name: rib_ident.name,
|
|
||||||
is_type: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Res::Err;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This was an attempt to use a const parameter outside its scope.
|
// This was an attempt to use a const parameter outside its scope.
|
||||||
|
@ -918,6 +918,29 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
|||||||
self.diagnostic_metadata.current_where_predicate = previous_value;
|
self.diagnostic_metadata.current_where_predicate = previous_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
|
||||||
|
for (op, _) in &asm.operands {
|
||||||
|
match op {
|
||||||
|
InlineAsmOperand::In { expr, .. }
|
||||||
|
| InlineAsmOperand::Out { expr: Some(expr), .. }
|
||||||
|
| InlineAsmOperand::InOut { expr, .. } => self.visit_expr(expr),
|
||||||
|
InlineAsmOperand::Out { expr: None, .. } => {}
|
||||||
|
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
|
||||||
|
self.visit_expr(in_expr);
|
||||||
|
if let Some(out_expr) = out_expr {
|
||||||
|
self.visit_expr(out_expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InlineAsmOperand::Const { anon_const, .. } => {
|
||||||
|
// Although this is `DefKind::AnonConst`, it is allowed to reference outer
|
||||||
|
// generic parameters like an inline const.
|
||||||
|
self.resolve_inline_const(anon_const);
|
||||||
|
}
|
||||||
|
InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
|
fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
|
||||||
// This is similar to the code for AnonConst.
|
// This is similar to the code for AnonConst.
|
||||||
self.with_rib(ValueNS, InlineAsmSymRibKind, |this| {
|
self.with_rib(ValueNS, InlineAsmSymRibKind, |this| {
|
||||||
|
@ -2641,10 +2641,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
self.check_expr_asm_operand(out_expr, false);
|
self.check_expr_asm_operand(out_expr, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::InlineAsmOperand::Const { anon_const }
|
// `AnonConst`s have their own body and is type-checked separately.
|
||||||
| hir::InlineAsmOperand::SymFn { anon_const } => {
|
// As they don't flow into the type system we don't need them to
|
||||||
self.to_const(anon_const);
|
// be well-formed.
|
||||||
}
|
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
|
||||||
hir::InlineAsmOperand::SymStatic { .. } => {}
|
hir::InlineAsmOperand::SymStatic { .. } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1556,6 +1556,18 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
|||||||
Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
|
Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
|
||||||
Some(tcx.typeck_root_def_id(def_id))
|
Some(tcx.typeck_root_def_id(def_id))
|
||||||
}
|
}
|
||||||
|
// Exclude `GlobalAsm` here which cannot have generics.
|
||||||
|
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
|
||||||
|
if asm.operands.iter().any(|(op, _op_sp)| match op {
|
||||||
|
hir::InlineAsmOperand::Const { anon_const }
|
||||||
|
| hir::InlineAsmOperand::SymFn { anon_const } => {
|
||||||
|
anon_const.hir_id == hir_id
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}) =>
|
||||||
|
{
|
||||||
|
Some(parent_def_id.to_def_id())
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
30
src/test/ui/asm/generic-const.rs
Normal file
30
src/test/ui/asm/generic-const.rs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// needs-asm-support
|
||||||
|
// build-pass
|
||||||
|
|
||||||
|
#![feature(asm_const, asm_sym)]
|
||||||
|
|
||||||
|
use std::arch::asm;
|
||||||
|
|
||||||
|
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)>);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
foo::<0>();
|
||||||
|
bar::<usize>();
|
||||||
|
}
|
||||||
|
}
|
@ -63,7 +63,6 @@ fn main() {
|
|||||||
|
|
||||||
unsafe fn generic<T>() {
|
unsafe fn generic<T>() {
|
||||||
asm!("{}", sym generic::<T>);
|
asm!("{}", sym generic::<T>);
|
||||||
//~^ generic parameters may not be used in const operations
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Const operands must be integers and must be constants.
|
// Const operands must be integers and must be constants.
|
||||||
|
@ -33,15 +33,6 @@ LL | asm!("{}", sym x);
|
|||||||
|
|
|
|
||||||
= help: `sym` operands must refer to either a function or a static
|
= help: `sym` operands must refer to either a function or a static
|
||||||
|
|
||||||
error: generic parameters may not be used in const operations
|
|
||||||
--> $DIR/type-check-1.rs:65:30
|
|
||||||
|
|
|
||||||
LL | asm!("{}", sym generic::<T>);
|
|
||||||
| ^ cannot perform const operation using `T`
|
|
||||||
|
|
|
||||||
= note: type parameters may not be used in const expressions
|
|
||||||
= help: use `#![feature(generic_const_exprs)]` to allow generic const expressions
|
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/type-check-1.rs:55:26
|
--> $DIR/type-check-1.rs:55:26
|
||||||
|
|
|
|
||||||
@ -109,13 +100,13 @@ LL | asm!("{}", inout(reg) v[..]);
|
|||||||
= note: all inline asm arguments must have a statically known size
|
= note: all inline asm arguments must have a statically known size
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/type-check-1.rs:74:25
|
--> $DIR/type-check-1.rs:73:25
|
||||||
|
|
|
|
||||||
LL | global_asm!("{}", const 0f32);
|
LL | global_asm!("{}", const 0f32);
|
||||||
| ^^^^ expected integer, found `f32`
|
| ^^^^ expected integer, found `f32`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/type-check-1.rs:76:25
|
--> $DIR/type-check-1.rs:75:25
|
||||||
|
|
|
|
||||||
LL | global_asm!("{}", const 0 as *mut u8);
|
LL | global_asm!("{}", const 0 as *mut u8);
|
||||||
| ^^^^^^^^^^^^ expected integer, found *-ptr
|
| ^^^^^^^^^^^^ expected integer, found *-ptr
|
||||||
@ -123,7 +114,7 @@ LL | global_asm!("{}", const 0 as *mut u8);
|
|||||||
= note: expected type `{integer}`
|
= note: expected type `{integer}`
|
||||||
found raw pointer `*mut u8`
|
found raw pointer `*mut u8`
|
||||||
|
|
||||||
error: aborting due to 15 previous errors
|
error: aborting due to 14 previous errors
|
||||||
|
|
||||||
Some errors have detailed explanations: E0277, E0308, E0435.
|
Some errors have detailed explanations: E0277, E0308, E0435.
|
||||||
For more information about an error, try `rustc --explain E0277`.
|
For more information about an error, try `rustc --explain E0277`.
|
||||||
|
@ -2,8 +2,14 @@
|
|||||||
|
|
||||||
use std::arch::asm;
|
use std::arch::asm;
|
||||||
|
|
||||||
|
unsafe fn foo<const N: usize>() {
|
||||||
|
asm!("mov eax, {}", const N + 1);
|
||||||
|
//~^ ERROR const operands for inline assembly are unstable
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
foo::<0>();
|
||||||
asm!("mov eax, {}", const 123);
|
asm!("mov eax, {}", const 123);
|
||||||
//~^ ERROR const operands for inline assembly are unstable
|
//~^ ERROR const operands for inline assembly are unstable
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
error[E0658]: const operands for inline assembly are unstable
|
error[E0658]: const operands for inline assembly are unstable
|
||||||
--> $DIR/feature-gate-asm_const.rs:7:29
|
--> $DIR/feature-gate-asm_const.rs:6:25
|
||||||
|
|
|
||||||
|
LL | asm!("mov eax, {}", const N + 1);
|
||||||
|
| ^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #93332 <https://github.com/rust-lang/rust/issues/93332> for more information
|
||||||
|
= help: add `#![feature(asm_const)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: const operands for inline assembly are unstable
|
||||||
|
--> $DIR/feature-gate-asm_const.rs:13:29
|
||||||
|
|
|
|
||||||
LL | asm!("mov eax, {}", const 123);
|
LL | asm!("mov eax, {}", const 123);
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
@ -7,6 +16,6 @@ LL | asm!("mov eax, {}", const 123);
|
|||||||
= note: see issue #93332 <https://github.com/rust-lang/rust/issues/93332> for more information
|
= note: see issue #93332 <https://github.com/rust-lang/rust/issues/93332> for more information
|
||||||
= help: add `#![feature(asm_const)]` to the crate attributes to enable
|
= help: add `#![feature(asm_const)]` to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
@ -2,9 +2,18 @@
|
|||||||
|
|
||||||
use std::arch::asm;
|
use std::arch::asm;
|
||||||
|
|
||||||
fn main() {
|
fn bar<const N: usize>() {}
|
||||||
|
|
||||||
|
fn foo<const N: usize>() {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("mov eax, {}", sym main);
|
asm!("mov eax, {}", sym bar::<N>);
|
||||||
|
//~^ ERROR sym operands for inline assembly are unstable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
asm!("mov eax, {}", sym foo::<0>);
|
||||||
//~^ ERROR sym operands for inline assembly are unstable
|
//~^ ERROR sym operands for inline assembly are unstable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
error[E0658]: sym operands for inline assembly are unstable
|
error[E0658]: sym operands for inline assembly are unstable
|
||||||
--> $DIR/feature-gate-asm_sym.rs:7:29
|
--> $DIR/feature-gate-asm_sym.rs:9:29
|
||||||
|
|
|
|
||||||
LL | asm!("mov eax, {}", sym main);
|
LL | asm!("mov eax, {}", sym bar::<N>);
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: see issue #93333 <https://github.com/rust-lang/rust/issues/93333> for more information
|
= note: see issue #93333 <https://github.com/rust-lang/rust/issues/93333> for more information
|
||||||
= help: add `#![feature(asm_sym)]` to the crate attributes to enable
|
= help: add `#![feature(asm_sym)]` to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to previous error
|
error[E0658]: sym operands for inline assembly are unstable
|
||||||
|
--> $DIR/feature-gate-asm_sym.rs:16:29
|
||||||
|
|
|
||||||
|
LL | asm!("mov eax, {}", sym foo::<0>);
|
||||||
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #93333 <https://github.com/rust-lang/rust/issues/93333> for more information
|
||||||
|
= help: add `#![feature(asm_sym)]` to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user