diff --git a/compiler/rustc_typeck/src/check/intrinsicck.rs b/compiler/rustc_typeck/src/check/intrinsicck.rs index cc91f2431e076..a5add1e9a8acb 100644 --- a/compiler/rustc_typeck/src/check/intrinsicck.rs +++ b/compiler/rustc_typeck/src/check/intrinsicck.rs @@ -4,7 +4,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_index::vec::Idx; use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; -use rustc_middle::ty::{self, Article, FloatTy, InferTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy}; +use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitable, UintTy}; use rustc_session::lint; use rustc_span::{Span, Symbol, DUMMY_SP}; use rustc_target::abi::{Pointer, VariantIdx}; @@ -99,8 +99,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } + // FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()` fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool { - if ty.is_sized(self.tcx.at(DUMMY_SP), self.param_env) { + // Type still may have region variables, but `Sized` does not depend + // on those, so just erase them before querying. + if self.tcx.erase_regions(ty).is_sized(self.tcx.at(DUMMY_SP), self.param_env) { return true; } if let ty::Foreign(..) = ty.kind() { @@ -128,30 +131,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 64 => InlineAsmType::I64, _ => unreachable!(), }; + + // Expect types to be fully resolved, no const or type variables. + if ty.has_infer_types_or_consts() { + assert!(self.is_tainted_by_errors()); + return None; + } + let asm_ty = match *ty.kind() { // `!` is allowed for input but not for output (issue #87802) ty::Never if is_input => return None, ty::Error(_) => return None, ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::I8), ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => Some(InlineAsmType::I16), - // Somewhat of a hack: fallback in the presence of errors does not actually - // fall back to i32, but to ty::Error. For integer inference variables this - // means that they don't get any fallback and stay as `{integer}`. - // Since compilation can't succeed anyway, it's fine to use this to avoid printing - // "cannot use value of type `{integer}`", even though that would absolutely - // work due due i32 fallback if the current function had no other errors. - ty::Infer(InferTy::IntVar(_)) => { - assert!(self.is_tainted_by_errors()); - Some(InlineAsmType::I32) - } ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => Some(InlineAsmType::I32), ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => Some(InlineAsmType::I64), ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => Some(InlineAsmType::I128), ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => Some(asm_ty_isize), - ty::Infer(InferTy::FloatVar(_)) => { - assert!(self.is_tainted_by_errors()); - Some(InlineAsmType::F32) - } ty::Float(FloatTy::F32) => Some(InlineAsmType::F32), ty::Float(FloatTy::F64) => Some(InlineAsmType::F64), ty::FnPtr(_) => Some(asm_ty_isize), @@ -191,6 +187,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, } } + ty::Infer(_) => unreachable!(), _ => None, }; let Some(asm_ty) = asm_ty else { @@ -204,11 +201,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - if ty.has_infer_types_or_consts() { - assert!(self.is_tainted_by_errors()); - return None; - } - // Check that the type implements Copy. The only case where this can // possibly fail is for SIMD types which don't #[derive(Copy)]. if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, DUMMY_SP) { diff --git a/src/test/ui/asm/issue-99122-2.rs b/src/test/ui/asm/issue-99122-2.rs new file mode 100644 index 0000000000000..87ae837a14864 --- /dev/null +++ b/src/test/ui/asm/issue-99122-2.rs @@ -0,0 +1,18 @@ +// check-pass +// This demonstrates why we need to erase regions before sized check in intrinsicck + +struct NoCopy; + +struct Wrap<'a, T, Tail: ?Sized>(&'a T, Tail); + +pub unsafe fn test() { + let i = NoCopy; + let j = Wrap(&i, ()); + let pointer = &j as *const _; + core::arch::asm!( + "nop", + in("eax") pointer, + ); +} + +fn main() {} diff --git a/src/test/ui/asm/issue-99122.rs b/src/test/ui/asm/issue-99122.rs new file mode 100644 index 0000000000000..588d63069570f --- /dev/null +++ b/src/test/ui/asm/issue-99122.rs @@ -0,0 +1,10 @@ +pub unsafe fn test() { + let pointer = 1u32 as *const _; + //~^ ERROR cannot cast to a pointer of an unknown kind + core::arch::asm!( + "nop", + in("eax") pointer, + ); +} + +fn main() {} diff --git a/src/test/ui/asm/issue-99122.stderr b/src/test/ui/asm/issue-99122.stderr new file mode 100644 index 0000000000000..bef8f34a52537 --- /dev/null +++ b/src/test/ui/asm/issue-99122.stderr @@ -0,0 +1,11 @@ +error[E0641]: cannot cast to a pointer of an unknown kind + --> $DIR/issue-99122.rs:2:27 + | +LL | let pointer = 1u32 as *const _; + | ^^^^^^^^ needs more type information + | + = note: the type information given here is insufficient to check whether the pointer cast is valid + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0641`.