Skip to content

Commit f11baaa

Browse files
Properly structurally resolve type for HIR and MIR cast checks
1 parent b9fe8a5 commit f11baaa

File tree

6 files changed

+119
-43
lines changed

6 files changed

+119
-43
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

+60-25
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ use rustc_middle::ty::{
3838
use rustc_span::def_id::CRATE_DEF_ID;
3939
use rustc_span::{Span, DUMMY_SP};
4040
use rustc_target::abi::VariantIdx;
41+
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
4142
use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
4243
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
4344
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
4445
use rustc_trait_selection::traits::query::Fallible;
4546
use rustc_trait_selection::traits::PredicateObligation;
47+
use rustc_trait_selection::traits::{fully_solve_obligation, Obligation, ObligationCause};
4648

4749
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
4850
use rustc_mir_dataflow::move_paths::MoveData;
@@ -1154,6 +1156,31 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
11541156
self.infcx.tcx
11551157
}
11561158

1159+
fn structurally_resolved_ty(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
1160+
if self.tcx().trait_solver_next() && let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
1161+
let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
1162+
kind: TypeVariableOriginKind::NormalizeProjectionType,
1163+
span: DUMMY_SP,
1164+
});
1165+
let obligation = Obligation::new(
1166+
self.tcx(),
1167+
ObligationCause::dummy(),
1168+
self.param_env,
1169+
ty::Binder::dummy(ty::ProjectionPredicate {
1170+
projection_ty,
1171+
term: new_infer_ty.into(),
1172+
}),
1173+
);
1174+
1175+
if self.infcx.predicate_may_hold(&obligation) {
1176+
fully_solve_obligation(&self.infcx, obligation);
1177+
return self.infcx.resolve_vars_if_possible(new_infer_ty);
1178+
}
1179+
}
1180+
1181+
ty
1182+
}
1183+
11571184
#[instrument(skip(self, body, location), level = "debug")]
11581185
fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
11591186
let tcx = self.tcx();
@@ -1871,6 +1898,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18711898
Rvalue::Cast(cast_kind, op, ty) => {
18721899
self.check_operand(op, location);
18731900

1901+
let structurally_resolved_cast_tys = || {
1902+
(
1903+
self.structurally_resolved_ty(op.ty(body, tcx)),
1904+
self.structurally_resolved_ty(*ty),
1905+
)
1906+
};
1907+
18741908
match cast_kind {
18751909
CastKind::Pointer(PointerCast::ReifyFnPointer) => {
18761910
let fn_sig = op.ty(body, tcx).fn_sig(tcx);
@@ -1902,7 +1936,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
19021936
}
19031937

19041938
CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => {
1905-
let sig = match op.ty(body, tcx).kind() {
1939+
let sig = match self.structurally_resolved_ty(op.ty(body, tcx)).kind() {
19061940
ty::Closure(_, substs) => substs.as_closure().sig(),
19071941
_ => bug!(),
19081942
};
@@ -1971,10 +2005,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
19712005
// get the constraints from the target type (`dyn* Clone`)
19722006
//
19732007
// apply them to prove that the source type `Foo` implements `Clone` etc
1974-
let (existential_predicates, region) = match ty.kind() {
1975-
Dynamic(predicates, region, ty::DynStar) => (predicates, region),
1976-
_ => panic!("Invalid dyn* cast_ty"),
1977-
};
2008+
let (existential_predicates, region) =
2009+
match self.structurally_resolved_ty(*ty).kind() {
2010+
Dynamic(predicates, region, ty::DynStar) => (predicates, region),
2011+
_ => panic!("Invalid dyn* cast_ty"),
2012+
};
19782013

19792014
let self_ty = op.ty(body, tcx);
19802015

@@ -2001,7 +2036,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20012036
let ty::RawPtr(ty::TypeAndMut {
20022037
ty: ty_from,
20032038
mutbl: hir::Mutability::Mut,
2004-
}) = op.ty(body, tcx).kind() else {
2039+
}) = self.structurally_resolved_ty(op.ty(body, tcx)).kind() else {
20052040
span_mirbug!(
20062041
self,
20072042
rvalue,
@@ -2013,7 +2048,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20132048
let ty::RawPtr(ty::TypeAndMut {
20142049
ty: ty_to,
20152050
mutbl: hir::Mutability::Not,
2016-
}) = ty.kind() else {
2051+
}) = self.structurally_resolved_ty(*ty).kind() else {
20172052
span_mirbug!(
20182053
self,
20192054
rvalue,
@@ -2042,7 +2077,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20422077
CastKind::Pointer(PointerCast::ArrayToPointer) => {
20432078
let ty_from = op.ty(body, tcx);
20442079

2045-
let opt_ty_elem_mut = match ty_from.kind() {
2080+
let opt_ty_elem_mut = match self.structurally_resolved_ty(ty_from).kind() {
20462081
ty::RawPtr(ty::TypeAndMut { mutbl: array_mut, ty: array_ty }) => {
20472082
match array_ty.kind() {
20482083
ty::Array(ty_elem, _) => Some((ty_elem, *array_mut)),
@@ -2062,7 +2097,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20622097
return;
20632098
};
20642099

2065-
let (ty_to, ty_to_mut) = match ty.kind() {
2100+
let (ty_to, ty_to_mut) = match self.structurally_resolved_ty(*ty).kind() {
20662101
ty::RawPtr(ty::TypeAndMut { mutbl: ty_to_mut, ty: ty_to }) => {
20672102
(ty_to, *ty_to_mut)
20682103
}
@@ -2106,9 +2141,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21062141
}
21072142

21082143
CastKind::PointerExposeAddress => {
2109-
let ty_from = op.ty(body, tcx);
2144+
let (ty_from, ty) = structurally_resolved_cast_tys();
21102145
let cast_ty_from = CastTy::from_ty(ty_from);
2111-
let cast_ty_to = CastTy::from_ty(*ty);
2146+
let cast_ty_to = CastTy::from_ty(ty);
21122147
match (cast_ty_from, cast_ty_to) {
21132148
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (),
21142149
_ => {
@@ -2124,9 +2159,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21242159
}
21252160

21262161
CastKind::PointerFromExposedAddress => {
2127-
let ty_from = op.ty(body, tcx);
2162+
let (ty_from, ty) = structurally_resolved_cast_tys();
21282163
let cast_ty_from = CastTy::from_ty(ty_from);
2129-
let cast_ty_to = CastTy::from_ty(*ty);
2164+
let cast_ty_to = CastTy::from_ty(ty);
21302165
match (cast_ty_from, cast_ty_to) {
21312166
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (),
21322167
_ => {
@@ -2141,9 +2176,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21412176
}
21422177
}
21432178
CastKind::IntToInt => {
2144-
let ty_from = op.ty(body, tcx);
2179+
let (ty_from, ty) = structurally_resolved_cast_tys();
21452180
let cast_ty_from = CastTy::from_ty(ty_from);
2146-
let cast_ty_to = CastTy::from_ty(*ty);
2181+
let cast_ty_to = CastTy::from_ty(ty);
21472182
match (cast_ty_from, cast_ty_to) {
21482183
(Some(CastTy::Int(_)), Some(CastTy::Int(_))) => (),
21492184
_ => {
@@ -2158,9 +2193,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21582193
}
21592194
}
21602195
CastKind::IntToFloat => {
2161-
let ty_from = op.ty(body, tcx);
2196+
let (ty_from, ty) = structurally_resolved_cast_tys();
21622197
let cast_ty_from = CastTy::from_ty(ty_from);
2163-
let cast_ty_to = CastTy::from_ty(*ty);
2198+
let cast_ty_to = CastTy::from_ty(ty);
21642199
match (cast_ty_from, cast_ty_to) {
21652200
(Some(CastTy::Int(_)), Some(CastTy::Float)) => (),
21662201
_ => {
@@ -2175,9 +2210,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21752210
}
21762211
}
21772212
CastKind::FloatToInt => {
2178-
let ty_from = op.ty(body, tcx);
2213+
let (ty_from, ty) = structurally_resolved_cast_tys();
21792214
let cast_ty_from = CastTy::from_ty(ty_from);
2180-
let cast_ty_to = CastTy::from_ty(*ty);
2215+
let cast_ty_to = CastTy::from_ty(ty);
21812216
match (cast_ty_from, cast_ty_to) {
21822217
(Some(CastTy::Float), Some(CastTy::Int(_))) => (),
21832218
_ => {
@@ -2192,9 +2227,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
21922227
}
21932228
}
21942229
CastKind::FloatToFloat => {
2195-
let ty_from = op.ty(body, tcx);
2230+
let (ty_from, ty) = structurally_resolved_cast_tys();
21962231
let cast_ty_from = CastTy::from_ty(ty_from);
2197-
let cast_ty_to = CastTy::from_ty(*ty);
2232+
let cast_ty_to = CastTy::from_ty(ty);
21982233
match (cast_ty_from, cast_ty_to) {
21992234
(Some(CastTy::Float), Some(CastTy::Float)) => (),
22002235
_ => {
@@ -2209,9 +2244,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22092244
}
22102245
}
22112246
CastKind::FnPtrToPtr => {
2212-
let ty_from = op.ty(body, tcx);
2247+
let (ty_from, ty) = structurally_resolved_cast_tys();
22132248
let cast_ty_from = CastTy::from_ty(ty_from);
2214-
let cast_ty_to = CastTy::from_ty(*ty);
2249+
let cast_ty_to = CastTy::from_ty(ty);
22152250
match (cast_ty_from, cast_ty_to) {
22162251
(Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => (),
22172252
_ => {
@@ -2226,9 +2261,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
22262261
}
22272262
}
22282263
CastKind::PtrToPtr => {
2229-
let ty_from = op.ty(body, tcx);
2264+
let (ty_from, ty) = structurally_resolved_cast_tys();
22302265
let cast_ty_from = CastTy::from_ty(ty_from);
2231-
let cast_ty_to = CastTy::from_ty(*ty);
2266+
let cast_ty_to = CastTy::from_ty(ty);
22322267
match (cast_ty_from, cast_ty_to) {
22332268
(Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => (),
22342269
_ => {

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_hir_analysis::astconv::{
1919
};
2020
use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
2121
use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282;
22+
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
2223
use rustc_infer::infer::InferResult;
2324
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability};
2425
use rustc_middle::ty::error::TypeError;
@@ -34,6 +35,7 @@ use rustc_span::hygiene::DesugaringKind;
3435
use rustc_span::symbol::{kw, sym, Ident};
3536
use rustc_span::Span;
3637
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
38+
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
3739
use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCauseCode, ObligationCtxt};
3840

3941
use std::collections::hash_map::Entry;
@@ -1408,7 +1410,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14081410
/// Resolves `typ` by a single level if `typ` is a type variable.
14091411
/// If no resolution is possible, then an error is reported.
14101412
/// Numeric inference variables may be left unresolved.
1411-
pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
1413+
pub fn structurally_resolved_type(&self, sp: Span, mut ty: Ty<'tcx>) -> Ty<'tcx> {
1414+
if self.tcx.trait_solver_next() && let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
1415+
let new_infer_ty = self.next_ty_var(TypeVariableOrigin {
1416+
kind: TypeVariableOriginKind::NormalizeProjectionType,
1417+
span: sp,
1418+
});
1419+
let obligation = traits::Obligation::new(
1420+
self.tcx,
1421+
self.misc(sp),
1422+
self.param_env,
1423+
ty::Binder::dummy(ty::ProjectionPredicate {
1424+
projection_ty,
1425+
term: new_infer_ty.into(),
1426+
}),
1427+
);
1428+
if self.predicate_may_hold(&obligation) {
1429+
self.register_predicate(obligation);
1430+
ty = new_infer_ty;
1431+
}
1432+
}
1433+
14121434
let ty = self.resolve_vars_with_obligations(ty);
14131435
if !ty.is_ty_var() {
14141436
ty

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_middle::mir::AssertKind;
1313
use rustc_middle::mir::Place;
1414
use rustc_middle::mir::*;
1515
use rustc_middle::thir::*;
16-
use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
16+
use rustc_middle::ty::cast::{mir_cast_kind};
1717
use rustc_middle::ty::{self, Ty, UpvarSubsts};
1818
use rustc_span::Span;
1919

@@ -263,11 +263,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
263263
);
264264
(source, ty)
265265
};
266-
let from_ty = CastTy::from_ty(ty);
267-
let cast_ty = CastTy::from_ty(expr.ty);
268-
debug!("ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}", expr.ty,);
269-
let cast_kind = mir_cast_kind(ty, expr.ty);
270-
block.and(Rvalue::Cast(cast_kind, source, expr.ty))
266+
267+
let ty = this.structurally_resolved_ty(ty);
268+
let cast_ty = this.structurally_resolved_ty(expr.ty);
269+
let cast_kind = mir_cast_kind(ty, cast_ty);
270+
block.and(Rvalue::Cast(cast_kind, source, cast_ty))
271271
}
272272
ExprKind::Pointer { cast, source } => {
273273
let source = unpack!(

compiler/rustc_mir_build/src/build/mod.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_hir::def::DefKind;
1111
use rustc_hir::def_id::{DefId, LocalDefId};
1212
use rustc_hir::{GeneratorKind, Node};
1313
use rustc_index::vec::{Idx, IndexVec};
14+
use rustc_infer::infer::type_variable::{TypeVariableOriginKind, TypeVariableOrigin};
1415
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
1516
use rustc_middle::hir::place::PlaceBase as HirPlaceBase;
1617
use rustc_middle::middle::region;
@@ -22,9 +23,11 @@ use rustc_middle::thir::{
2223
};
2324
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
2425
use rustc_span::symbol::sym;
25-
use rustc_span::Span;
26+
use rustc_span::{Span, DUMMY_SP};
2627
use rustc_span::Symbol;
2728
use rustc_target::spec::abi::Abi;
29+
use rustc_trait_selection::traits;
30+
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
2831

2932
use super::lints;
3033

@@ -229,6 +232,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
229232
fn var_local_id(&self, id: LocalVarId, for_guard: ForGuard) -> Local {
230233
self.var_indices[&id].local_id(for_guard)
231234
}
235+
236+
fn structurally_resolved_ty(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
237+
if self.tcx.trait_solver_next() && let ty::Alias(ty::Projection, projection_ty) = *ty.kind() {
238+
let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin {
239+
kind: TypeVariableOriginKind::NormalizeProjectionType,
240+
span: DUMMY_SP,
241+
});
242+
let obligation = traits::Obligation::new(
243+
self.tcx,
244+
traits::ObligationCause::dummy(),
245+
self.param_env,
246+
ty::Binder::dummy(ty::ProjectionPredicate {
247+
projection_ty,
248+
term: new_infer_ty.into(),
249+
}),
250+
);
251+
252+
if self.infcx.predicate_may_hold(&obligation) {
253+
traits::fully_solve_obligation(&self.infcx, obligation);
254+
return self.infcx.resolve_vars_if_possible(new_infer_ty);
255+
}
256+
}
257+
258+
ty
259+
}
232260
}
233261

234262
impl BlockContext {

tests/ui/typeck/lazy-norm/cast-checks-handling-projections.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// compile-flags: -Ztrait-solver=next
2-
// known-bug: unknown
2+
// check-pass
33

44
fn main() {
55
(0u8 + 0u8) as char;

tests/ui/typeck/lazy-norm/cast-checks-handling-projections.stderr

-9
This file was deleted.

0 commit comments

Comments
 (0)