1
Fork 0

Pass InferCtxt to InlineAsmCtxt to properly taint on error

Split up some of the tests bc tainting causes some errors to become
suppressed
This commit is contained in:
Michael Goulet 2025-03-06 22:01:01 +00:00
parent 2b285cd5f0
commit bc4f0bb486
8 changed files with 109 additions and 79 deletions

View file

@ -3,8 +3,11 @@ use rustc_ast::InlineAsmTemplatePiece;
use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{self as hir, LangItem}; use rustc_hir::{self as hir, LangItem};
use rustc_infer::infer::InferCtxt;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy}; use rustc_middle::ty::{
self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, TypeckResults, UintTy,
};
use rustc_session::lint; use rustc_session::lint;
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::{Symbol, sym}; use rustc_span::{Symbol, sym};
@ -14,12 +17,11 @@ use rustc_target::asm::{
use crate::errors::RegisterTypeUnstable; use crate::errors::RegisterTypeUnstable;
pub struct InlineAsmCtxt<'a, 'tcx: 'a> { pub struct InlineAsmCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
target_features: &'tcx FxIndexSet<Symbol>, target_features: &'tcx FxIndexSet<Symbol>,
expr_ty: Box<dyn Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a>, infcx: &'a InferCtxt<'tcx>,
node_ty: Box<dyn Fn(hir::HirId) -> Ty<'tcx> + 'a>, typeck_results: &'a TypeckResults<'tcx>,
} }
enum NonAsmTypeReason<'tcx> { enum NonAsmTypeReason<'tcx> {
@ -31,34 +33,38 @@ enum NonAsmTypeReason<'tcx> {
impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
pub fn new( pub fn new(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId, def_id: LocalDefId,
infcx: &'a InferCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>, typing_env: ty::TypingEnv<'tcx>,
expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a, typeck_results: &'a TypeckResults<'tcx>,
node_ty: impl Fn(hir::HirId) -> Ty<'tcx> + 'a,
) -> Self { ) -> Self {
InlineAsmCtxt { InlineAsmCtxt {
tcx,
typing_env, typing_env,
target_features: tcx.asm_target_features(def_id), target_features: infcx.tcx.asm_target_features(def_id),
expr_ty: Box::new(expr_ty), infcx,
node_ty: Box::new(node_ty), typeck_results,
} }
} }
fn tcx(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> { fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> {
(self.expr_ty)(expr) let ty = self.typeck_results.expr_ty_adjusted(expr);
let ty = self.infcx.resolve_vars_if_possible(ty);
if ty.has_non_region_infer() {
Ty::new_misc_error(self.tcx())
} else {
self.tcx().erase_regions(ty)
} }
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 == ()` // FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool { fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
// Type still may have region variables, but `Sized` does not depend // Type still may have region variables, but `Sized` does not depend
// on those, so just erase them before querying. // on those, so just erase them before querying.
if ty.is_sized(self.tcx, self.typing_env) { if ty.is_sized(self.tcx(), self.typing_env) {
return true; return true;
} }
if let ty::Foreign(..) = ty.kind() { if let ty::Foreign(..) = ty.kind() {
@ -68,7 +74,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
} }
fn get_asm_ty(&self, ty: Ty<'tcx>) -> Result<InlineAsmType, NonAsmTypeReason<'tcx>> { fn get_asm_ty(&self, ty: Ty<'tcx>) -> Result<InlineAsmType, NonAsmTypeReason<'tcx>> {
let asm_ty_isize = match self.tcx.sess.target.pointer_width { let asm_ty_isize = match self.tcx().sess.target.pointer_width {
16 => InlineAsmType::I16, 16 => InlineAsmType::I16,
32 => InlineAsmType::I32, 32 => InlineAsmType::I32,
64 => InlineAsmType::I64, 64 => InlineAsmType::I64,
@ -97,12 +103,12 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::Adt(adt, args) if adt.repr().simd() => { ty::Adt(adt, args) if adt.repr().simd() => {
let fields = &adt.non_enum_variant().fields; let fields = &adt.non_enum_variant().fields;
let field = &fields[FieldIdx::ZERO]; let field = &fields[FieldIdx::ZERO];
let elem_ty = field.ty(self.tcx, args); let elem_ty = field.ty(self.tcx(), args);
let (size, ty) = match elem_ty.kind() { let (size, ty) = match elem_ty.kind() {
ty::Array(ty, len) => { ty::Array(ty, len) => {
let len = self.tcx.normalize_erasing_regions(self.typing_env, *len); let len = self.tcx().normalize_erasing_regions(self.typing_env, *len);
if let Some(len) = len.try_to_target_usize(self.tcx) { if let Some(len) = len.try_to_target_usize(self.tcx()) {
(len, *ty) (len, *ty)
} else { } else {
return Err(NonAsmTypeReason::UnevaluatedSIMDArrayLength( return Err(NonAsmTypeReason::UnevaluatedSIMDArrayLength(
@ -122,7 +128,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
Ok(InlineAsmType::VecI128(size)) Ok(InlineAsmType::VecI128(size))
} }
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => { ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => {
Ok(match self.tcx.sess.target.pointer_width { Ok(match self.tcx().sess.target.pointer_width {
16 => InlineAsmType::VecI16(size), 16 => InlineAsmType::VecI16(size),
32 => InlineAsmType::VecI32(size), 32 => InlineAsmType::VecI32(size),
64 => InlineAsmType::VecI64(size), 64 => InlineAsmType::VecI64(size),
@ -159,9 +165,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// `!` is allowed for input but not for output (issue #87802) // `!` is allowed for input but not for output (issue #87802)
ty::Never if is_input => return None, ty::Never if is_input => return None,
_ if ty.references_error() => return None, _ if ty.references_error() => return None,
ty::Adt(adt, args) if self.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => { ty::Adt(adt, args) if self.tcx().is_lang_item(adt.did(), LangItem::MaybeUninit) => {
let fields = &adt.non_enum_variant().fields; let fields = &adt.non_enum_variant().fields;
let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx, args); let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx(), args);
// FIXME: Are we just trying to map to the `T` in `MaybeUninit<T>`? // FIXME: Are we just trying to map to the `T` in `MaybeUninit<T>`?
// If so, just get it from the args. // If so, just get it from the args.
let ty::Adt(ty, args) = ty.kind() else { let ty::Adt(ty, args) = ty.kind() else {
@ -172,7 +178,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
"expected first field of `MaybeUninit` to be `ManuallyDrop`" "expected first field of `MaybeUninit` to be `ManuallyDrop`"
); );
let fields = &ty.non_enum_variant().fields; let fields = &ty.non_enum_variant().fields;
let ty = fields[FieldIdx::ZERO].ty(self.tcx, args); let ty = fields[FieldIdx::ZERO].ty(self.tcx(), args);
self.get_asm_ty(ty) self.get_asm_ty(ty)
} }
_ => self.get_asm_ty(ty), _ => self.get_asm_ty(ty),
@ -183,9 +189,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
match reason { match reason {
NonAsmTypeReason::UnevaluatedSIMDArrayLength(did, len) => { NonAsmTypeReason::UnevaluatedSIMDArrayLength(did, len) => {
let msg = format!("cannot evaluate SIMD vector length `{len}`"); let msg = format!("cannot evaluate SIMD vector length `{len}`");
self.tcx self.infcx
.dcx() .dcx()
.struct_span_err(self.tcx.def_span(did), msg) .struct_span_err(self.tcx().def_span(did), msg)
.with_span_note( .with_span_note(
expr.span, expr.span,
"SIMD vector length needs to be known statically for use in `asm!`", "SIMD vector length needs to be known statically for use in `asm!`",
@ -194,7 +200,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
} }
NonAsmTypeReason::Invalid(ty) => { NonAsmTypeReason::Invalid(ty) => {
let msg = format!("cannot use value of type `{ty}` for inline assembly"); let msg = format!("cannot use value of type `{ty}` for inline assembly");
self.tcx.dcx().struct_span_err(expr.span, msg).with_note( self.infcx.dcx().struct_span_err(expr.span, msg).with_note(
"only integers, floats, SIMD vectors, pointers and function pointers \ "only integers, floats, SIMD vectors, pointers and function pointers \
can be used as arguments for inline assembly", can be used as arguments for inline assembly",
).emit(); ).emit();
@ -203,7 +209,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let msg = format!( let msg = format!(
"cannot use value of unsized pointer type `{ty}` for inline assembly" "cannot use value of unsized pointer type `{ty}` for inline assembly"
); );
self.tcx self.infcx
.dcx() .dcx()
.struct_span_err(expr.span, msg) .struct_span_err(expr.span, msg)
.with_note("only sized pointers can be used in inline assembly") .with_note("only sized pointers can be used in inline assembly")
@ -213,8 +219,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
let msg = format!( let msg = format!(
"cannot use SIMD vector with element type `{ty}` for inline assembly" "cannot use SIMD vector with element type `{ty}` for inline assembly"
); );
self.tcx.dcx() self.infcx.dcx()
.struct_span_err(self.tcx.def_span(did), msg).with_span_note( .struct_span_err(self.tcx().def_span(did), msg).with_span_note(
expr.span, expr.span,
"only integers, floats, SIMD vectors, pointers and function pointers \ "only integers, floats, SIMD vectors, pointers and function pointers \
can be used as arguments for inline assembly", can be used as arguments for inline assembly",
@ -227,9 +233,9 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// Check that the type implements Copy. The only case where this can // Check that the type implements Copy. The only case where this can
// possibly fail is for SIMD types which don't #[derive(Copy)]. // possibly fail is for SIMD types which don't #[derive(Copy)].
if !self.tcx.type_is_copy_modulo_regions(self.typing_env, ty) { if !self.tcx().type_is_copy_modulo_regions(self.typing_env, ty) {
let msg = "arguments for inline assembly must be copyable"; let msg = "arguments for inline assembly must be copyable";
self.tcx self.infcx
.dcx() .dcx()
.struct_span_err(expr.span, msg) .struct_span_err(expr.span, msg)
.with_note(format!("`{ty}` does not implement the Copy trait")) .with_note(format!("`{ty}` does not implement the Copy trait"))
@ -249,7 +255,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
if in_asm_ty != asm_ty { if in_asm_ty != asm_ty {
let msg = "incompatible types for asm inout argument"; let msg = "incompatible types for asm inout argument";
let in_expr_ty = self.expr_ty(in_expr); let in_expr_ty = self.expr_ty(in_expr);
self.tcx self.infcx
.dcx() .dcx()
.struct_span_err(vec![in_expr.span, expr.span], msg) .struct_span_err(vec![in_expr.span, expr.span], msg)
.with_span_label(in_expr.span, format!("type `{in_expr_ty}`")) .with_span_label(in_expr.span, format!("type `{in_expr_ty}`"))
@ -268,21 +274,21 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
// Check the type against the list of types supported by the selected // Check the type against the list of types supported by the selected
// register class. // register class.
let asm_arch = self.tcx.sess.asm_arch.unwrap(); let asm_arch = self.tcx().sess.asm_arch.unwrap();
let allow_experimental_reg = self.tcx.features().asm_experimental_reg(); let allow_experimental_reg = self.tcx().features().asm_experimental_reg();
let reg_class = reg.reg_class(); let reg_class = reg.reg_class();
let supported_tys = reg_class.supported_types(asm_arch, allow_experimental_reg); let supported_tys = reg_class.supported_types(asm_arch, allow_experimental_reg);
let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else { let Some((_, feature)) = supported_tys.iter().find(|&&(t, _)| t == asm_ty) else {
let mut err = if !allow_experimental_reg let mut err = if !allow_experimental_reg
&& reg_class.supported_types(asm_arch, true).iter().any(|&(t, _)| t == asm_ty) && reg_class.supported_types(asm_arch, true).iter().any(|&(t, _)| t == asm_ty)
{ {
self.tcx.sess.create_feature_err( self.tcx().sess.create_feature_err(
RegisterTypeUnstable { span: expr.span, ty }, RegisterTypeUnstable { span: expr.span, ty },
sym::asm_experimental_reg, sym::asm_experimental_reg,
) )
} else { } else {
let msg = format!("type `{ty}` cannot be used with this register class"); let msg = format!("type `{ty}` cannot be used with this register class");
let mut err = self.tcx.dcx().struct_span_err(expr.span, msg); let mut err = self.infcx.dcx().struct_span_err(expr.span, msg);
let supported_tys: Vec<_> = let supported_tys: Vec<_> =
supported_tys.iter().map(|(t, _)| t.to_string()).collect(); supported_tys.iter().map(|(t, _)| t.to_string()).collect();
err.note(format!( err.note(format!(
@ -312,7 +318,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
if let Some(feature) = feature { if let Some(feature) = feature {
if !self.target_features.contains(feature) { if !self.target_features.contains(feature) {
let msg = format!("`{feature}` target feature is not enabled"); let msg = format!("`{feature}` target feature is not enabled");
self.tcx self.infcx
.dcx() .dcx()
.struct_span_err(expr.span, msg) .struct_span_err(expr.span, msg)
.with_note(format!( .with_note(format!(
@ -349,7 +355,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
result: default_result, result: default_result,
size: default_size, size: default_size,
} = reg_class.default_modifier(asm_arch).unwrap(); } = reg_class.default_modifier(asm_arch).unwrap();
self.tcx.node_span_lint( self.tcx().node_span_lint(
lint::builtin::ASM_SUB_REGISTER, lint::builtin::ASM_SUB_REGISTER,
expr.hir_id, expr.hir_id,
spans, spans,
@ -371,11 +377,11 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
} }
pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) { pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) {
let Some(asm_arch) = self.tcx.sess.asm_arch else { let Some(asm_arch) = self.tcx().sess.asm_arch else {
self.tcx.dcx().delayed_bug("target architecture does not support asm"); self.infcx.dcx().delayed_bug("target architecture does not support asm");
return; return;
}; };
let allow_experimental_reg = self.tcx.features().asm_experimental_reg(); let allow_experimental_reg = self.tcx().features().asm_experimental_reg();
for (idx, &(op, op_sp)) in asm.operands.iter().enumerate() { for (idx, &(op, op_sp)) in asm.operands.iter().enumerate() {
// Validate register classes against currently enabled target // Validate register classes against currently enabled target
// features. We check that at least one type is available for // features. We check that at least one type is available for
@ -398,13 +404,13 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
} }
if let Err(msg) = reg.validate( if let Err(msg) = reg.validate(
asm_arch, asm_arch,
self.tcx.sess.relocation_model(), self.tcx().sess.relocation_model(),
self.target_features, self.target_features,
&self.tcx.sess.target, &self.tcx().sess.target,
op.is_clobber(), op.is_clobber(),
) { ) {
let msg = format!("cannot use register `{}`: {}", reg.name(), msg); let msg = format!("cannot use register `{}`: {}", reg.name(), msg);
self.tcx.dcx().span_err(op_sp, msg); self.infcx.dcx().span_err(op_sp, msg);
continue; continue;
} }
} }
@ -444,7 +450,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
reg_class.name(), reg_class.name(),
feature feature
); );
self.tcx.dcx().span_err(op_sp, msg); self.infcx.dcx().span_err(op_sp, msg);
// register isn't enabled, don't do more checks // register isn't enabled, don't do more checks
continue; continue;
} }
@ -458,7 +464,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
.intersperse(", ") .intersperse(", ")
.collect::<String>(), .collect::<String>(),
); );
self.tcx.dcx().span_err(op_sp, msg); self.infcx.dcx().span_err(op_sp, msg);
// register isn't enabled, don't do more checks // register isn't enabled, don't do more checks
continue; continue;
} }
@ -493,16 +499,16 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
} }
} }
hir::InlineAsmOperand::Const { anon_const } => { hir::InlineAsmOperand::Const { anon_const } => {
let ty = self.node_ty(anon_const.hir_id); let ty = self.expr_ty(self.tcx().hir_body(anon_const.body).value);
match ty.kind() { match ty.kind() {
ty::Error(_) => {} ty::Error(_) => {}
_ if ty.is_integral() => {} _ if ty.is_integral() => {}
_ => { _ => {
self.tcx self.infcx
.dcx() .dcx()
.struct_span_err(op_sp, "invalid type for `const` operand") .struct_span_err(op_sp, "invalid type for `const` operand")
.with_span_label( .with_span_label(
self.tcx.def_span(anon_const.def_id), self.tcx().def_span(anon_const.def_id),
format!("is {} `{}`", ty.kind().article(), ty), format!("is {} `{}`", ty.kind().article(), ty),
) )
.with_help("`const` operands must be of an integer type") .with_help("`const` operands must be of an integer type")
@ -517,7 +523,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::FnDef(..) => {} ty::FnDef(..) => {}
ty::Error(_) => {} ty::Error(_) => {}
_ => { _ => {
self.tcx self.infcx
.dcx() .dcx()
.struct_span_err(op_sp, "invalid `sym` operand") .struct_span_err(op_sp, "invalid `sym` operand")
.with_span_label( .with_span_label(

View file

@ -99,22 +99,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len()); debug!("FnCtxt::check_asm: {} deferred checks", deferred_asm_checks.len());
for (asm, hir_id) in deferred_asm_checks.drain(..) { for (asm, hir_id) in deferred_asm_checks.drain(..) {
let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id); let enclosing_id = self.tcx.hir_enclosing_body_owner(hir_id);
let expr_ty = |expr: &hir::Expr<'tcx>| {
let ty = self.typeck_results.borrow().expr_ty_adjusted(expr);
let ty = self.resolve_vars_if_possible(ty);
if ty.has_non_region_infer() {
Ty::new_misc_error(self.tcx)
} else {
self.tcx.erase_regions(ty)
}
};
let node_ty = |hir_id: HirId| self.typeck_results.borrow().node_type(hir_id);
InlineAsmCtxt::new( InlineAsmCtxt::new(
self.tcx,
enclosing_id, enclosing_id,
&self.infcx,
self.typing_env(self.param_env), self.typing_env(self.param_env),
expr_ty, &*self.typeck_results.borrow(),
node_ty,
) )
.check_asm(asm); .check_asm(asm);
} }

View file

@ -14,7 +14,7 @@ global_asm!("{}", const 0f32);
global_asm!("{}", const 0 as *mut u8); global_asm!("{}", const 0 as *mut u8);
//~^ ERROR invalid type for `const` operand //~^ ERROR invalid type for `const` operand
fn main() { fn test1() {
unsafe { unsafe {
// Const operands must be integers and must be constants. // Const operands must be integers and must be constants.
@ -27,7 +27,11 @@ fn main() {
//~^ ERROR invalid type for `const` operand //~^ ERROR invalid type for `const` operand
asm!("{}", const &0); asm!("{}", const &0);
//~^ ERROR invalid type for `const` operand //~^ ERROR invalid type for `const` operand
}
}
fn test2() {
unsafe {
// Constants must be... constant // Constants must be... constant
let x = 0; let x = 0;
@ -47,3 +51,5 @@ fn main() {
//~^ ERROR attempt to use a non-constant value in a constant //~^ ERROR attempt to use a non-constant value in a constant
} }
} }
fn main() {}

View file

@ -1,5 +1,5 @@
error[E0435]: attempt to use a non-constant value in a constant error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/invalid-const-operand.rs:40:26 --> $DIR/invalid-const-operand.rs:44:26
| |
LL | asm!("{}", const x); LL | asm!("{}", const x);
| ^ non-constant value | ^ non-constant value
@ -11,7 +11,7 @@ LL + const x: /* Type */ = 0;
| |
error[E0435]: attempt to use a non-constant value in a constant error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/invalid-const-operand.rs:43:36 --> $DIR/invalid-const-operand.rs:47:36
| |
LL | asm!("{}", const const_foo(x)); LL | asm!("{}", const const_foo(x));
| ^ non-constant value | ^ non-constant value
@ -23,7 +23,7 @@ LL + const x: /* Type */ = 0;
| |
error[E0435]: attempt to use a non-constant value in a constant error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/invalid-const-operand.rs:46:36 --> $DIR/invalid-const-operand.rs:50:36
| |
LL | asm!("{}", const const_bar(x)); LL | asm!("{}", const const_bar(x));
| ^ non-constant value | ^ non-constant value
@ -80,7 +80,7 @@ error: invalid type for `const` operand
LL | asm!("{}", const &0); LL | asm!("{}", const &0);
| ^^^^^^-- | ^^^^^^--
| | | |
| is a `&{integer}` | is a `&i32`
| |
= help: `const` operands must be of an integer type = help: `const` operands must be of an integer type

View file

@ -0,0 +1,13 @@
//@ needs-asm-support
use std::arch::asm;
fn main() {
unsafe {
asm!(
"/* {} */",
sym None::<()>,
//~^ ERROR invalid `sym` operand
);
}
}

View file

@ -0,0 +1,10 @@
error: invalid `sym` operand
--> $DIR/tainting-on-error.rs:9:13
|
LL | sym None::<()>,
| ^^^^^^^^^^^^^^ is an `Option<()>`
|
= help: `sym` operands must refer to either a function or a static
error: aborting due to 1 previous error

View file

@ -7,7 +7,7 @@ use std::arch::{asm, global_asm};
#[repr(simd)] #[repr(simd)]
struct SimdNonCopy([f32; 4]); struct SimdNonCopy([f32; 4]);
fn main() { fn test1() {
unsafe { unsafe {
// Inputs must be initialized // Inputs must be initialized
@ -26,7 +26,11 @@ fn main() {
asm!("{}", in(reg) v[0]); asm!("{}", in(reg) v[0]);
asm!("{}", out(reg) v[0]); asm!("{}", out(reg) v[0]);
asm!("{}", inout(reg) v[0]); asm!("{}", inout(reg) v[0]);
}
}
fn test2() {
unsafe {
// Register operands must be Copy // Register operands must be Copy
asm!("{}", in(xmm_reg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); asm!("{}", in(xmm_reg) SimdNonCopy([0.0, 0.0, 0.0, 0.0]));
@ -68,3 +72,5 @@ fn main() {
asm!("{}", in(reg) u); asm!("{}", in(reg) u);
} }
} }
fn main() {}

View file

@ -1,13 +1,13 @@
error: arguments for inline assembly must be copyable error: arguments for inline assembly must be copyable
--> $DIR/type-check-2.rs:32:32 --> $DIR/type-check-2.rs:36:32
| |
LL | asm!("{}", in(xmm_reg) SimdNonCopy([0.0, 0.0, 0.0, 0.0])); LL | asm!("{}", in(xmm_reg) SimdNonCopy([0.0, 0.0, 0.0, 0.0]));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `SimdNonCopy` does not implement the Copy trait = note: `SimdNonCopy` does not implement the Copy trait
error: cannot use value of type `{closure@$DIR/type-check-2.rs:44:28: 44:36}` for inline assembly error: cannot use value of type `{closure@$DIR/type-check-2.rs:48:28: 48:36}` for inline assembly
--> $DIR/type-check-2.rs:44:28 --> $DIR/type-check-2.rs:48:28
| |
LL | asm!("{}", in(reg) |x: i32| x); LL | asm!("{}", in(reg) |x: i32| x);
| ^^^^^^^^^^ | ^^^^^^^^^^
@ -15,7 +15,7 @@ LL | asm!("{}", in(reg) |x: i32| x);
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `Vec<i32>` for inline assembly error: cannot use value of type `Vec<i32>` for inline assembly
--> $DIR/type-check-2.rs:46:28 --> $DIR/type-check-2.rs:50:28
| |
LL | asm!("{}", in(reg) vec![0]); LL | asm!("{}", in(reg) vec![0]);
| ^^^^^^^ | ^^^^^^^
@ -24,7 +24,7 @@ LL | asm!("{}", in(reg) vec![0]);
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
error: cannot use value of type `(i32, i32, i32)` for inline assembly error: cannot use value of type `(i32, i32, i32)` for inline assembly
--> $DIR/type-check-2.rs:48:28 --> $DIR/type-check-2.rs:52:28
| |
LL | asm!("{}", in(reg) (1, 2, 3)); LL | asm!("{}", in(reg) (1, 2, 3));
| ^^^^^^^^^ | ^^^^^^^^^
@ -32,7 +32,7 @@ LL | asm!("{}", in(reg) (1, 2, 3));
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `[i32; 3]` for inline assembly error: cannot use value of type `[i32; 3]` for inline assembly
--> $DIR/type-check-2.rs:50:28 --> $DIR/type-check-2.rs:54:28
| |
LL | asm!("{}", in(reg) [1, 2, 3]); LL | asm!("{}", in(reg) [1, 2, 3]);
| ^^^^^^^^^ | ^^^^^^^^^
@ -40,7 +40,7 @@ LL | asm!("{}", in(reg) [1, 2, 3]);
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `fn() {main}` for inline assembly error: cannot use value of type `fn() {main}` for inline assembly
--> $DIR/type-check-2.rs:58:31 --> $DIR/type-check-2.rs:62:31
| |
LL | asm!("{}", inout(reg) f); LL | asm!("{}", inout(reg) f);
| ^ | ^
@ -48,7 +48,7 @@ LL | asm!("{}", inout(reg) f);
= note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
error: cannot use value of type `&mut i32` for inline assembly error: cannot use value of type `&mut i32` for inline assembly
--> $DIR/type-check-2.rs:61:31 --> $DIR/type-check-2.rs:65:31
| |
LL | asm!("{}", inout(reg) r); LL | asm!("{}", inout(reg) r);
| ^ | ^