Skip to content

Commit fc629fd

Browse files
committed
do horrors in project.rs
1 parent 2a52de1 commit fc629fd

File tree

7 files changed

+103
-25
lines changed

7 files changed

+103
-25
lines changed

compiler/rustc_borrowck/src/type_check/relate_tys.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_infer::traits::ObligationCause;
44
use rustc_middle::mir::ConstraintCategory;
55
use rustc_middle::ty::error::TypeError;
66
use rustc_middle::ty::relate::TypeRelation;
7-
use rustc_middle::ty::{self, Const, ToPredicate, Ty};
7+
use rustc_middle::ty::{self, Const, Ty};
88
use rustc_span::Span;
99
use rustc_trait_selection::traits::query::Fallible;
1010

@@ -147,7 +147,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
147147
// 'static.
148148
fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {}
149149

150-
fn projection_equate(&mut self, projection_ty: ty::ProjectionTy<'tcx>, ty: Ty<'tcx>) {
150+
fn projection_equate(&mut self, _projection_ty: ty::ProjectionTy<'tcx>, _ty: Ty<'tcx>) {
151151
unreachable!()
152152
}
153153

compiler/rustc_infer/src/infer/combine.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
783783
}
784784

785785
fn defer_projection_equality(&self) -> bool {
786-
bug!("`TypeGeneralizer` shouldn't equate projections with other kinds of types");
786+
false
787787
}
788788
}
789789

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2780,8 +2780,8 @@ impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
27802780

27812781
fn projection_equate_obligation(
27822782
&mut self,
2783-
projection_ty: ty::ProjectionTy<'tcx>,
2784-
ty: Ty<'tcx>,
2783+
_projection_ty: ty::ProjectionTy<'tcx>,
2784+
_ty: Ty<'tcx>,
27852785
) {
27862786
unreachable!()
27872787
}

compiler/rustc_infer/src/infer/nll_relate/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,6 @@ where
10701070
}
10711071

10721072
fn defer_projection_equality(&self) -> bool {
1073-
bug!("`TypeGeneralizer` shouldn't equate projections with other kinds of types");
1073+
false
10741074
}
10751075
}

compiler/rustc_infer/src/infer/outlives/test_type_match.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
214214

215215
fn projection_equate_obligation(
216216
&mut self,
217-
projection_ty: ty::ProjectionTy<'tcx>,
218-
ty: Ty<'tcx>,
217+
_projection_ty: ty::ProjectionTy<'tcx>,
218+
_ty: Ty<'tcx>,
219219
) {
220220
unreachable!()
221221
}

compiler/rustc_middle/src/ty/relate.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -561,13 +561,6 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
561561
(ty::Projection(_), ty::Opaque(_, _)) | (ty::Opaque(_, _), ty::Projection(_)) => {
562562
Err(TypeError::Sorts(expected_found(relation, a, b)))
563563
}
564-
// FIXME(BoxyUwU): This is isnt quite right i.e. if we have
565-
// `<_ as Trait>::Assoc == <T as Other>::Assoc` we ideally wouldnt error because `_`
566-
// might get inferred to something which allows normalization to `<T as Other>::Assoc`.
567-
(&ty::Projection(proj_a), &ty::Projection(proj_b)) => {
568-
let projection_ty = relation.relate(proj_a, proj_b)?;
569-
Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
570-
}
571564
(&ty::Projection(proj_a), _)
572565
if proj_a.has_infer_types_or_consts() && relation.defer_projection_equality() =>
573566
{
@@ -580,6 +573,10 @@ pub fn super_relate_tys<'tcx, R: TypeRelation<'tcx>>(
580573
relation.projection_equate_obligation(proj_b, a);
581574
Ok(a)
582575
}
576+
(&ty::Projection(proj_a), &ty::Projection(proj_b)) => {
577+
let projection_ty = relation.relate(proj_a, proj_b)?;
578+
Ok(tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs))
579+
}
583580

584581
(&ty::Opaque(a_def_id, a_substs), &ty::Opaque(b_def_id, b_substs))
585582
if a_def_id == b_def_id =>

compiler/rustc_trait_selection/src/traits/project.rs

+91-10
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ use rustc_hir::def_id::DefId;
2929
use rustc_hir::lang_items::LangItem;
3030
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
3131
use rustc_middle::traits::select::OverflowError;
32+
use rustc_middle::ty::error::ExpectedFound;
33+
use rustc_middle::ty::error::TypeError;
3234
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
3335
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
3436
use rustc_middle::ty::DefIdTree;
@@ -255,6 +257,7 @@ fn project_and_unify_type<'cx, 'tcx>(
255257
};
256258
debug!(?normalized, ?obligations, "project_and_unify_type result");
257259
let actual = obligation.predicate.term;
260+
258261
// For an example where this is neccessary see src/test/ui/impl-trait/nested-return-type2.rs
259262
// This allows users to omit re-mentioning all bounds on an associated type and just use an
260263
// `impl Trait` for the assoc type to add more bounds.
@@ -267,16 +270,94 @@ fn project_and_unify_type<'cx, 'tcx>(
267270
);
268271
obligations.extend(new);
269272

270-
let defer_projection_equality =
271-
normalized.ty().map_or(true, |normalized| match normalized.kind() {
272-
ty::Projection(proj) => proj != &obligation.predicate.projection_ty,
273-
_ => true,
274-
});
275-
match infcx
276-
.at(&obligation.cause, obligation.param_env)
277-
.defer_projection_equality(defer_projection_equality)
278-
.eq(normalized, actual)
279-
{
273+
if let Some(ty) = normalized.ty() {
274+
if let &ty::Projection(projection) = ty.kind() {
275+
match opt_normalize_projection_type(
276+
selcx,
277+
obligation.param_env,
278+
projection,
279+
obligation.cause.clone(),
280+
obligation.recursion_depth,
281+
&mut obligations,
282+
) {
283+
Ok(Some(_)) => (),
284+
Ok(None) => {
285+
debug!("failed normalization of: {:?}", projection);
286+
return ProjectAndUnifyResult::FailedNormalization;
287+
}
288+
Err(InProgress) => unreachable!(),
289+
}
290+
291+
let actual = actual.ty().unwrap();
292+
let done = match actual.kind() {
293+
&ty::Projection(other) => {
294+
let flipped_projection_eq = InferOk {
295+
obligations: vec![Obligation::new(
296+
obligation.cause.clone(),
297+
obligation.param_env,
298+
ty::Binder::dummy(ty::ProjectionPredicate {
299+
projection_ty: other,
300+
term: ty::Term::from(ty),
301+
})
302+
.to_predicate(selcx.tcx()),
303+
)],
304+
value: (),
305+
};
306+
307+
match opt_normalize_projection_type(
308+
selcx,
309+
obligation.param_env,
310+
other,
311+
obligation.cause.clone(),
312+
obligation.recursion_depth,
313+
&mut obligations,
314+
) {
315+
Ok(Some(normed_other)) => match normed_other.ty().unwrap().kind() {
316+
&ty::Projection(normed_other) => {
317+
match opt_normalize_projection_type(
318+
selcx,
319+
obligation.param_env,
320+
normed_other,
321+
obligation.cause.clone(),
322+
obligation.recursion_depth,
323+
&mut obligations,
324+
) {
325+
Ok(Some(_)) => infcx
326+
.at(&obligation.cause, obligation.param_env)
327+
.trace(ty, actual)
328+
.eq(projection, normed_other),
329+
Ok(None) => Ok(flipped_projection_eq),
330+
Err(InProgress) => unreachable!(),
331+
}
332+
}
333+
ty::Infer(_) => {
334+
infcx.at(&obligation.cause, obligation.param_env).eq(ty, actual)
335+
}
336+
_ => Err(TypeError::Sorts(ExpectedFound::new(false, ty, actual))),
337+
},
338+
Ok(None) => Ok(flipped_projection_eq),
339+
Err(InProgress) => return ProjectAndUnifyResult::Recursive,
340+
}
341+
}
342+
ty::Infer(_) => infcx.at(&obligation.cause, obligation.param_env).eq(ty, actual),
343+
_ => Err(TypeError::Sorts(ExpectedFound::new(false, ty, actual))),
344+
};
345+
return match done {
346+
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
347+
obligations.extend(inferred_obligations);
348+
ProjectAndUnifyResult::Holds(obligations)
349+
}
350+
Err(err) => {
351+
debug!("equating types encountered error {:?}", err);
352+
ProjectAndUnifyResult::MismatchedProjectionTypes(MismatchedProjectionTypes {
353+
err,
354+
})
355+
}
356+
};
357+
}
358+
}
359+
360+
match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) {
280361
Ok(InferOk { obligations: inferred_obligations, value: () }) => {
281362
obligations.extend(inferred_obligations);
282363
ProjectAndUnifyResult::Holds(obligations)

0 commit comments

Comments
 (0)