11use 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 } ;
43use rustc_hir:: def_id:: DefId ;
5- use rustc_query_system:: ich:: StableHashingContext ;
64use std:: fmt:: Debug ;
75use std:: hash:: Hash ;
8- use std:: mem;
96
107use self :: SimplifiedTypeGen :: * ;
118
@@ -17,7 +14,7 @@ pub type SimplifiedType = SimplifiedTypeGen<DefId>;
1714/// because we sometimes need to use SimplifiedTypeGen values as stable sorting
1815/// keys (in which case we use a DefPathHash as id-type) but in the general case
1916/// 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 ) ]
2118pub enum SimplifiedTypeGen < D >
2219where
2320 D : Copy + Debug + Eq ,
@@ -45,34 +42,49 @@ where
4542 GeneratorWitnessSimplifiedType ( usize ) ,
4643 OpaqueSimplifiedType ( D ) ,
4744 FunctionSimplifiedType ( usize ) ,
48- ParameterSimplifiedType ,
45+ PlaceholderSimplifiedType ,
4946}
5047
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.
5160#[ derive( PartialEq , Eq , Debug , Clone , Copy ) ]
5261pub enum TreatParams {
53- /// Treat parameters as bound types in the given environment.
62+ /// Treat parameters as placeholders in the given environment.
5463 ///
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 ,
6071}
6172
6273/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
6374///
6475/// 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`.
6678///
6779/// 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 .
6981///
7082/// 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,
7284/// as they can unify with any other type.
7385///
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.
7688///
7789/// ¹ meaning that if the outermost layers are different, then the whole types are also different.
7890pub fn simplify_type < ' tcx > (
@@ -104,20 +116,25 @@ pub fn simplify_type<'tcx>(
104116 ty:: Never => Some ( NeverSimplifiedType ) ,
105117 ty:: Tuple ( tys) => Some ( TupleSimplifiedType ( tys. len ( ) ) ) ,
106118 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.
110127 //
111128 // 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 )
115132 }
116- TreatParams :: AsPlaceholders => None ,
133+ TreatParams :: AsPlaceholder | TreatParams :: AsInfer => None ,
117134 } ,
118135 ty:: Opaque ( def_id, _) => Some ( OpaqueSimplifiedType ( def_id) ) ,
119136 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 ,
121138 }
122139}
123140
@@ -161,41 +178,7 @@ impl<D: Copy + Debug + Eq> SimplifiedTypeGen<D> {
161178 GeneratorWitnessSimplifiedType ( n) => GeneratorWitnessSimplifiedType ( n) ,
162179 OpaqueSimplifiedType ( d) => OpaqueSimplifiedType ( map ( d) ) ,
163180 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 ,
199182 }
200183 }
201184}
0 commit comments