Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 6f0c5ee

Browse files
committed
change is_subtype to relate_types
1 parent cd7f471 commit 6f0c5ee

File tree

15 files changed

+128
-86
lines changed

15 files changed

+128
-86
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -716,14 +716,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
716716
}
717717
PlaceTy::from_ty(fty)
718718
}
719-
ProjectionElem::Subtype(_) => {
720-
let guard = span_mirbug_and_err!(
721-
self,
722-
place,
723-
"ProjectionElem::Subtype shouldn't exist in borrowck"
724-
);
725-
PlaceTy::from_ty(Ty::new_error(tcx, guard))
726-
}
719+
ProjectionElem::Subtype(_) => PlaceTy::from_ty(Ty::new_error_with_message(
720+
tcx,
721+
self.last_span,
722+
"ProjectionElem::Subtype shouldn't exist in borrowck",
723+
)),
727724
ProjectionElem::OpaqueCast(ty) => {
728725
let ty = self.sanitize_type(place, ty);
729726
let ty = self.cx.normalize(ty, location);
@@ -2564,14 +2561,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
25642561
}
25652562
}
25662563
ProjectionElem::Field(..)
2567-
| ProjectionElem::Subtype(..)
25682564
| ProjectionElem::Downcast(..)
25692565
| ProjectionElem::OpaqueCast(..)
25702566
| ProjectionElem::Index(..)
25712567
| ProjectionElem::ConstantIndex { .. }
25722568
| ProjectionElem::Subslice { .. } => {
25732569
// other field access
25742570
}
2571+
ProjectionElem::Subtype(_) => {
2572+
bug!("ProjectionElem::Subtype shouldn't exist in borrowck")
2573+
}
25752574
}
25762575
}
25772576
}

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ pub(crate) fn codegen_place<'tcx>(
876876
cplace = cplace.place_deref(fx);
877877
}
878878
PlaceElem::OpaqueCast(ty) => bug!("encountered OpaqueCast({ty}) in codegen"),
879-
PlaceElem::Subtype(ty) => cplace = cplace.place_transmute_type(fx, ty),
879+
PlaceElem::Subtype(ty) => cplace = cplace.place_transmute_type(fx, fx.monomorphize(ty)),
880880
PlaceElem::Field(field, _ty) => {
881881
cplace = cplace.place_field(fx, field);
882882
}

compiler/rustc_codegen_cranelift/src/value_and_place.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,12 +674,14 @@ impl<'tcx> CPlace<'tcx> {
674674
}
675675
}
676676

677+
/// Used for `ProjectionElem::Subtype`, ty has to be monomorphized before
678+
/// passed on.
677679
pub(crate) fn place_transmute_type(
678680
self,
679681
fx: &mut FunctionCx<'_, '_, 'tcx>,
680682
ty: Ty<'tcx>,
681683
) -> CPlace<'tcx> {
682-
CPlace { inner: self.inner, layout: fx.layout_of(fx.monomorphize(ty)) }
684+
CPlace { inner: self.inner, layout: fx.layout_of(ty) }
683685
}
684686

685687
pub(crate) fn place_field(

compiler/rustc_const_eval/src/interpret/eval_context.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_middle::ty::layout::{
1313
self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
1414
TyAndLayout,
1515
};
16-
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable};
16+
use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt, TypeFoldable, Variance};
1717
use rustc_mir_dataflow::storage::always_storage_live_locals;
1818
use rustc_session::Limit;
1919
use rustc_span::Span;
@@ -384,7 +384,7 @@ pub(super) fn mir_assign_valid_types<'tcx>(
384384
// all normal lifetimes are erased, higher-ranked types with their
385385
// late-bound lifetimes are still around and can lead to type
386386
// differences.
387-
if util::is_subtype(tcx, param_env, src.ty, dest.ty) {
387+
if util::relate_types(tcx, param_env, Variance::Covariant, src.ty, dest.ty) {
388388
// Make sure the layout is equal, too -- just to be safe. Miri really
389389
// needs layout equality. For performance reason we skip this check when
390390
// the types are equal. Equal types *can* have different layouts when

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_infer::traits::Reveal;
77
use rustc_middle::mir::interpret::Scalar;
88
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
99
use rustc_middle::mir::*;
10-
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
10+
use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt, Variance};
1111
use rustc_mir_dataflow::impls::MaybeStorageLive;
1212
use rustc_mir_dataflow::storage::always_storage_live_locals;
1313
use rustc_mir_dataflow::{Analysis, ResultsCursor};
@@ -16,7 +16,7 @@ use rustc_target::spec::abi::Abi;
1616

1717
use crate::util::is_within_packed;
1818

19-
use crate::util::is_subtype;
19+
use crate::util::relate_types;
2020

2121
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
2222
enum EdgeKind {
@@ -604,7 +604,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
604604
return true;
605605
}
606606

607-
return crate::util::is_subtype(self.tcx, self.param_env, src, dest);
607+
// After borrowck subtyping should be fully explicit via
608+
// `Subtype` projections.
609+
let variance = if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
610+
Variance::Invariant
611+
} else {
612+
Variance::Covariant
613+
};
614+
615+
crate::util::relate_types(self.tcx, self.param_env, variance, src, dest)
608616
}
609617
}
610618

@@ -756,9 +764,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
756764
}
757765
}
758766
ProjectionElem::Subtype(ty) => {
759-
if !is_subtype(
767+
if !relate_types(
760768
self.tcx,
761769
self.param_env,
770+
Variance::Covariant,
762771
ty,
763772
place_ref.ty(&self.body.local_decls, self.tcx).ty,
764773
) {

compiler/rustc_const_eval/src/util/compare_types.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
use rustc_infer::infer::TyCtxtInferExt;
77
use rustc_middle::traits::{DefiningAnchor, ObligationCause};
8-
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
8+
use rustc_middle::ty::{ParamEnv, Ty, TyCtxt, Variance};
99
use rustc_trait_selection::traits::ObligationCtxt;
1010

1111
/// Returns whether the two types are equal up to subtyping.
@@ -24,16 +24,22 @@ pub fn is_equal_up_to_subtyping<'tcx>(
2424
}
2525

2626
// Check for subtyping in either direction.
27-
is_subtype(tcx, param_env, src, dest) || is_subtype(tcx, param_env, dest, src)
27+
relate_types(tcx, param_env, Variance::Covariant, src, dest)
28+
|| relate_types(tcx, param_env, Variance::Covariant, dest, src)
2829
}
2930

3031
/// Returns whether `src` is a subtype of `dest`, i.e. `src <: dest`.
3132
///
33+
/// For almost all of the use cases variance should be `Covariant`,
34+
/// in `MirPhase` >= `MirPhase::Runtime(RuntimePhase::Initial` variance should
35+
/// be `Invariant`.
36+
///
3237
/// This mostly ignores opaque types as it can be used in constraining contexts
3338
/// while still computing the final underlying type.
34-
pub fn is_subtype<'tcx>(
39+
pub fn relate_types<'tcx>(
3540
tcx: TyCtxt<'tcx>,
3641
param_env: ParamEnv<'tcx>,
42+
variance: Variance,
3743
src: Ty<'tcx>,
3844
dest: Ty<'tcx>,
3945
) -> bool {
@@ -48,7 +54,7 @@ pub fn is_subtype<'tcx>(
4854
let cause = ObligationCause::dummy();
4955
let src = ocx.normalize(&cause, param_env, src);
5056
let dest = ocx.normalize(&cause, param_env, dest);
51-
match ocx.sub(&cause, param_env, src, dest) {
57+
match ocx.relate(&cause, param_env, variance, src, dest) {
5258
Ok(()) => {}
5359
Err(_) => return false,
5460
};

compiler/rustc_const_eval/src/util/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ mod type_name;
77

88
pub use self::alignment::{is_disaligned, is_within_packed};
99
pub use self::check_validity_requirement::check_validity_requirement;
10-
pub use self::compare_types::{is_equal_up_to_subtyping, is_subtype};
10+
pub use self::compare_types::{is_equal_up_to_subtyping, relate_types};
1111
pub use self::type_name::type_name;
1212

1313
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the

compiler/rustc_mir_transform/src/inline.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,13 @@ impl<'tcx> Inliner<'tcx> {
218218
// Normally, this shouldn't be required, but trait normalization failure can create a
219219
// validation ICE.
220220
let output_type = callee_body.return_ty();
221-
if !util::is_subtype(self.tcx, self.param_env, output_type, destination_ty) {
221+
if !util::relate_types(
222+
self.tcx,
223+
self.param_env,
224+
ty::Variance::Covariant,
225+
output_type,
226+
destination_ty,
227+
) {
222228
trace!(?output_type, ?destination_ty);
223229
return Err("failed to normalize return type");
224230
}
@@ -248,7 +254,13 @@ impl<'tcx> Inliner<'tcx> {
248254
self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter())
249255
{
250256
let input_type = callee_body.local_decls[input].ty;
251-
if !util::is_subtype(self.tcx, self.param_env, input_type, arg_ty) {
257+
if !util::relate_types(
258+
self.tcx,
259+
self.param_env,
260+
ty::Variance::Covariant,
261+
input_type,
262+
arg_ty,
263+
) {
252264
trace!(?arg_ty, ?input_type);
253265
return Err("failed to normalize tuple argument type");
254266
}
@@ -257,7 +269,13 @@ impl<'tcx> Inliner<'tcx> {
257269
for (arg, input) in args.iter().zip(callee_body.args_iter()) {
258270
let input_type = callee_body.local_decls[input].ty;
259271
let arg_ty = arg.ty(&caller_body.local_decls, self.tcx);
260-
if !util::is_subtype(self.tcx, self.param_env, input_type, arg_ty) {
272+
if !util::relate_types(
273+
self.tcx,
274+
self.param_env,
275+
ty::Variance::Covariant,
276+
input_type,
277+
arg_ty,
278+
) {
261279
trace!(?arg_ty, ?input_type);
262280
return Err("failed to normalize argument type");
263281
}

compiler/rustc_trait_selection/src/traits/engine.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use rustc_middle::traits::query::NoSolution;
2323
use rustc_middle::ty::error::TypeError;
2424
use rustc_middle::ty::ToPredicate;
2525
use rustc_middle::ty::TypeFoldable;
26+
use rustc_middle::ty::Variance;
2627
use rustc_middle::ty::{self, Ty, TyCtxt};
2728
use rustc_session::config::TraitSolver;
2829

@@ -156,6 +157,20 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
156157
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
157158
}
158159

160+
pub fn relate<T: ToTrace<'tcx>>(
161+
&self,
162+
cause: &ObligationCause<'tcx>,
163+
param_env: ty::ParamEnv<'tcx>,
164+
variance: Variance,
165+
expected: T,
166+
actual: T,
167+
) -> Result<(), TypeError<'tcx>> {
168+
self.infcx
169+
.at(cause, param_env)
170+
.relate(DefineOpaqueTypes::Yes, expected, variance, actual)
171+
.map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
172+
}
173+
159174
/// Checks whether `expected` is a supertype of `actual`: `expected :> actual`.
160175
pub fn sup<T: ToTrace<'tcx>>(
161176
&self,

src/tools/stable-mir-dev

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 9434648ba82a0519222677bcc3fdf8b4f1ac5ced

0 commit comments

Comments
 (0)