Skip to content

Commit 62f0fc5

Browse files
committed
port the relate-types code from NLL type-check into a type-op
Add regression tests for #55219 and #55241 Also another test where a duplicate-like error appears to have been suppressed; I'm not 100% sure why this output changes, though I could imagine that some duplicate suppression is enabled by this PR.
1 parent 7c8887c commit 62f0fc5

File tree

7 files changed

+244
-128
lines changed

7 files changed

+244
-128
lines changed

src/librustc/infer/at.rs

+22
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,28 @@ impl<'a, 'gcx, 'tcx> At<'a, 'gcx, 'tcx> {
142142
self.trace(expected, actual).eq(&expected, &actual)
143143
}
144144

145+
pub fn relate<T>(
146+
self,
147+
expected: T,
148+
variance: ty::Variance,
149+
actual: T,
150+
) -> InferResult<'tcx, ()>
151+
where T: ToTrace<'tcx>
152+
{
153+
match variance {
154+
ty::Variance::Covariant => self.sub(expected, actual),
155+
ty::Variance::Invariant => self.eq(expected, actual),
156+
ty::Variance::Contravariant => self.sup(expected, actual),
157+
158+
// We could make this make sense but it's not readily
159+
// exposed and I don't feel like dealing with it. Note
160+
// that bivariance in general does a bit more than just
161+
// *nothing*, it checks that the types are the same
162+
// "modulo variance" basically.
163+
ty::Variance::Bivariant => panic!("Bivariant given to `relate()`"),
164+
}
165+
}
166+
145167
/// Compute the least-upper-bound, or mutual supertype, of two
146168
/// values. The order of the arguments doesn't matter, but since
147169
/// this can result in an error (e.g., if asked to compute LUB of

src/librustc/traits/query/type_op/ascribe_user_type.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,27 @@
99
// except according to those terms.
1010

1111
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
12-
use mir::UserTypeAnnotation;
1312
use traits::query::Fallible;
13+
use hir::def_id::DefId;
1414
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
15+
use ty::subst::UserSubsts;
1516

1617
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
1718
pub struct AscribeUserType<'tcx> {
1819
pub mir_ty: Ty<'tcx>,
1920
pub variance: ty::Variance,
20-
pub user_ty: UserTypeAnnotation<'tcx>,
21+
pub def_id: DefId,
22+
pub user_substs: UserSubsts<'tcx>,
2123
}
2224

2325
impl<'tcx> AscribeUserType<'tcx> {
2426
pub fn new(
2527
mir_ty: Ty<'tcx>,
2628
variance: ty::Variance,
27-
user_ty: UserTypeAnnotation<'tcx>,
29+
def_id: DefId,
30+
user_substs: UserSubsts<'tcx>,
2831
) -> Self {
29-
AscribeUserType { mir_ty, variance, user_ty }
32+
AscribeUserType { mir_ty, variance, def_id, user_substs }
3033
}
3134
}
3235

@@ -56,19 +59,19 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for AscribeUserType<'tcx>
5659

5760
BraceStructTypeFoldableImpl! {
5861
impl<'tcx> TypeFoldable<'tcx> for AscribeUserType<'tcx> {
59-
mir_ty, variance, user_ty
62+
mir_ty, variance, def_id, user_substs
6063
}
6164
}
6265

6366
BraceStructLiftImpl! {
6467
impl<'a, 'tcx> Lift<'tcx> for AscribeUserType<'a> {
6568
type Lifted = AscribeUserType<'tcx>;
66-
mir_ty, variance, user_ty
69+
mir_ty, variance, def_id, user_substs
6770
}
6871
}
6972

7073
impl_stable_hash_for! {
7174
struct AscribeUserType<'tcx> {
72-
mir_ty, variance, user_ty
75+
mir_ty, variance, def_id, user_substs
7376
}
7477
}

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+15-99
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
4242
use rustc::traits::query::{Fallible, NoSolution};
4343
use rustc::traits::{ObligationCause, PredicateObligations};
4444
use rustc::ty::fold::TypeFoldable;
45-
use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSelfTy, UserSubsts};
45+
use rustc::ty::subst::{Subst, Substs, UnpackedKind};
4646
use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
4747
use std::rc::Rc;
4848
use std::{fmt, iter};
@@ -975,127 +975,43 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
975975
locations: Locations,
976976
category: ConstraintCategory,
977977
) -> Fallible<()> {
978-
let tcx = self.tcx();
979-
980978
debug!(
981-
"relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
982-
a, v, user_ty, locations
979+
"relate_type_and_user_type(a={:?}, v={:?}, user_ty={:?}, locations={:?})",
980+
a, v, user_ty, locations,
983981
);
984982

985-
// The `TypeRelating` code assumes that "unresolved inference
986-
// variables" appear in the "a" side, so flip `Contravariant`
987-
// ambient variance to get the right relationship.
988-
let v1 = ty::Contravariant.xform(v);
989-
990983
match user_ty {
991984
UserTypeAnnotation::Ty(canonical_ty) => {
992985
let (ty, _) = self.infcx
993986
.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty);
994987

995-
self.relate_types(ty, v1, a, locations, category)?;
988+
// The `TypeRelating` code assumes that "unresolved inference
989+
// variables" appear in the "a" side, so flip `Contravariant`
990+
// ambient variance to get the right relationship.
991+
let v1 = ty::Contravariant.xform(v);
996992

997-
self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
993+
self.relate_types(ty, v1, a, locations, category)?;
998994
}
999995
UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
1000996
let (
1001-
UserSubsts {
1002-
substs,
1003-
user_self_ty,
1004-
},
997+
user_substs,
1005998
_,
1006999
) = self.infcx
10071000
.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
10081001

1009-
let ty = self.tcx().type_of(def_id);
1010-
let ty = ty.subst(tcx, substs);
1011-
debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
1012-
let ty = self.normalize(ty, locations);
1013-
1014-
self.relate_types(ty, v1, a, locations, category)?;
1015-
1016-
if let Some(UserSelfTy {
1017-
impl_def_id,
1018-
self_ty,
1019-
}) = user_self_ty
1020-
{
1021-
let impl_self_ty = tcx.type_of(impl_def_id);
1022-
let impl_self_ty = impl_self_ty.subst(tcx, &substs);
1023-
let impl_self_ty = self.normalize(impl_self_ty, locations);
1024-
1025-
// There may be type variables in `substs` and hence
1026-
// in `impl_self_ty`, but they should all have been
1027-
// resolved to some fixed value during the first call
1028-
// to `relate`, above. Therefore, if we use
1029-
// `resolve_type_vars_if_possible` we should get to
1030-
// something without type variables. This is important
1031-
// because the `b` type in `relate_with_variance`
1032-
// below is not permitted to have inference variables.
1033-
let impl_self_ty = self.infcx.resolve_type_vars_if_possible(&impl_self_ty);
1034-
assert!(!impl_self_ty.has_infer_types());
1035-
1036-
self.eq_types(self_ty, impl_self_ty, locations, category)?;
1037-
1038-
self.prove_predicate(
1039-
ty::Predicate::WellFormed(impl_self_ty),
1040-
locations,
1041-
category,
1042-
);
1043-
}
1044-
1045-
// Prove the predicates coming along with `def_id`.
1046-
//
1047-
// Also, normalize the `instantiated_predicates`
1048-
// because otherwise we wind up with duplicate "type
1049-
// outlives" error messages.
1050-
let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
1051-
let instantiated_predicates = self.fold_to_region_vid(instantiated_predicates);
1052-
self.normalize_and_prove_instantiated_predicates(
1053-
instantiated_predicates,
1002+
self.fully_perform_op(
10541003
locations,
1055-
);
1056-
1057-
// In addition to proving the predicates, we have to
1058-
// prove that `ty` is well-formed -- this is because
1059-
// the WF of `ty` is predicated on the substs being
1060-
// well-formed, and we haven't proven *that*. We don't
1061-
// want to prove the WF of types from `substs` directly because they
1062-
// haven't been normalized.
1063-
//
1064-
// FIXME(nmatsakis): Well, perhaps we should normalize
1065-
// them? This would only be relevant if some input
1066-
// type were ill-formed but did not appear in `ty`,
1067-
// which...could happen with normalization...
1068-
self.prove_predicate(ty::Predicate::WellFormed(ty), locations, category);
1004+
category,
1005+
self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
1006+
a, v, def_id, user_substs,
1007+
)),
1008+
)?;
10691009
}
10701010
}
10711011

10721012
Ok(())
10731013
}
10741014

1075-
/// Replace all free regions in `value` with their NLL `RegionVid`
1076-
/// equivalents; if not in NLL, does nothing. This is never
1077-
/// particularly necessary -- we'll do it lazilly as we process
1078-
/// the value anyway -- but in some specific cases it is useful to
1079-
/// normalize so we can suppress duplicate error messages.
1080-
fn fold_to_region_vid<T>(&self, value: T) -> T
1081-
where
1082-
T: TypeFoldable<'tcx>,
1083-
{
1084-
if let Some(borrowck_context) = &self.borrowck_context {
1085-
self.tcx().fold_regions(&value, &mut false, |r, _debruijn| {
1086-
if r.has_free_regions() {
1087-
self.tcx().mk_region(ty::RegionKind::ReVar(
1088-
borrowck_context.universal_regions.to_region_vid(r),
1089-
))
1090-
} else {
1091-
r
1092-
}
1093-
})
1094-
} else {
1095-
value
1096-
}
1097-
}
1098-
10991015
fn eq_opaque_type_and_type(
11001016
&mut self,
11011017
revealed_ty: Ty<'tcx>,

0 commit comments

Comments
 (0)