Permit asm_const and asm_sym to reference outer generic params

This commit is contained in:
Gary Guo 2022-05-07 02:57:42 +01:00
parent d93b03793d
commit b1c6c0648e
6 changed files with 60 additions and 47 deletions

View file

@ -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);
} }

View file

@ -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.

View file

@ -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| {

View 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>();
}
}

View file

@ -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.

View file

@ -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`.