Rollup merge of #99124 - compiler-errors:issue-99122, r=oli-obk

Fix sized check ICE in asm check

Fixes (beta nominated, so doesn't close) #99122

1. Moves a check for unresolved inference variables to _before_ other checks that could possibly ICE. We're not changing behavior here, just doing the same thing earlier in the function.
2. Erases region variables in sized check (which are not resolved at this point) because rustc will also ICE when region vars are passed to a query which does not canonicalize them.
This commit is contained in:
Matthias Krüger 2022-07-11 22:39:06 +02:00 committed by GitHub
commit 7151aaf940
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 21 deletions

View File

@ -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) {

View File

@ -0,0 +1,21 @@
// check-pass
// needs-asm-support
// only-x86_64
// 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() {}

View File

@ -0,0 +1,13 @@
// needs-asm-support
// only-x86_64
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() {}

View File

@ -0,0 +1,11 @@
error[E0641]: cannot cast to a pointer of an unknown kind
--> $DIR/issue-99122.rs:5: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`.