@@ -49,36 +49,36 @@ where
49
49
}
50
50
51
51
#[ derive( PartialEq , Eq , Debug , Clone , Copy ) ]
52
- pub enum SimplifyParams {
53
- Yes ,
54
- No ,
52
+ pub enum TreatParams {
53
+ /// Treat parameters as bound types in the given environment.
54
+ ///
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 ,
55
60
}
56
61
57
62
/// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
58
63
///
59
64
/// The idea is to get something simple that we can use to quickly decide if two types could unify,
60
65
/// for example during method lookup.
61
66
///
62
- /// A special case here are parameters and projections. Projections can be normalized to
63
- /// a different type, meaning that `<T as Trait>::Assoc` and `u8` can be unified, even though
64
- /// their outermost layer is different while parameters like `T` of impls are later replaced
65
- /// with an inference variable, which then also allows unification with other types.
67
+ /// A special case here are parameters and projections, which are only injective
68
+ /// if they are treated as bound types.
66
69
///
67
- /// When using `SimplifyParams::Yes`, we still return a simplified type for params and projections²,
68
- /// the reasoning for this can be seen at the places doing this.
70
+ /// For example when storing impls based on their simplified self type, we treat
71
+ /// generic parameters as placeholders. We must not simplify them here,
72
+ /// as they can unify with any other type.
69
73
///
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.
70
76
///
71
- /// ¹ meaning that if two outermost layers are different, then the whole types are also different.
72
- /// ² FIXME(@lcnr): this seems like it can actually end up being unsound with the way it's used during
73
- /// candidate selection. We do not consider non blanket impls for `<_ as Trait>::Assoc` even
74
- /// though `_` can be inferred to a concrete type later at which point a concrete impl
75
- /// could actually apply. After experimenting for about an hour I wasn't able to cause any issues
76
- /// this way so I am not going to change this until we actually find an issue as I am really
77
- /// interesting in getting an actual test for this.
78
- pub fn simplify_type (
79
- tcx : TyCtxt < ' _ > ,
80
- ty : Ty < ' _ > ,
81
- can_simplify_params : SimplifyParams ,
77
+ /// ¹ meaning that if the outermost layers are different, then the whole types are also different.
78
+ pub fn simplify_type < ' tcx > (
79
+ tcx : TyCtxt < ' tcx > ,
80
+ ty : Ty < ' tcx > ,
81
+ treat_params : TreatParams ,
82
82
) -> Option < SimplifiedType > {
83
83
match * ty. kind ( ) {
84
84
ty:: Bool => Some ( BoolSimplifiedType ) ,
@@ -91,7 +91,7 @@ pub fn simplify_type(
91
91
ty:: Array ( ..) => Some ( ArraySimplifiedType ) ,
92
92
ty:: Slice ( ..) => Some ( SliceSimplifiedType ) ,
93
93
ty:: RawPtr ( ptr) => Some ( PtrSimplifiedType ( ptr. mutbl ) ) ,
94
- ty:: Dynamic ( ref trait_info, ..) => match trait_info. principal_def_id ( ) {
94
+ ty:: Dynamic ( trait_info, ..) => match trait_info. principal_def_id ( ) {
95
95
Some ( principal_def_id) if !tcx. trait_is_auto ( principal_def_id) => {
96
96
Some ( TraitSimplifiedType ( principal_def_id) )
97
97
}
@@ -100,24 +100,21 @@ pub fn simplify_type(
100
100
ty:: Ref ( _, _, mutbl) => Some ( RefSimplifiedType ( mutbl) ) ,
101
101
ty:: FnDef ( def_id, _) | ty:: Closure ( def_id, _) => Some ( ClosureSimplifiedType ( def_id) ) ,
102
102
ty:: Generator ( def_id, _, _) => Some ( GeneratorSimplifiedType ( def_id) ) ,
103
- ty:: GeneratorWitness ( ref tys) => {
104
- Some ( GeneratorWitnessSimplifiedType ( tys. skip_binder ( ) . len ( ) ) )
105
- }
103
+ ty:: GeneratorWitness ( tys) => Some ( GeneratorWitnessSimplifiedType ( tys. skip_binder ( ) . len ( ) ) ) ,
106
104
ty:: Never => Some ( NeverSimplifiedType ) ,
107
- ty:: Tuple ( ref tys) => Some ( TupleSimplifiedType ( tys. len ( ) ) ) ,
108
- ty:: FnPtr ( ref f) => Some ( FunctionSimplifiedType ( f. skip_binder ( ) . inputs ( ) . len ( ) ) ) ,
109
- ty:: Projection ( _) | ty:: Param ( _) => {
110
- if can_simplify_params == SimplifyParams :: Yes {
111
- // In normalized types, projections don't unify with
112
- // anything. when lazy normalization happens, this
113
- // will change. It would still be nice to have a way
114
- // to deal with known-not-to-unify-with-anything
115
- // projections (e.g., the likes of <__S as Encoder>::Error).
105
+ ty:: Tuple ( tys) => Some ( TupleSimplifiedType ( tys. len ( ) ) ) ,
106
+ 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.
110
+ //
111
+ // We will have to be careful with lazy normalization here.
112
+ TreatParams :: AsBoundTypes => {
113
+ debug ! ( "treating `{}` as a bound type" , ty ) ;
116
114
Some ( ParameterSimplifiedType )
117
- } else {
118
- None
119
115
}
120
- }
116
+ TreatParams :: AsPlaceholders => None ,
117
+ } ,
121
118
ty:: Opaque ( def_id, _) => Some ( OpaqueSimplifiedType ( def_id) ) ,
122
119
ty:: Foreign ( def_id) => Some ( ForeignSimplifiedType ( def_id) ) ,
123
120
ty:: Placeholder ( ..) | ty:: Bound ( ..) | ty:: Infer ( _) | ty:: Error ( _) => None ,
0 commit comments