Skip to content

Commit 4ab5bcb

Browse files
committed
introduce Normalizable trait for things directly normalizable
1 parent 79ccf81 commit 4ab5bcb

File tree

13 files changed

+362
-57
lines changed

13 files changed

+362
-57
lines changed

src/librustc/dep_graph/dep_node.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ use std::hash::Hash;
7272
use syntax_pos::symbol::InternedString;
7373
use traits::query::{
7474
CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpSubtypeGoal,
75-
CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal,
75+
CanonicalPredicateGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpNormalizeGoal,
7676
};
77-
use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
77+
use ty::{TyCtxt, FnSig, Instance, InstanceDef,
78+
ParamEnv, ParamEnvAnd, Predicate, PolyFnSig, PolyTraitRef, Ty};
7879
use ty::subst::Substs;
7980

8081
// erase!() just makes tokens go away. It's used to specify which macro argument
@@ -652,6 +653,10 @@ define_dep_nodes!( <'tcx>
652653
[] TypeOpEq(CanonicalTypeOpEqGoal<'tcx>),
653654
[] TypeOpSubtype(CanonicalTypeOpSubtypeGoal<'tcx>),
654655
[] TypeOpProvePredicate(CanonicalTypeOpProvePredicateGoal<'tcx>),
656+
[] TypeOpNormalizeTy(CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>),
657+
[] TypeOpNormalizePredicate(CanonicalTypeOpNormalizeGoal<'tcx, Predicate<'tcx>>),
658+
[] TypeOpNormalizePolyFnSig(CanonicalTypeOpNormalizeGoal<'tcx, PolyFnSig<'tcx>>),
659+
[] TypeOpNormalizeFnSig(CanonicalTypeOpNormalizeGoal<'tcx, FnSig<'tcx>>),
655660

656661
[] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
657662

src/librustc/traits/query/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ pub type CanonicalTypeOpSubtypeGoal<'tcx> =
4141
pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
4242
Canonical<'tcx, type_op::prove_predicate::ProvePredicate<'tcx>>;
4343

44+
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
45+
Canonical<'tcx, type_op::normalize::Normalize<'tcx, T>>;
46+
4447
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
4548
pub struct NoSolution;
4649

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use infer::canonical::{Canonical, CanonicalizedQueryResult};
11+
use infer::canonical::{Canonical, CanonicalizedQueryResult, QueryResult};
1212
use ty::{self, ParamEnv, Ty, TyCtxt};
1313

1414
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -45,6 +45,12 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Eq<'tcx> {
4545
) -> CanonicalizedQueryResult<'gcx, ()> {
4646
tcx.type_op_eq(canonicalized).unwrap()
4747
}
48+
49+
fn upcast_result(
50+
v: &'a CanonicalizedQueryResult<'gcx, ()>,
51+
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
52+
v
53+
}
4854
}
4955

5056
BraceStructTypeFoldableImpl! {

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

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@
99
// except according to those terms.
1010

1111
use infer::canonical::query_result;
12-
use infer::canonical::{Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint};
12+
use infer::canonical::{
13+
Canonical, Canonicalized, CanonicalizedQueryResult, QueryRegionConstraint, QueryResult,
14+
};
1315
use infer::{InferCtxt, InferOk, InferResult};
16+
use std::fmt;
17+
use std::rc::Rc;
18+
use syntax::codemap::DUMMY_SP;
1419
use traits::{ObligationCause, TraitEngine};
1520
use ty::error::TypeError;
1621
use ty::fold::TypeFoldable;
1722
use ty::{Lift, ParamEnv, TyCtxt};
18-
use std::fmt;
19-
use std::rc::Rc;
20-
use syntax::codemap::DUMMY_SP;
2123

2224
pub mod custom;
2325
pub mod eq;
@@ -98,32 +100,37 @@ pub trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
98100
}
99101
}
100102

101-
type Lifted<'gcx, T> = <T as Lift<'gcx>>::Lifted;
102-
103103
pub trait QueryTypeOp<'gcx: 'tcx, 'tcx>: TypeFoldable<'tcx> + Lift<'gcx> {
104104
type QueryResult: TypeFoldable<'tcx> + Lift<'gcx>;
105105

106106
/// Micro-optimization: returns `Ok(x)` if we can trivially
107107
/// produce the output, else returns `Err(self)` back.
108-
fn trivial_noop(
109-
self,
110-
tcx: TyCtxt<'_, 'gcx, 'tcx>,
111-
) -> Result<Lifted<'gcx, Self::QueryResult>, Self>;
108+
fn trivial_noop(self, tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::QueryResult, Self>;
112109

113110
fn param_env(&self) -> ParamEnv<'tcx>;
114111

115112
fn perform_query(
116113
tcx: TyCtxt<'_, 'gcx, 'tcx>,
117114
canonicalized: Canonicalized<'gcx, Self>,
118115
) -> CanonicalizedQueryResult<'gcx, Self::QueryResult>;
116+
117+
/// "Upcasts" a lifted query result (which is in the gcx lifetime)
118+
/// into the tcx lifetime. This is always just an identity cast,
119+
/// but the generic code does't realize it, so we have to push the
120+
/// operation into the impls that know more specifically what
121+
/// `QueryResult` is. This operation would (maybe) be nicer with
122+
/// something like HKTs or GATs, since then we could make
123+
/// `QueryResult` parametric and `'gcx` and `'tcx` etc.
124+
fn upcast_result(
125+
lifted_query_result: &'a CanonicalizedQueryResult<'gcx, Self::QueryResult>,
126+
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self::QueryResult>>;
119127
}
120128

121129
impl<'gcx: 'tcx, 'tcx, Q> TypeOp<'gcx, 'tcx> for Q
122130
where
123131
Q: QueryTypeOp<'gcx, 'tcx>,
124-
Lifted<'gcx, Q::QueryResult>: TypeFoldable<'tcx>,
125132
{
126-
type Output = Lifted<'gcx, Q::QueryResult>;
133+
type Output = Q::QueryResult;
127134

128135
fn trivial_noop(self, tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::Output, Self> {
129136
QueryTypeOp::trivial_noop(self, tcx)
@@ -152,7 +159,7 @@ where
152159
&ObligationCause::dummy(),
153160
param_env,
154161
&canonical_var_values,
155-
&canonical_result,
162+
Q::upcast_result(&canonical_result),
156163
)
157164
}
158165
}

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

Lines changed: 131 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,15 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use infer::{InferCtxt, InferOk, InferResult};
12-
use traits::query::NoSolution;
13-
use traits::{Normalized, ObligationCause};
14-
use ty::fold::TypeFoldable;
15-
use ty::{ParamEnv, TyCtxt};
11+
use infer::canonical::{Canonical, Canonicalized, CanonicalizedQueryResult, QueryResult};
1612
use std::fmt;
13+
use ty::fold::TypeFoldable;
14+
use ty::{self, Lift, ParamEnv, Ty, TyCtxt};
1715

18-
#[derive(Debug)]
16+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
1917
pub struct Normalize<'tcx, T> {
20-
param_env: ParamEnv<'tcx>,
21-
value: T,
18+
pub param_env: ParamEnv<'tcx>,
19+
pub value: T,
2220
}
2321

2422
impl<'tcx, T> Normalize<'tcx, T>
@@ -30,27 +28,140 @@ where
3028
}
3129
}
3230

33-
impl<'gcx, 'tcx, T> super::TypeOp<'gcx, 'tcx> for Normalize<'tcx, T>
31+
impl<'gcx: 'tcx, 'tcx, T> super::QueryTypeOp<'gcx, 'tcx> for Normalize<'tcx, T>
3432
where
35-
T: fmt::Debug + TypeFoldable<'tcx>,
33+
T: Normalizable<'gcx, 'tcx>,
3634
{
37-
type Output = T;
35+
type QueryResult = T;
3836

39-
fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<Self::Output, Self> {
37+
fn trivial_noop(self, _tcx: TyCtxt<'_, 'gcx, 'tcx>) -> Result<T, Self> {
4038
if !self.value.has_projections() {
4139
Ok(self.value)
4240
} else {
4341
Err(self)
4442
}
4543
}
4644

47-
fn perform(self, infcx: &InferCtxt<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output> {
48-
let Normalized { value, obligations } = infcx
49-
.at(&ObligationCause::dummy(), self.param_env)
50-
.normalize(&self.value)
51-
.unwrap_or_else(|NoSolution| {
52-
bug!("normalization of `{:?}` failed", self.value,);
53-
});
54-
Ok(InferOk { value, obligations })
45+
fn param_env(&self) -> ParamEnv<'tcx> {
46+
self.param_env
47+
}
48+
49+
fn perform_query(
50+
tcx: TyCtxt<'_, 'gcx, 'tcx>,
51+
canonicalized: Canonicalized<'gcx, Self>,
52+
) -> CanonicalizedQueryResult<'gcx, Self::QueryResult> {
53+
T::type_op_method(tcx, canonicalized)
54+
}
55+
56+
fn upcast_result(
57+
v: &'a CanonicalizedQueryResult<'gcx, T>,
58+
) -> &'a Canonical<'tcx, QueryResult<'tcx, T>> {
59+
T::upcast_result(v)
60+
}
61+
}
62+
63+
pub trait Normalizable<'gcx, 'tcx>: fmt::Debug + TypeFoldable<'tcx> + Lift<'gcx> {
64+
fn type_op_method(
65+
tcx: TyCtxt<'_, 'gcx, 'tcx>,
66+
canonicalized: Canonicalized<'gcx, Normalize<'gcx, Self>>,
67+
) -> CanonicalizedQueryResult<'gcx, Self>;
68+
69+
/// Convert from the `'gcx` (lifted) form of `Self` into the `tcx`
70+
/// form of `Self`.
71+
fn upcast_result(
72+
v: &'a CanonicalizedQueryResult<'gcx, Self>,
73+
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>>;
74+
}
75+
76+
impl Normalizable<'gcx, 'tcx> for Ty<'tcx>
77+
where
78+
'gcx: 'tcx,
79+
{
80+
fn type_op_method(
81+
tcx: TyCtxt<'_, 'gcx, 'tcx>,
82+
canonicalized: Canonicalized<'gcx, Normalize<'gcx, Self>>,
83+
) -> CanonicalizedQueryResult<'gcx, Self> {
84+
tcx.type_op_normalize_ty(canonicalized).unwrap()
85+
}
86+
87+
fn upcast_result(
88+
v: &'a CanonicalizedQueryResult<'gcx, Self>,
89+
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
90+
v
91+
}
92+
}
93+
94+
impl Normalizable<'gcx, 'tcx> for ty::Predicate<'tcx>
95+
where
96+
'gcx: 'tcx,
97+
{
98+
fn type_op_method(
99+
tcx: TyCtxt<'_, 'gcx, 'tcx>,
100+
canonicalized: Canonicalized<'gcx, Normalize<'gcx, Self>>,
101+
) -> CanonicalizedQueryResult<'gcx, Self> {
102+
tcx.type_op_normalize_predicate(canonicalized).unwrap()
103+
}
104+
105+
fn upcast_result(
106+
v: &'a CanonicalizedQueryResult<'gcx, Self>,
107+
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
108+
v
109+
}
110+
}
111+
112+
impl Normalizable<'gcx, 'tcx> for ty::PolyFnSig<'tcx>
113+
where
114+
'gcx: 'tcx,
115+
{
116+
fn type_op_method(
117+
tcx: TyCtxt<'_, 'gcx, 'tcx>,
118+
canonicalized: Canonicalized<'gcx, Normalize<'gcx, Self>>,
119+
) -> CanonicalizedQueryResult<'gcx, Self> {
120+
tcx.type_op_normalize_poly_fn_sig(canonicalized).unwrap()
121+
}
122+
123+
fn upcast_result(
124+
v: &'a CanonicalizedQueryResult<'gcx, Self>,
125+
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
126+
v
127+
}
128+
}
129+
130+
impl Normalizable<'gcx, 'tcx> for ty::FnSig<'tcx>
131+
where
132+
'gcx: 'tcx,
133+
{
134+
fn type_op_method(
135+
tcx: TyCtxt<'_, 'gcx, 'tcx>,
136+
canonicalized: Canonicalized<'gcx, Normalize<'gcx, Self>>,
137+
) -> CanonicalizedQueryResult<'gcx, Self> {
138+
tcx.type_op_normalize_fn_sig(canonicalized).unwrap()
139+
}
140+
141+
fn upcast_result(
142+
v: &'a CanonicalizedQueryResult<'gcx, Self>,
143+
) -> &'a Canonical<'tcx, QueryResult<'tcx, Self>> {
144+
v
145+
}
146+
}
147+
148+
BraceStructTypeFoldableImpl! {
149+
impl<'tcx, T> TypeFoldable<'tcx> for Normalize<'tcx, T> {
150+
param_env,
151+
value,
152+
} where T: TypeFoldable<'tcx>,
153+
}
154+
155+
BraceStructLiftImpl! {
156+
impl<'a, 'tcx, T> Lift<'tcx> for Normalize<'a, T> {
157+
type Lifted = Normalize<'tcx, T::Lifted>;
158+
param_env,
159+
value,
160+
} where T: Lift<'tcx>,
161+
}
162+
163+
impl_stable_hash_for! {
164+
impl<'tcx, T> for struct Normalize<'tcx, T> {
165+
param_env, value
55166
}
56167
}

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use infer::canonical::{Canonical, CanonicalizedQueryResult};
11+
use infer::canonical::{Canonical, CanonicalizedQueryResult, QueryResult};
1212
use ty::{ParamEnv, Predicate, TyCtxt};
1313

1414
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -18,11 +18,11 @@ pub struct ProvePredicate<'tcx> {
1818
}
1919

2020
impl<'tcx> ProvePredicate<'tcx> {
21-
pub fn new(
22-
param_env: ParamEnv<'tcx>,
23-
predicate: Predicate<'tcx>,
24-
) -> Self {
25-
ProvePredicate { param_env, predicate }
21+
pub fn new(param_env: ParamEnv<'tcx>, predicate: Predicate<'tcx>) -> Self {
22+
ProvePredicate {
23+
param_env,
24+
predicate,
25+
}
2626
}
2727
}
2828

@@ -43,6 +43,12 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for ProvePredicate<'tcx> {
4343
) -> CanonicalizedQueryResult<'gcx, ()> {
4444
tcx.type_op_prove_predicate(canonicalized).unwrap()
4545
}
46+
47+
fn upcast_result(
48+
v: &'a CanonicalizedQueryResult<'gcx, ()>,
49+
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
50+
v
51+
}
4652
}
4753

4854
BraceStructTypeFoldableImpl! {

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use infer::canonical::{Canonical, CanonicalizedQueryResult};
11+
use infer::canonical::{Canonical, CanonicalizedQueryResult, QueryResult};
1212
use ty::{ParamEnv, Ty, TyCtxt};
1313

1414
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -49,6 +49,12 @@ impl<'gcx: 'tcx, 'tcx> super::QueryTypeOp<'gcx, 'tcx> for Subtype<'tcx> {
4949
) -> CanonicalizedQueryResult<'gcx, ()> {
5050
tcx.type_op_subtype(canonicalized).unwrap()
5151
}
52+
53+
fn upcast_result(
54+
v: &'a CanonicalizedQueryResult<'gcx, ()>,
55+
) -> &'a Canonical<'tcx, QueryResult<'tcx, ()>> {
56+
v
57+
}
5258
}
5359

5460
BraceStructTypeFoldableImpl! {

0 commit comments

Comments
 (0)