1
1
use crate :: mir:: Mutability ;
2
- use crate :: ty:: { self , Ty , TyCtxt } ;
3
- use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
2
+ use crate :: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
4
3
use rustc_hir:: def_id:: DefId ;
5
- use rustc_query_system:: ich:: StableHashingContext ;
6
4
use std:: fmt:: Debug ;
7
5
use std:: hash:: Hash ;
8
- use std:: mem;
9
6
10
7
use self :: SimplifiedTypeGen :: * ;
11
8
@@ -17,7 +14,7 @@ pub type SimplifiedType = SimplifiedTypeGen<DefId>;
17
14
/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
18
15
/// keys (in which case we use a DefPathHash as id-type) but in the general case
19
16
/// the non-stable but fast to construct DefId-version is the better choice.
20
- #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , TyEncodable , TyDecodable ) ]
17
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash , TyEncodable , TyDecodable , HashStable ) ]
21
18
pub enum SimplifiedTypeGen < D >
22
19
where
23
20
D : Copy + Debug + Eq ,
@@ -45,34 +42,49 @@ where
45
42
GeneratorWitnessSimplifiedType ( usize ) ,
46
43
OpaqueSimplifiedType ( D ) ,
47
44
FunctionSimplifiedType ( usize ) ,
48
- ParameterSimplifiedType ,
45
+ PlaceholderSimplifiedType ,
49
46
}
50
47
48
+ /// Generic parameters are pretty much just bound variables, e.g.
49
+ /// the type of `fn foo<'a, T>(x: &'a T) -> u32 { ... }` can be thought of as
50
+ /// `for<'a, T> fn(&'a T) -> u32`.
51
+ ///
52
+ /// Typecheck of `foo` has to succeed for all possible generic arguments, so
53
+ /// during typeck, we have to treat its generic parameters as if they
54
+ /// were placeholders.
55
+ ///
56
+ /// But when calling `foo` we only have to provide a specific generic argument.
57
+ /// In that case the generic parameters are instantiated with inference variables.
58
+ /// As we use `simplify_type` before that instantiation happens, we just treat
59
+ /// generic parameters as if they were inference variables in that case.
51
60
#[ derive( PartialEq , Eq , Debug , Clone , Copy ) ]
52
61
pub enum TreatParams {
53
- /// Treat parameters as bound types in the given environment.
62
+ /// Treat parameters as placeholders in the given environment.
54
63
///
55
- /// For this to be correct the input has to be fully normalized
56
- /// in its param env as it may otherwise cause us to ignore
57
- /// potentially applying impls.
58
- AsBoundTypes ,
59
- AsPlaceholders ,
64
+ /// Note that this also causes us to treat projections as if they were
65
+ /// placeholders. This is only correct if the given projection cannot
66
+ /// be normalized in the current context. Even if normalization fails,
67
+ /// it may still succeed later if the projection contains any inference
68
+ /// variables.
69
+ AsPlaceholder ,
70
+ AsInfer ,
60
71
}
61
72
62
73
/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
63
74
///
64
75
/// The idea is to get something simple that we can use to quickly decide if two types could unify,
65
- /// for example during method lookup.
76
+ /// for example during method lookup. If this function returns `Some(x)` it can only unify with
77
+ /// types for which this method returns either `Some(x)` as well or `None`.
66
78
///
67
79
/// A special case here are parameters and projections, which are only injective
68
- /// if they are treated as bound types .
80
+ /// if they are treated as placeholders .
69
81
///
70
82
/// For example when storing impls based on their simplified self type, we treat
71
- /// generic parameters as placeholders . We must not simplify them here,
83
+ /// generic parameters as if they were inference variables . We must not simplify them here,
72
84
/// as they can unify with any other type.
73
85
///
74
- /// With projections we have to be even more careful, as even when treating them as bound types
75
- /// this is still only correct if they are fully normalized.
86
+ /// With projections we have to be even more careful, as treating them as placeholders
87
+ /// is only correct if they are fully normalized.
76
88
///
77
89
/// ¹ meaning that if the outermost layers are different, then the whole types are also different.
78
90
pub fn simplify_type < ' tcx > (
@@ -104,20 +116,25 @@ pub fn simplify_type<'tcx>(
104
116
ty:: Never => Some ( NeverSimplifiedType ) ,
105
117
ty:: Tuple ( tys) => Some ( TupleSimplifiedType ( tys. len ( ) ) ) ,
106
118
ty:: FnPtr ( f) => Some ( FunctionSimplifiedType ( f. skip_binder ( ) . inputs ( ) . len ( ) ) ) ,
107
- ty:: Param ( _) | ty:: Projection ( _) => match treat_params {
108
- // When treated as bound types, projections don't unify with
109
- // anything as long as they are fully normalized.
119
+ ty:: Placeholder ( ..) => Some ( PlaceholderSimplifiedType ) ,
120
+ ty:: Param ( _) => match treat_params {
121
+ TreatParams :: AsPlaceholder => Some ( PlaceholderSimplifiedType ) ,
122
+ TreatParams :: AsInfer => None ,
123
+ } ,
124
+ ty:: Projection ( _) => match treat_params {
125
+ // When treating `ty::Param` as a placeholder, projections also
126
+ // don't unify with anything else as long as they are fully normalized.
110
127
//
111
128
// We will have to be careful with lazy normalization here.
112
- TreatParams :: AsBoundTypes => {
113
- debug ! ( "treating `{}` as a bound type " , ty) ;
114
- Some ( ParameterSimplifiedType )
129
+ TreatParams :: AsPlaceholder if !ty . has_infer_types_or_consts ( ) => {
130
+ debug ! ( "treating `{}` as a placeholder " , ty) ;
131
+ Some ( PlaceholderSimplifiedType )
115
132
}
116
- TreatParams :: AsPlaceholders => None ,
133
+ TreatParams :: AsPlaceholder | TreatParams :: AsInfer => None ,
117
134
} ,
118
135
ty:: Opaque ( def_id, _) => Some ( OpaqueSimplifiedType ( def_id) ) ,
119
136
ty:: Foreign ( def_id) => Some ( ForeignSimplifiedType ( def_id) ) ,
120
- ty:: Placeholder ( .. ) | ty :: Bound ( ..) | ty:: Infer ( _) | ty:: Error ( _) => None ,
137
+ ty:: Bound ( ..) | ty:: Infer ( _) | ty:: Error ( _) => None ,
121
138
}
122
139
}
123
140
@@ -161,41 +178,7 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
161
178
GeneratorWitnessSimplifiedType ( n) => GeneratorWitnessSimplifiedType ( n) ,
162
179
OpaqueSimplifiedType ( d) => OpaqueSimplifiedType ( map ( d) ) ,
163
180
FunctionSimplifiedType ( n) => FunctionSimplifiedType ( n) ,
164
- ParameterSimplifiedType => ParameterSimplifiedType ,
165
- }
166
- }
167
- }
168
-
169
- impl < ' a , D > HashStable < StableHashingContext < ' a > > for SimplifiedTypeGen < D >
170
- where
171
- D : Copy + Debug + Eq + HashStable < StableHashingContext < ' a > > ,
172
- {
173
- fn hash_stable ( & self , hcx : & mut StableHashingContext < ' a > , hasher : & mut StableHasher ) {
174
- mem:: discriminant ( self ) . hash_stable ( hcx, hasher) ;
175
- match * self {
176
- BoolSimplifiedType
177
- | CharSimplifiedType
178
- | StrSimplifiedType
179
- | ArraySimplifiedType
180
- | SliceSimplifiedType
181
- | NeverSimplifiedType
182
- | ParameterSimplifiedType
183
- | MarkerTraitObjectSimplifiedType => {
184
- // nothing to do
185
- }
186
- RefSimplifiedType ( m) | PtrSimplifiedType ( m) => m. hash_stable ( hcx, hasher) ,
187
- IntSimplifiedType ( t) => t. hash_stable ( hcx, hasher) ,
188
- UintSimplifiedType ( t) => t. hash_stable ( hcx, hasher) ,
189
- FloatSimplifiedType ( t) => t. hash_stable ( hcx, hasher) ,
190
- AdtSimplifiedType ( d) => d. hash_stable ( hcx, hasher) ,
191
- TupleSimplifiedType ( n) => n. hash_stable ( hcx, hasher) ,
192
- TraitSimplifiedType ( d) => d. hash_stable ( hcx, hasher) ,
193
- ClosureSimplifiedType ( d) => d. hash_stable ( hcx, hasher) ,
194
- GeneratorSimplifiedType ( d) => d. hash_stable ( hcx, hasher) ,
195
- GeneratorWitnessSimplifiedType ( n) => n. hash_stable ( hcx, hasher) ,
196
- OpaqueSimplifiedType ( d) => d. hash_stable ( hcx, hasher) ,
197
- FunctionSimplifiedType ( n) => n. hash_stable ( hcx, hasher) ,
198
- ForeignSimplifiedType ( d) => d. hash_stable ( hcx, hasher) ,
181
+ PlaceholderSimplifiedType => PlaceholderSimplifiedType ,
199
182
}
200
183
}
201
184
}
0 commit comments