From b1c6c0648e430ffc8a9acd5e90c7984d76067cd8 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 7 May 2022 02:57:42 +0100 Subject: [PATCH] Permit asm_const and asm_sym to reference outer generic params --- compiler/rustc_ast/src/visit.rs | 4 ++-- compiler/rustc_resolve/src/ident.rs | 34 ++--------------------------- compiler/rustc_resolve/src/late.rs | 23 +++++++++++++++++++ src/test/ui/asm/generic-const.rs | 30 +++++++++++++++++++++++++ src/test/ui/asm/type-check-1.rs | 1 - src/test/ui/asm/type-check-1.stderr | 15 +++---------- 6 files changed, 60 insertions(+), 47 deletions(-) create mode 100644 src/test/ui/asm/generic-const.rs diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index cc772ac74f251..42213cf69661b 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -326,7 +326,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { ItemKind::ForeignMod(ref foreign_module) => { 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, .. }) => { visitor.visit_generics(generics); 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::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) => { walk_list!(visitor, visit_expr, optional_expression); } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index baaab33d71f50..7ac1bb441c68d 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1171,6 +1171,7 @@ impl<'a> Resolver<'a> { | AssocItemRibKind | ModuleRibKind(..) | MacroDefinition(..) + | InlineAsmSymRibKind | ForwardGenericParamBanRibKind => { // Nothing to do. Continue. continue; @@ -1216,22 +1217,6 @@ impl<'a> Resolver<'a> { } 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 { @@ -1262,6 +1247,7 @@ impl<'a> Resolver<'a> { | AssocItemRibKind | ModuleRibKind(..) | MacroDefinition(..) + | InlineAsmSymRibKind | ForwardGenericParamBanRibKind => continue, ConstantItemRibKind(trivial, _) => { @@ -1296,22 +1282,6 @@ impl<'a> Resolver<'a> { } 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. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 723e66e9ef618..2712bfeb7b311 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -918,6 +918,29 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { 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) { // This is similar to the code for AnonConst. self.with_rib(ValueNS, InlineAsmSymRibKind, |this| { diff --git a/src/test/ui/asm/generic-const.rs b/src/test/ui/asm/generic-const.rs new file mode 100644 index 0000000000000..55c5587804b32 --- /dev/null +++ b/src/test/ui/asm/generic-const.rs @@ -0,0 +1,30 @@ +// needs-asm-support +// build-pass + +#![feature(asm_const, asm_sym)] + +use std::arch::asm; + +fn foofoo() {} + +unsafe fn foo() { + asm!("/* {0} */", const N); + asm!("/* {0} */", const N + 1); + asm!("/* {0} */", sym foofoo::); +} + +fn barbar() {} + +unsafe fn bar() { + asm!("/* {0} */", const std::mem::size_of::()); + asm!("/* {0} */", const std::mem::size_of::<(T, T)>()); + asm!("/* {0} */", sym barbar::); + asm!("/* {0} */", sym barbar::<(T, T)>); +} + +fn main() { + unsafe { + foo::<0>(); + bar::(); + } +} diff --git a/src/test/ui/asm/type-check-1.rs b/src/test/ui/asm/type-check-1.rs index 9f0121e11b447..367a035387bc8 100644 --- a/src/test/ui/asm/type-check-1.rs +++ b/src/test/ui/asm/type-check-1.rs @@ -63,7 +63,6 @@ fn main() { unsafe fn generic() { asm!("{}", sym generic::); - //~^ generic parameters may not be used in const operations } // Const operands must be integers and must be constants. diff --git a/src/test/ui/asm/type-check-1.stderr b/src/test/ui/asm/type-check-1.stderr index 7dba69fb74592..bf5ea1befb69e 100644 --- a/src/test/ui/asm/type-check-1.stderr +++ b/src/test/ui/asm/type-check-1.stderr @@ -33,15 +33,6 @@ LL | asm!("{}", sym x); | = 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::); - | ^ 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 --> $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 error[E0308]: mismatched types - --> $DIR/type-check-1.rs:74:25 + --> $DIR/type-check-1.rs:73:25 | LL | global_asm!("{}", const 0f32); | ^^^^ expected integer, found `f32` 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); | ^^^^^^^^^^^^ expected integer, found *-ptr @@ -123,7 +114,7 @@ LL | global_asm!("{}", const 0 as *mut u8); = note: expected type `{integer}` 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. For more information about an error, try `rustc --explain E0277`.