1
Fork 0

Stop relying on rustc_type_ir in non-type-system crates

This commit is contained in:
Michael Goulet 2025-03-13 18:05:00 +00:00
parent 19c84c8812
commit b88f85a410
37 changed files with 136 additions and 163 deletions

View file

@ -23,7 +23,6 @@ rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_target = { path = "../rustc_target" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
tracing = "0.1"
unicode-security = "0.1.0"

View file

@ -2582,34 +2582,35 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
) -> Option<InitError> {
let ty = cx.tcx.try_normalize_erasing_regions(cx.typing_env(), ty).unwrap_or(ty);
use rustc_type_ir::TyKind::*;
match ty.kind() {
// Primitive types that don't like 0 as a value.
Ref(..) => Some("references must be non-null".into()),
Adt(..) if ty.is_box() => Some("`Box` must be non-null".into()),
FnPtr(..) => Some("function pointers must be non-null".into()),
Never => Some("the `!` type has no valid value".into()),
RawPtr(ty, _) if matches!(ty.kind(), Dynamic(..)) =>
ty::Ref(..) => Some("references must be non-null".into()),
ty::Adt(..) if ty.is_box() => Some("`Box` must be non-null".into()),
ty::FnPtr(..) => Some("function pointers must be non-null".into()),
ty::Never => Some("the `!` type has no valid value".into()),
ty::RawPtr(ty, _) if matches!(ty.kind(), ty::Dynamic(..)) =>
// raw ptr to dyn Trait
{
Some("the vtable of a wide raw pointer must be non-null".into())
}
// Primitive types with other constraints.
Bool if init == InitKind::Uninit => {
ty::Bool if init == InitKind::Uninit => {
Some("booleans must be either `true` or `false`".into())
}
Char if init == InitKind::Uninit => {
ty::Char if init == InitKind::Uninit => {
Some("characters must be a valid Unicode codepoint".into())
}
Int(_) | Uint(_) if init == InitKind::Uninit => {
ty::Int(_) | ty::Uint(_) if init == InitKind::Uninit => {
Some("integers must be initialized".into())
}
Float(_) if init == InitKind::Uninit => Some("floats must be initialized".into()),
RawPtr(_, _) if init == InitKind::Uninit => {
ty::Float(_) if init == InitKind::Uninit => {
Some("floats must be initialized".into())
}
ty::RawPtr(_, _) if init == InitKind::Uninit => {
Some("raw pointers must be initialized".into())
}
// Recurse and checks for some compound types. (but not unions)
Adt(adt_def, args) if !adt_def.is_union() => {
ty::Adt(adt_def, args) if !adt_def.is_union() => {
// Handle structs.
if adt_def.is_struct() {
return variant_find_init_error(
@ -2675,11 +2676,11 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
// We couldn't find anything wrong here.
None
}
Tuple(..) => {
ty::Tuple(..) => {
// Proceed recursively, check all fields.
ty.tuple_fields().iter().find_map(|field| ty_find_init_error(cx, field, init))
}
Array(ty, len) => {
ty::Array(ty, len) => {
if matches!(len.try_to_target_usize(cx.tcx), Some(v) if v > 0) {
// Array length known at array non-empty -- recurse.
ty_find_init_error(cx, *ty, init)

View file

@ -270,14 +270,12 @@ fn structurally_same_type_impl<'tcx>(
true
} else {
// Do a full, depth-first comparison between the two.
use rustc_type_ir::TyKind::*;
let is_primitive_or_pointer =
|ty: Ty<'tcx>| ty.is_primitive() || matches!(ty.kind(), RawPtr(..) | Ref(..));
|ty: Ty<'tcx>| ty.is_primitive() || matches!(ty.kind(), ty::RawPtr(..) | ty::Ref(..));
ensure_sufficient_stack(|| {
match (a.kind(), b.kind()) {
(&Adt(a_def, a_gen_args), &Adt(b_def, b_gen_args)) => {
(&ty::Adt(a_def, a_gen_args), &ty::Adt(b_def, b_gen_args)) => {
// Only `repr(C)` types can be compared structurally.
if !(a_def.repr().c() && b_def.repr().c()) {
return false;
@ -308,30 +306,30 @@ fn structurally_same_type_impl<'tcx>(
},
)
}
(Array(a_ty, a_len), Array(b_ty, b_len)) => {
(ty::Array(a_ty, a_len), ty::Array(b_ty, b_len)) => {
// For arrays, we also check the length.
a_len == b_len
&& structurally_same_type_impl(
seen_types, tcx, typing_env, *a_ty, *b_ty, ckind,
)
}
(Slice(a_ty), Slice(b_ty)) => {
(ty::Slice(a_ty), ty::Slice(b_ty)) => {
structurally_same_type_impl(seen_types, tcx, typing_env, *a_ty, *b_ty, ckind)
}
(RawPtr(a_ty, a_mutbl), RawPtr(b_ty, b_mutbl)) => {
(ty::RawPtr(a_ty, a_mutbl), ty::RawPtr(b_ty, b_mutbl)) => {
a_mutbl == b_mutbl
&& structurally_same_type_impl(
seen_types, tcx, typing_env, *a_ty, *b_ty, ckind,
)
}
(Ref(_a_region, a_ty, a_mut), Ref(_b_region, b_ty, b_mut)) => {
(ty::Ref(_a_region, a_ty, a_mut), ty::Ref(_b_region, b_ty, b_mut)) => {
// For structural sameness, we don't need the region to be same.
a_mut == b_mut
&& structurally_same_type_impl(
seen_types, tcx, typing_env, *a_ty, *b_ty, ckind,
)
}
(FnDef(..), FnDef(..)) => {
(ty::FnDef(..), ty::FnDef(..)) => {
let a_poly_sig = a.fn_sig(tcx);
let b_poly_sig = b.fn_sig(tcx);
@ -354,35 +352,38 @@ fn structurally_same_type_impl<'tcx>(
ckind,
)
}
(Tuple(..), Tuple(..)) => {
(ty::Tuple(..), ty::Tuple(..)) => {
// Tuples are not `repr(C)` so these cannot be compared structurally.
false
}
// For these, it's not quite as easy to define structural-sameness quite so easily.
// For the purposes of this lint, take the conservative approach and mark them as
// not structurally same.
(Dynamic(..), Dynamic(..))
| (Error(..), Error(..))
| (Closure(..), Closure(..))
| (Coroutine(..), Coroutine(..))
| (CoroutineWitness(..), CoroutineWitness(..))
| (Alias(ty::Projection, ..), Alias(ty::Projection, ..))
| (Alias(ty::Inherent, ..), Alias(ty::Inherent, ..))
| (Alias(ty::Opaque, ..), Alias(ty::Opaque, ..)) => false,
(ty::Dynamic(..), ty::Dynamic(..))
| (ty::Error(..), ty::Error(..))
| (ty::Closure(..), ty::Closure(..))
| (ty::Coroutine(..), ty::Coroutine(..))
| (ty::CoroutineWitness(..), ty::CoroutineWitness(..))
| (ty::Alias(ty::Projection, ..), ty::Alias(ty::Projection, ..))
| (ty::Alias(ty::Inherent, ..), ty::Alias(ty::Inherent, ..))
| (ty::Alias(ty::Opaque, ..), ty::Alias(ty::Opaque, ..)) => false,
// These definitely should have been caught above.
(Bool, Bool) | (Char, Char) | (Never, Never) | (Str, Str) => unreachable!(),
(ty::Bool, ty::Bool)
| (ty::Char, ty::Char)
| (ty::Never, ty::Never)
| (ty::Str, ty::Str) => unreachable!(),
// An Adt and a primitive or pointer type. This can be FFI-safe if non-null
// enum layout optimisation is being applied.
(Adt(..) | Pat(..), _) if is_primitive_or_pointer(b) => {
(ty::Adt(..) | ty::Pat(..), _) if is_primitive_or_pointer(b) => {
if let Some(a_inner) = types::repr_nullable_ptr(tcx, typing_env, a, ckind) {
a_inner == b
} else {
false
}
}
(_, Adt(..) | Pat(..)) if is_primitive_or_pointer(a) => {
(_, ty::Adt(..) | ty::Pat(..)) if is_primitive_or_pointer(a) => {
if let Some(b_inner) = types::repr_nullable_ptr(tcx, typing_env, b, ckind) {
b_inner == a
} else {

View file

@ -506,9 +506,9 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for FunctionalVariances<'tcx> {
self.tcx
}
fn relate_with_variance<T: ty::relate::Relate<TyCtxt<'tcx>>>(
fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
&mut self,
variance: rustc_type_ir::Variance,
variance: ty::Variance,
_: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
a: T,
b: T,