Skip to content

Commit 3476ac0

Browse files
committed
Auto merge of #55323 - nikomatsakis:nll-ICE-55219-and-55241, r=pnkfelix
introduce type-op for user-type ascription in NLL Handle user-type ascription in a type operator, which gives us a lot more flexibility around the order in which we resolve things. r? @pnkfelix Fixes #55219 Fixes #55241
2 parents 365b900 + 62f0fc5 commit 3476ac0

File tree

15 files changed

+367
-126
lines changed

15 files changed

+367
-126
lines changed

src/librustc/dep_graph/dep_node.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ use std::hash::Hash;
7272
use syntax_pos::symbol::InternedString;
7373
use traits;
7474
use traits::query::{
75-
CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal,
76-
CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
75+
CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal,
76+
CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal, CanonicalPredicateGoal,
77+
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
7778
};
7879
use ty::{TyCtxt, FnSig, Instance, InstanceDef,
7980
ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty};
@@ -654,6 +655,7 @@ define_dep_nodes!( <'tcx>
654655
[] ImpliedOutlivesBounds(CanonicalTyGoal<'tcx>),
655656
[] DropckOutlives(CanonicalTyGoal<'tcx>),
656657
[] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
658+
[] TypeOpAscribeUserType(CanonicalTypeOpAscribeUserTypeGoal<'tcx>),
657659
[] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>),
658660
[] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>),
659661
[] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'tcx>),

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/mir/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -2438,6 +2438,14 @@ EnumTypeFoldableImpl! {
24382438
}
24392439
}
24402440

2441+
EnumLiftImpl! {
2442+
impl<'a, 'tcx> Lift<'tcx> for UserTypeAnnotation<'a> {
2443+
type Lifted = UserTypeAnnotation<'tcx>;
2444+
(UserTypeAnnotation::Ty)(ty),
2445+
(UserTypeAnnotation::TypeOf)(def, substs),
2446+
}
2447+
}
2448+
24412449
newtype_index! {
24422450
pub struct Promoted {
24432451
DEBUG_FORMAT = "promoted[{}]"

src/librustc/traits/query/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>
3434
pub type CanonicalPredicateGoal<'tcx> =
3535
Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>;
3636

37+
pub type CanonicalTypeOpAscribeUserTypeGoal<'tcx> =
38+
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::ascribe_user_type::AscribeUserType<'tcx>>>;
39+
3740
pub type CanonicalTypeOpEqGoal<'tcx> =
3841
Canonical<'tcx, ty::ParamEnvAnd<'tcx, type_op::eq::Eq<'tcx>>>;
3942

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResponse, QueryResponse};
12+
use traits::query::Fallible;
13+
use hir::def_id::DefId;
14+
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
15+
use ty::subst::UserSubsts;
16+
17+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
18+
pub struct AscribeUserType<'tcx> {
19+
pub mir_ty: Ty<'tcx>,
20+
pub variance: ty::Variance,
21+
pub def_id: DefId,
22+
pub user_substs: UserSubsts<'tcx>,
23+
}
24+
25+
impl<'tcx> AscribeUserType<'tcx> {
26+
pub fn new(
27+
mir_ty: Ty<'tcx>,
28+
variance: ty::Variance,
29+
def_id: DefId,
30+
user_substs: UserSubsts<'tcx>,
31+
) -> Self {
32+
AscribeUserType { mir_ty, variance, def_id, user_substs }
33+
}
34+
}
35+
36+
impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for AscribeUserType<'tcx> {
37+
type QueryResponse = ();
38+
39+
fn try_fast_path(
40+
_tcx: TyCtxt<'_, 'gcx, 'tcx>,
41+
_key: &ParamEnvAnd<'tcx, Self>,
42+
) -> Option<Self::QueryResponse> {
43+
None
44+
}
45+
46+
fn perform_query(
47+
tcx: TyCtxt<'_, 'gcx, 'tcx>,
48+
canonicalized: Canonicalized<'gcx, ParamEnvAnd<'tcx, Self>>,
49+
) -> Fallible<CanonicalizedQueryResponse<'gcx, ()>> {
50+
tcx.type_op_ascribe_user_type(canonicalized)
51+
}
52+
53+
fn shrink_to_tcx_lifetime(
54+
v: &'a CanonicalizedQueryResponse<'gcx, ()>,
55+
) -> &'a Canonical<'tcx, QueryResponse<'tcx, ()>> {
56+
v
57+
}
58+
}
59+
60+
BraceStructTypeFoldableImpl! {
61+
impl<'tcx> TypeFoldable<'tcx> for AscribeUserType<'tcx> {
62+
mir_ty, variance, def_id, user_substs
63+
}
64+
}
65+
66+
BraceStructLiftImpl! {
67+
impl<'a, 'tcx> Lift<'tcx> for AscribeUserType<'a> {
68+
type Lifted = AscribeUserType<'tcx>;
69+
mir_ty, variance, def_id, user_substs
70+
}
71+
}
72+
73+
impl_stable_hash_for! {
74+
struct AscribeUserType<'tcx> {
75+
mir_ty, variance, def_id, user_substs
76+
}
77+
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use traits::ObligationCause;
2020
use ty::fold::TypeFoldable;
2121
use ty::{Lift, ParamEnvAnd, TyCtxt};
2222

23+
pub mod ascribe_user_type;
2324
pub mod custom;
2425
pub mod eq;
2526
pub mod implied_outlives_bounds;

src/librustc/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ impl Visibility {
330330
}
331331
}
332332

333-
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)]
333+
#[derive(Copy, Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Hash)]
334334
pub enum Variance {
335335
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
336336
Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell

src/librustc/ty/query/config.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ use hir::def_id::{CrateNum, DefId, DefIndex};
1414
use mir::interpret::GlobalId;
1515
use traits;
1616
use traits::query::{
17-
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal,
18-
CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
17+
CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal,
18+
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal,
19+
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal,
1920
};
2021
use ty::{self, ParamEnvAnd, Ty, TyCtxt};
2122
use ty::subst::Substs;
@@ -115,6 +116,15 @@ impl<'tcx> QueryDescription<'tcx> for queries::evaluate_obligation<'tcx> {
115116
}
116117
}
117118

119+
impl<'tcx> QueryDescription<'tcx> for queries::type_op_ascribe_user_type<'tcx> {
120+
fn describe(
121+
_tcx: TyCtxt<'_, '_, '_>,
122+
goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx>,
123+
) -> Cow<'static, str> {
124+
format!("evaluating `type_op_ascribe_user_type` `{:?}`", goal).into()
125+
}
126+
}
127+
118128
impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> {
119129
fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> Cow<'static, str> {
120130
format!("evaluating `type_op_eq` `{:?}`", goal).into()

src/librustc/ty/query/mod.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@ use mir::interpret::GlobalId;
3434
use session::{CompileResult, CrateDisambiguator};
3535
use session::config::OutputFilenames;
3636
use traits::{self, Vtable};
37-
use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal,
38-
CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal,
39-
CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal, NoSolution};
37+
use traits::query::{
38+
CanonicalPredicateGoal, CanonicalProjectionGoal,
39+
CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal,
40+
CanonicalTypeOpSubtypeGoal, CanonicalTypeOpProvePredicateGoal,
41+
CanonicalTypeOpNormalizeGoal, NoSolution,
42+
};
4043
use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
4144
use traits::query::normalize::NormalizationResult;
4245
use traits::query::outlives_bounds::OutlivesBound;
@@ -589,6 +592,14 @@ define_queries! { <'tcx>
589592
CanonicalPredicateGoal<'tcx>
590593
) -> Result<traits::EvaluationResult, traits::OverflowError>,
591594

595+
/// Do not call this query directly: part of the `Eq` type-op
596+
[] fn type_op_ascribe_user_type: TypeOpAscribeUserType(
597+
CanonicalTypeOpAscribeUserTypeGoal<'tcx>
598+
) -> Result<
599+
Lrc<Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>>,
600+
NoSolution,
601+
>,
602+
592603
/// Do not call this query directly: part of the `Eq` type-op
593604
[] fn type_op_eq: TypeOpEq(
594605
CanonicalTypeOpEqGoal<'tcx>

src/librustc/ty/query/plumbing.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
10791079
DepKind::ImpliedOutlivesBounds |
10801080
DepKind::DropckOutlives |
10811081
DepKind::EvaluateObligation |
1082+
DepKind::TypeOpAscribeUserType |
10821083
DepKind::TypeOpEq |
10831084
DepKind::TypeOpSubtype |
10841085
DepKind::TypeOpProvePredicate |

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

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

10711012
Ok(())
10721013
}
10731014

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

0 commit comments

Comments
 (0)