Skip to content

Commit f482460

Browse files
committed
Handle asm const similar to inline const
1 parent 6e4adbe commit f482460

File tree

11 files changed

+96
-69
lines changed

11 files changed

+96
-69
lines changed

compiler/rustc_ast_lowering/src/asm.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
195195
}
196196
}
197197
InlineAsmOperand::Const { anon_const } => hir::InlineAsmOperand::Const {
198-
anon_const: self.lower_anon_const_to_anon_const(anon_const),
198+
anon_const: self.lower_const_block(anon_const),
199199
},
200200
InlineAsmOperand::Sym { sym } => {
201201
let static_def_id = self

compiler/rustc_hir/src/hir.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3506,7 +3506,7 @@ pub enum InlineAsmOperand<'hir> {
35063506
out_expr: Option<&'hir Expr<'hir>>,
35073507
},
35083508
Const {
3509-
anon_const: &'hir AnonConst,
3509+
anon_const: ConstBlock,
35103510
},
35113511
SymFn {
35123512
expr: &'hir Expr<'hir>,

compiler/rustc_hir/src/intravisit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1447,7 +1447,7 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>(
14471447
visit_opt!(visitor, visit_expr, out_expr);
14481448
}
14491449
InlineAsmOperand::Const { anon_const, .. } => {
1450-
try_visit!(visitor.visit_anon_const(anon_const));
1450+
try_visit!(visitor.visit_inline_const(anon_const));
14511451
}
14521452
InlineAsmOperand::SymFn { expr, .. } => {
14531453
try_visit!(visitor.visit_expr(expr));

compiler/rustc_hir_analysis/src/check/intrinsicck.rs

+25-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::assert_matches::debug_assert_matches;
2-
31
use rustc_abi::FieldIdx;
42
use rustc_ast::InlineAsmTemplatePiece;
53
use rustc_data_structures::fx::FxIndexSet;
@@ -21,6 +19,7 @@ pub struct InlineAsmCtxt<'a, 'tcx: 'a> {
2119
typing_env: ty::TypingEnv<'tcx>,
2220
target_features: &'tcx FxIndexSet<Symbol>,
2321
expr_ty: Box<dyn Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a>,
22+
node_ty: Box<dyn Fn(hir::HirId) -> Ty<'tcx> + 'a>,
2423
}
2524

2625
enum NonAsmTypeReason<'tcx> {
@@ -35,20 +34,26 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
3534
tcx: TyCtxt<'tcx>,
3635
def_id: LocalDefId,
3736
typing_env: ty::TypingEnv<'tcx>,
38-
get_operand_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
37+
expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
38+
node_ty: impl Fn(hir::HirId) -> Ty<'tcx> + 'a,
3939
) -> Self {
4040
InlineAsmCtxt {
4141
tcx,
4242
typing_env,
4343
target_features: tcx.asm_target_features(def_id),
44-
expr_ty: Box::new(get_operand_ty),
44+
expr_ty: Box::new(expr_ty),
45+
node_ty: Box::new(node_ty),
4546
}
4647
}
4748

4849
fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> {
4950
(self.expr_ty)(expr)
5051
}
5152

53+
fn node_ty(&self, hir_id: hir::HirId) -> Ty<'tcx> {
54+
(self.node_ty)(hir_id)
55+
}
56+
5257
// FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
5358
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
5459
// Type still may have region variables, but `Sized` does not depend
@@ -487,12 +492,23 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
487492
);
488493
}
489494
}
490-
// Typeck has checked that Const operands are integers.
491495
hir::InlineAsmOperand::Const { anon_const } => {
492-
debug_assert_matches!(
493-
self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
494-
ty::Error(_) | ty::Int(_) | ty::Uint(_)
495-
);
496+
let ty = self.node_ty(anon_const.hir_id);
497+
match ty.kind() {
498+
ty::Error(_) => {}
499+
_ if ty.is_integral() => {}
500+
_ => {
501+
self.tcx
502+
.dcx()
503+
.struct_span_err(op_sp, "invalid type for `const` operand")
504+
.with_span_label(
505+
self.tcx.def_span(anon_const.def_id),
506+
format!("is {} `{}`", ty.kind().article(), ty),
507+
)
508+
.with_help("`const` operands must be of an integer type")
509+
.emit();
510+
}
511+
}
496512
}
497513
// Typeck has checked that SymFn refers to a function.
498514
hir::InlineAsmOperand::SymFn { expr } => {

compiler/rustc_hir_analysis/src/collect/generics_of.rs

-11
Original file line numberDiff line numberDiff line change
@@ -186,17 +186,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
186186
{
187187
Some(parent_did)
188188
}
189-
// Exclude `GlobalAsm` here which cannot have generics.
190-
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
191-
if asm.operands.iter().any(|(op, _op_sp)| match op {
192-
hir::InlineAsmOperand::Const { anon_const } => {
193-
anon_const.hir_id == hir_id
194-
}
195-
_ => false,
196-
}) =>
197-
{
198-
Some(parent_did)
199-
}
200189
Node::TyPat(_) => Some(parent_did),
201190
_ => None,
202191
}

compiler/rustc_hir_analysis/src/collect/type_of.rs

+1-33
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::query::plumbing::CyclePlaceholder;
88
use rustc_middle::ty::fold::fold_regions;
99
use rustc_middle::ty::print::with_forced_trimmed_paths;
1010
use rustc_middle::ty::util::IntTypeExt;
11-
use rustc_middle::ty::{self, Article, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
11+
use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
1212
use rustc_middle::{bug, span_bug};
1313
use rustc_span::{DUMMY_SP, Ident, Span};
1414

@@ -35,13 +35,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
3535
let parent_node_id = tcx.parent_hir_id(hir_id);
3636
let parent_node = tcx.hir_node(parent_node_id);
3737

38-
let find_const = |&(op, op_sp)| match op {
39-
hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => {
40-
Some((anon_const, op_sp))
41-
}
42-
_ => None,
43-
};
44-
4538
match parent_node {
4639
// Anon consts "inside" the type system.
4740
Node::ConstArg(&ConstArg {
@@ -50,31 +43,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
5043
..
5144
}) if anon_hir_id == hir_id => const_arg_anon_type_of(icx, arg_hir_id, span),
5245

53-
// Anon consts outside the type system.
54-
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
55-
| Node::Item(&Item { kind: ItemKind::GlobalAsm { asm, .. }, .. })
56-
if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) =>
57-
{
58-
let ty = tcx.typeck(def_id).node_type(hir_id);
59-
60-
match ty.kind() {
61-
ty::Error(_) => ty,
62-
ty::Int(_) | ty::Uint(_) => ty,
63-
_ => {
64-
let guar = tcx
65-
.dcx()
66-
.struct_span_err(op_sp, "invalid type for `const` operand")
67-
.with_span_label(
68-
tcx.def_span(anon_const.def_id),
69-
format!("is {} `{}`", ty.kind().article(), ty),
70-
)
71-
.with_help("`const` operands must be of an integer type")
72-
.emit();
73-
74-
Ty::new_error(tcx, guar)
75-
}
76-
}
77-
}
7846
Node::Variant(Variant { disr_expr: Some(e), .. }) if e.hir_id == hir_id => {
7947
tcx.adt_def(tcx.hir_get_parent_item(hir_id)).repr().discr_type().to_ty(tcx)
8048
}

compiler/rustc_hir_pretty/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1414,7 +1414,8 @@ impl<'a> State<'a> {
14141414
hir::InlineAsmOperand::Const { ref anon_const } => {
14151415
s.word("const");
14161416
s.space();
1417-
s.print_anon_const(anon_const);
1417+
// Not using `print_inline_const` to avoid additional `const { ... }`
1418+
s.ann.nested(s, Nested::Body(anon_const.body))
14181419
}
14191420
hir::InlineAsmOperand::SymFn { ref expr } => {
14201421
s.word("sym_fn");

compiler/rustc_hir_typeck/src/expr.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -3778,13 +3778,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
37783778
self.check_expr_asm_operand(out_expr, false);
37793779
}
37803780
}
3781+
hir::InlineAsmOperand::Const { ref anon_const } => {
3782+
self.check_expr_const_block(anon_const, Expectation::NoExpectation);
3783+
}
37813784
hir::InlineAsmOperand::SymFn { expr } => {
37823785
self.check_expr(expr);
37833786
}
3784-
// `AnonConst`s have their own body and is type-checked separately.
3785-
// As they don't flow into the type system we don't need them to
3786-
// be well-formed.
3787-
hir::InlineAsmOperand::Const { .. } => {}
37883787
hir::InlineAsmOperand::SymStatic { .. } => {}
37893788
hir::InlineAsmOperand::Label { block } => {
37903789
let previous_diverges = self.diverges.get();

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
110110
self.tcx.erase_regions(ty)
111111
}
112112
};
113-
InlineAsmCtxt::new(self.tcx, enclosing_id, self.typing_env(self.param_env), expr_ty)
114-
.check_asm(asm);
113+
let node_ty = |hir_id: HirId| self.typeck_results.borrow().node_type(hir_id);
114+
InlineAsmCtxt::new(
115+
self.tcx,
116+
enclosing_id,
117+
self.typing_env(self.param_env),
118+
expr_ty,
119+
node_ty,
120+
)
121+
.check_asm(asm);
115122
}
116123
}
117124

compiler/rustc_mir_build/src/thir/cx/expr.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -730,12 +730,20 @@ impl<'tcx> ThirBuildCx<'tcx> {
730730
}
731731
}
732732
hir::InlineAsmOperand::Const { ref anon_const } => {
733-
let value =
734-
mir::Const::from_unevaluated(tcx, anon_const.def_id.to_def_id())
735-
.instantiate_identity();
736-
let span = tcx.def_span(anon_const.def_id);
737-
738-
InlineAsmOperand::Const { value, span }
733+
let ty = self.typeck_results.node_type(anon_const.hir_id);
734+
let did = anon_const.def_id.to_def_id();
735+
let typeck_root_def_id = tcx.typeck_root_def_id(did);
736+
let parent_args = tcx.erase_regions(GenericArgs::identity_for_item(
737+
tcx,
738+
typeck_root_def_id,
739+
));
740+
let args =
741+
InlineConstArgs::new(tcx, InlineConstArgsParts { parent_args, ty })
742+
.args;
743+
744+
let uneval = mir::UnevaluatedConst::new(did, args);
745+
let value = mir::Const::Unevaluated(uneval, ty);
746+
InlineAsmOperand::Const { value, span: tcx.def_span(did) }
739747
}
740748
hir::InlineAsmOperand::SymFn { expr } => {
741749
InlineAsmOperand::SymFn { value: self.mirror_expr(expr) }

compiler/rustc_resolve/src/def_collector.rs

+39
Original file line numberDiff line numberDiff line change
@@ -459,4 +459,43 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
459459
visit::walk_attribute(self, attr);
460460
self.in_attr = orig_in_attr;
461461
}
462+
463+
fn visit_inline_asm(&mut self, asm: &'a InlineAsm) {
464+
let InlineAsm {
465+
asm_macro: _,
466+
template: _,
467+
template_strs: _,
468+
operands,
469+
clobber_abis: _,
470+
options: _,
471+
line_spans: _,
472+
} = asm;
473+
for (op, _span) in operands {
474+
match op {
475+
InlineAsmOperand::In { expr, reg: _ }
476+
| InlineAsmOperand::Out { expr: Some(expr), reg: _, late: _ }
477+
| InlineAsmOperand::InOut { expr, reg: _, late: _ } => {
478+
self.visit_expr(expr);
479+
}
480+
InlineAsmOperand::Out { expr: None, reg: _, late: _ } => {}
481+
InlineAsmOperand::SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
482+
self.visit_expr(in_expr);
483+
if let Some(expr) = out_expr {
484+
self.visit_expr(expr);
485+
}
486+
}
487+
InlineAsmOperand::Const { anon_const } => {
488+
let def = self.create_def(
489+
anon_const.id,
490+
kw::Empty,
491+
DefKind::InlineConst,
492+
anon_const.value.span,
493+
);
494+
self.with_parent(def, |this| visit::walk_anon_const(this, anon_const));
495+
}
496+
InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
497+
InlineAsmOperand::Label { block } => self.visit_block(block),
498+
}
499+
}
500+
}
462501
}

0 commit comments

Comments
 (0)