Skip to content

Do not trim paths in MIR validator #139025

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 31 additions & 26 deletions compiler/rustc_mir_transform/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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
Expand All @@ -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) => {
Expand All @@ -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}`"
)
)
}
Expand Down Expand Up @@ -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
),
)
Expand All @@ -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}"
),
);
}
Expand All @@ -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() {
Expand Down Expand Up @@ -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}"),
);
}
}
Expand All @@ -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 => {
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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:?}"),
);
}
}
Expand Down Expand Up @@ -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}"
),
);
}
Expand Down Expand Up @@ -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}"),
)
}
}
Expand Down
36 changes: 36 additions & 0 deletions tests/ui/mir/inline-causes-trimmed-paths.rs
Original file line number Diff line number Diff line change
@@ -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