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/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 6d56445771a07..20d7924d68034 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -2641,10 +2641,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_expr_asm_operand(out_expr, false); } } - hir::InlineAsmOperand::Const { anon_const } - | hir::InlineAsmOperand::SymFn { anon_const } => { - self.to_const(anon_const); - } + // `AnonConst`s have their own body and is type-checked separately. + // As they don't flow into the type system we don't need them to + // be well-formed. + hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {} hir::InlineAsmOperand::SymStatic { .. } => {} } } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 29134bd168cf9..7f43f96c9a2b1 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1556,6 +1556,18 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => { 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, } } 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`. diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.rs b/src/test/ui/feature-gates/feature-gate-asm_const.rs index d41d7b258aafb..936918a3cfc86 100644 --- a/src/test/ui/feature-gates/feature-gate-asm_const.rs +++ b/src/test/ui/feature-gates/feature-gate-asm_const.rs @@ -2,8 +2,14 @@ use std::arch::asm; +unsafe fn foo() { + asm!("mov eax, {}", const N + 1); + //~^ ERROR const operands for inline assembly are unstable +} + fn main() { unsafe { + foo::<0>(); asm!("mov eax, {}", const 123); //~^ ERROR const operands for inline assembly are unstable } diff --git a/src/test/ui/feature-gates/feature-gate-asm_const.stderr b/src/test/ui/feature-gates/feature-gate-asm_const.stderr index 0202ccbe5a2d2..c248374ec4924 100644 --- a/src/test/ui/feature-gates/feature-gate-asm_const.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm_const.stderr @@ -1,5 +1,14 @@ 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 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); | ^^^^^^^^^ @@ -7,6 +16,6 @@ LL | asm!("mov eax, {}", const 123); = note: see issue #93332 for more information = 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`. diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.rs b/src/test/ui/feature-gates/feature-gate-asm_sym.rs index e4d781c685932..0de6b3abb18bb 100644 --- a/src/test/ui/feature-gates/feature-gate-asm_sym.rs +++ b/src/test/ui/feature-gates/feature-gate-asm_sym.rs @@ -2,9 +2,18 @@ use std::arch::asm; +fn bar() {} + +fn foo() { + unsafe { + asm!("mov eax, {}", sym bar::); + //~^ ERROR sym operands for inline assembly are unstable + } +} + fn main() { unsafe { - asm!("mov eax, {}", sym main); + asm!("mov eax, {}", sym foo::<0>); //~^ ERROR sym operands for inline assembly are unstable } } diff --git a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr index 68f2d0f6c18b0..d4b16f60b0b41 100644 --- a/src/test/ui/feature-gates/feature-gate-asm_sym.stderr +++ b/src/test/ui/feature-gates/feature-gate-asm_sym.stderr @@ -1,12 +1,21 @@ 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::); + | ^^^^^^^^^^^^ | = note: see issue #93333 for more information = 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 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`.