1
Fork 0

Handle asm const similar to inline const

This commit is contained in:
Gary Guo 2025-02-26 16:28:37 +00:00
parent 6e4adbed76
commit f482460f92
11 changed files with 95 additions and 68 deletions

View file

@ -1,5 +1,3 @@
use std::assert_matches::debug_assert_matches;
use rustc_abi::FieldIdx;
use rustc_ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxIndexSet;
@ -21,6 +19,7 @@ pub struct InlineAsmCtxt<'a, 'tcx: 'a> {
typing_env: ty::TypingEnv<'tcx>,
target_features: &'tcx FxIndexSet<Symbol>,
expr_ty: Box<dyn Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
node_ty: Box<dyn Fn(hir::HirId) -> Ty<'tcx> + 'a>,
}
enum NonAsmTypeReason<'tcx> {
@ -35,13 +34,15 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
typing_env: ty::TypingEnv<'tcx>,
get_operand_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
node_ty: impl Fn(hir::HirId) -> Ty<'tcx> + 'a,
) -> Self {
InlineAsmCtxt {
tcx,
typing_env,
target_features: tcx.asm_target_features(def_id),
expr_ty: Box::new(get_operand_ty),
expr_ty: Box::new(expr_ty),
node_ty: Box::new(node_ty),
}
}
@ -49,6 +50,10 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
(self.expr_ty)(expr)
}
fn node_ty(&self, hir_id: hir::HirId) -> Ty<'tcx> {
(self.node_ty)(hir_id)
}
// FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
// Type still may have region variables, but `Sized` does not depend
@ -487,12 +492,23 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
);
}
}
// Typeck has checked that Const operands are integers.
hir::InlineAsmOperand::Const { anon_const } => {
debug_assert_matches!(
self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
ty::Error(_) | ty::Int(_) | ty::Uint(_)
);
let ty = self.node_ty(anon_const.hir_id);
match ty.kind() {
ty::Error(_) => {}
_ if ty.is_integral() => {}
_ => {
self.tcx
.dcx()
.struct_span_err(op_sp, "invalid type for `const` operand")
.with_span_label(
self.tcx.def_span(anon_const.def_id),
format!("is {} `{}`", ty.kind().article(), ty),
)
.with_help("`const` operands must be of an integer type")
.emit();
}
}
}
// Typeck has checked that SymFn refers to a function.
hir::InlineAsmOperand::SymFn { expr } => {

View file

@ -186,17 +186,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
{
Some(parent_did)
}
// 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 } => {
anon_const.hir_id == hir_id
}
_ => false,
}) =>
{
Some(parent_did)
}
Node::TyPat(_) => Some(parent_did),
_ => None,
}

View file

@ -8,7 +8,7 @@ use rustc_middle::query::plumbing::CyclePlaceholder;
use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use rustc_span::{DUMMY_SP, Ident, Span};
@ -35,13 +35,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
let parent_node_id = tcx.parent_hir_id(hir_id);
let parent_node = tcx.hir_node(parent_node_id);
let find_const = |&(op, op_sp)| match op {
hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => {
Some((anon_const, op_sp))
}
_ => None,
};
match parent_node {
// Anon consts "inside" the type system.
Node::ConstArg(&ConstArg {
@ -50,31 +43,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
..
}) if anon_hir_id == hir_id => const_arg_anon_type_of(icx, arg_hir_id, span),
// Anon consts outside the type system.
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
| Node::Item(&Item { kind: ItemKind::GlobalAsm { asm, .. }, .. })
if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) =>
{
let ty = tcx.typeck(def_id).node_type(hir_id);
match ty.kind() {
ty::Error(_) => ty,
ty::Int(_) | ty::Uint(_) => ty,
_ => {
let guar = tcx
.dcx()
.struct_span_err(op_sp, "invalid type for `const` operand")
.with_span_label(
tcx.def_span(anon_const.def_id),
format!("is {} `{}`", ty.kind().article(), ty),
)
.with_help("`const` operands must be of an integer type")
.emit();
Ty::new_error(tcx, guar)
}
}
}
Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => {
tcx.adt_def(tcx.hir_get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
}