mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Rollup merge of #139025 - compiler-errors:trim-validator-err, r=jieyouxu
Do not trim paths in MIR validator From my inline comment: ``` // The type checker formats a bunch of strings with type names in it, but these strings // are not always going to be encountered on the error path since the inliner also uses // the validator, and there are certain kinds of inlining (even for valid code) that // can cause validation errors (mostly around where clauses and rigid projections). ``` Fixes https://github.com/rust-lang/rust/issues/138979 r? `@jieyouxu`
This commit is contained in:
commit
d837ab4489
@ -12,6 +12,7 @@ use rustc_middle::mir::coverage::CoverageKind;
|
||||
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
|
||||
use rustc_middle::mir::*;
|
||||
use rustc_middle::ty::adjustment::PointerCoercion;
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{
|
||||
self, CoroutineArgsExt, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Upcast, Variance,
|
||||
};
|
||||
@ -56,7 +57,7 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
|
||||
ty::Coroutine(..) => ExternAbi::Rust,
|
||||
// No need to do MIR validation on error bodies
|
||||
ty::Error(_) => return,
|
||||
_ => span_bug!(body.span, "unexpected body ty: {body_ty:?}"),
|
||||
_ => span_bug!(body.span, "unexpected body ty: {body_ty}"),
|
||||
};
|
||||
|
||||
ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi)
|
||||
@ -543,7 +544,13 @@ pub(super) fn validate_types<'tcx>(
|
||||
caller_body: &Body<'tcx>,
|
||||
) -> Vec<(Location, String)> {
|
||||
let mut type_checker = TypeChecker { body, caller_body, tcx, typing_env, failures: Vec::new() };
|
||||
type_checker.visit_body(body);
|
||||
// The type checker formats a bunch of strings with type names in it, but these strings
|
||||
// are not always going to be encountered on the error path since the inliner also uses
|
||||
// the validator, and there are certain kinds of inlining (even for valid code) that
|
||||
// can cause validation errors (mostly around where clauses and rigid projections).
|
||||
with_no_trimmed_paths!({
|
||||
type_checker.visit_body(body);
|
||||
});
|
||||
type_checker.failures
|
||||
}
|
||||
|
||||
@ -655,7 +662,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
ProjectionElem::Index(index) => {
|
||||
let index_ty = self.body.local_decls[index].ty;
|
||||
if index_ty != self.tcx.types.usize {
|
||||
self.fail(location, format!("bad index ({index_ty:?} != usize)"))
|
||||
self.fail(location, format!("bad index ({index_ty} != usize)"))
|
||||
}
|
||||
}
|
||||
ProjectionElem::Deref
|
||||
@ -664,10 +671,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;
|
||||
|
||||
if base_ty.is_box() {
|
||||
self.fail(
|
||||
location,
|
||||
format!("{base_ty:?} dereferenced after ElaborateBoxDerefs"),
|
||||
)
|
||||
self.fail(location, format!("{base_ty} dereferenced after ElaborateBoxDerefs"))
|
||||
}
|
||||
}
|
||||
ProjectionElem::Field(f, ty) => {
|
||||
@ -680,7 +684,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
this.fail(
|
||||
location,
|
||||
format!(
|
||||
"Field projection `{place_ref:?}.{f:?}` specified type `{ty:?}`, but actual type is `{f_ty:?}`"
|
||||
"Field projection `{place_ref:?}.{f:?}` specified type `{ty}`, but actual type is `{f_ty}`"
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -806,7 +810,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"Failed subtyping {ty:#?} and {:#?}",
|
||||
"Failed subtyping {ty} and {}",
|
||||
place_ref.ty(&self.body.local_decls, self.tcx).ty
|
||||
),
|
||||
)
|
||||
@ -826,7 +830,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty:?}"
|
||||
"Cannot unwrap unsafe binder {binder_ty:?} into type {unwrapped_ty}"
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -841,7 +845,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
if ty.is_union() || ty.is_enum() {
|
||||
self.fail(
|
||||
START_BLOCK.start_location(),
|
||||
format!("invalid type {ty:?} in debuginfo for {:?}", debuginfo.name),
|
||||
format!("invalid type {ty} in debuginfo for {:?}", debuginfo.name),
|
||||
);
|
||||
}
|
||||
if projection.is_empty() {
|
||||
@ -1064,15 +1068,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
if !self.mir_assign_valid_types(a, b) {
|
||||
self.fail(
|
||||
location,
|
||||
format!("Cannot {op:?} compare incompatible types {a:?} and {b:?}"),
|
||||
format!("Cannot {op:?} compare incompatible types {a} and {b}"),
|
||||
);
|
||||
}
|
||||
} else if a != b {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"Cannot perform binary op {op:?} on unequal types {a:?} and {b:?}"
|
||||
),
|
||||
format!("Cannot perform binary op {op:?} on unequal types {a} and {b}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1081,7 +1083,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
Offset => {
|
||||
check_kinds!(a, "Cannot offset non-pointer type {:?}", ty::RawPtr(..));
|
||||
if b != self.tcx.types.isize && b != self.tcx.types.usize {
|
||||
self.fail(location, format!("Cannot offset by non-isize type {b:?}"));
|
||||
self.fail(location, format!("Cannot offset by non-isize type {b}"));
|
||||
}
|
||||
}
|
||||
Eq | Lt | Le | Ne | Ge | Gt => {
|
||||
@ -1313,7 +1315,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
{
|
||||
self.fail(
|
||||
location,
|
||||
format!("Cannot transmute from non-`Sized` type {op_ty:?}"),
|
||||
format!("Cannot transmute from non-`Sized` type {op_ty}"),
|
||||
);
|
||||
}
|
||||
if !self
|
||||
@ -1340,7 +1342,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
Rvalue::NullaryOp(NullOp::OffsetOf(indices), container) => {
|
||||
let fail_out_of_bounds = |this: &mut Self, location, field, ty| {
|
||||
this.fail(location, format!("Out of bounds field {field:?} for {ty:?}"));
|
||||
this.fail(location, format!("Out of bounds field {field:?} for {ty}"));
|
||||
};
|
||||
|
||||
let mut current_ty = *container;
|
||||
@ -1374,7 +1376,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
_ => {
|
||||
self.fail(
|
||||
location,
|
||||
format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty:?}"),
|
||||
format!("Cannot get offset ({variant:?}, {field:?}) from type {current_ty}"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -1403,7 +1405,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
if !self.mir_assign_valid_types(unwrapped_ty, binder_inner_ty) {
|
||||
self.fail(
|
||||
location,
|
||||
format!("Cannot wrap {unwrapped_ty:?} into unsafe binder {binder_ty:?}"),
|
||||
format!("Cannot wrap {unwrapped_ty} into unsafe binder {binder_ty:?}"),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1489,24 +1491,27 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
// since CopyNonOverlapping is parametrized by 1 type,
|
||||
// we only need to check that they are equal and not keep an extra parameter.
|
||||
if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) {
|
||||
self.fail(location, format!("bad arg ({op_src_ty:?} != {op_dst_ty:?})"));
|
||||
self.fail(location, format!("bad arg ({op_src_ty} != {op_dst_ty})"));
|
||||
}
|
||||
|
||||
let op_cnt_ty = count.ty(&self.body.local_decls, self.tcx);
|
||||
if op_cnt_ty != self.tcx.types.usize {
|
||||
self.fail(location, format!("bad arg ({op_cnt_ty:?} != usize)"))
|
||||
self.fail(location, format!("bad arg ({op_cnt_ty} != usize)"))
|
||||
}
|
||||
}
|
||||
StatementKind::SetDiscriminant { place, .. } => {
|
||||
if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) {
|
||||
self.fail(location, "`SetDiscriminant`is not allowed until deaggregation");
|
||||
}
|
||||
let pty = place.ty(&self.body.local_decls, self.tcx).ty.kind();
|
||||
if !matches!(pty, ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..)) {
|
||||
let pty = place.ty(&self.body.local_decls, self.tcx).ty;
|
||||
if !matches!(
|
||||
pty.kind(),
|
||||
ty::Adt(..) | ty::Coroutine(..) | ty::Alias(ty::Opaque, ..)
|
||||
) {
|
||||
self.fail(
|
||||
location,
|
||||
format!(
|
||||
"`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty:?}"
|
||||
"`SetDiscriminant` is only allowed on ADTs and coroutines, not {pty}"
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -1555,7 +1560,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
if ScalarInt::try_from_uint(value, size).is_none() {
|
||||
self.fail(
|
||||
location,
|
||||
format!("the value {value:#x} is not a proper {switch_ty:?}"),
|
||||
format!("the value {value:#x} is not a proper {switch_ty}"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
36
tests/ui/mir/inline-causes-trimmed-paths.rs
Normal file
36
tests/ui/mir/inline-causes-trimmed-paths.rs
Normal file
@ -0,0 +1,36 @@
|
||||
//@ build-pass
|
||||
//@ compile-flags: -Zinline-mir
|
||||
|
||||
trait Storage {
|
||||
type Buffer: ?Sized;
|
||||
}
|
||||
|
||||
struct Array<const N: usize>;
|
||||
impl<const N: usize> Storage for Array<N> {
|
||||
type Buffer = [(); N];
|
||||
}
|
||||
|
||||
struct Slice;
|
||||
impl Storage for Slice {
|
||||
type Buffer = [()];
|
||||
}
|
||||
|
||||
struct Wrap<S: Storage> {
|
||||
_b: S::Buffer,
|
||||
}
|
||||
|
||||
fn coerce<const N: usize>(this: &Wrap<Array<N>>) -> &Wrap<Slice>
|
||||
where
|
||||
Array<N>: Storage,
|
||||
{
|
||||
coerce_again(this)
|
||||
}
|
||||
|
||||
fn coerce_again<const N: usize>(this: &Wrap<Array<N>>) -> &Wrap<Slice> {
|
||||
this
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let inner: Wrap<Array<1>> = Wrap { _b: [(); 1] };
|
||||
let _: &Wrap<Slice> = coerce(&inner);
|
||||
}
|
Loading…
Reference in New Issue
Block a user