@@ -60,29 +60,23 @@ pub enum StripReferences {
60
60
No ,
61
61
}
62
62
63
- /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
63
+ /// Tries to simplify a type by only returning the outermost layer of an inductive type , if one exists.
64
64
///
65
65
/// The idea is to get something simple that we can use to quickly decide if two types could unify,
66
66
/// for example during method lookup.
67
67
///
68
- /// A special case here are parameters and projections. Projections can be normalized to
69
- /// a different type, meaning that `<T as Trait>::Assoc` and `u8` can be unified, even though
70
- /// their outermost layer is different while parameters like `T` of impls are later replaced
71
- /// with an inference variable, which then also allows unification with other types.
68
+ /// We have to be careful with parameters and projections as we might want them to unify with other types.
69
+ /// Projections can be normalized to a different type, meaning that `<T as Trait>::Assoc`
70
+ /// and `u8` can be unified, even though their outermost layer is different while parameters like `T` of
71
+ /// impls are later replaced with an inference variable, which then also allows unification with other types.
72
72
///
73
- /// When using `SimplifyParams::Yes`, we still return a simplified type for params and projections²,
74
- /// the reasoning for this can be seen at the places doing this.
73
+ /// When using `SimplifyParams::Yes`, we still return a simplified type for params.
74
+ /// This is used during candidate selection when looking for impls satisfying `T: Trait`
75
+ /// but must not be used on candidates, as the `T` in `impl<T> Trait for T` can unify
76
+ /// with any other type.
75
77
///
76
78
/// For diagnostics we strip references with `StripReferences::Yes`. This is currently the best
77
79
/// way to skip some unhelpful suggestions.
78
- ///
79
- /// ¹ meaning that if two outermost layers are different, then the whole types are also different.
80
- /// ² FIXME(@lcnr): this seems like it can actually end up being unsound with the way it's used during
81
- /// candidate selection. We do not consider non blanket impls for `<_ as Trait>::Assoc` even
82
- /// though `_` can be inferred to a concrete type later at which point a concrete impl
83
- /// could actually apply. After experimenting for about an hour I wasn't able to cause any issues
84
- /// this way so I am not going to change this until we actually find an issue as I am really
85
- /// interesting in getting an actual test for this.
86
80
pub fn simplify_type (
87
81
tcx : TyCtxt < ' _ > ,
88
82
ty : Ty < ' _ > ,
@@ -124,18 +118,23 @@ pub fn simplify_type(
124
118
ty:: Never => Some ( NeverSimplifiedType ) ,
125
119
ty:: Tuple ( ref tys) => Some ( TupleSimplifiedType ( tys. len ( ) ) ) ,
126
120
ty:: FnPtr ( ref f) => Some ( FunctionSimplifiedType ( f. skip_binder ( ) . inputs ( ) . len ( ) ) ) ,
127
- ty:: Projection ( _ ) | ty :: Param ( _) => {
121
+ ty:: Param ( _) => {
128
122
if can_simplify_params == SimplifyParams :: Yes {
129
- // In normalized types, projections don't unify with
130
- // anything. when lazy normalization happens, this
131
- // will change. It would still be nice to have a way
132
- // to deal with known-not-to-unify-with-anything
133
- // projections (e.g., the likes of <__S as Encoder>::Error).
134
123
Some ( ParameterSimplifiedType )
135
124
} else {
136
125
None
137
126
}
138
127
}
128
+ ty:: Projection ( _) => {
129
+ // Returning a simplified for projections can end up being unsound as it would
130
+ // stop us from considering not consider non blanket impls for `<_ as Trait>::Assoc` even
131
+ // though `_` can be inferred to a concrete type later at which point a concrete impl
132
+ // could actually apply.
133
+ //
134
+ // We could return `Some` here in cases where the input type is fully normalized, but
135
+ // I (@lcnr) don't know how to guarantee that.
136
+ None
137
+ }
139
138
ty:: Opaque ( def_id, _) => Some ( OpaqueSimplifiedType ( def_id) ) ,
140
139
ty:: Foreign ( def_id) => Some ( ForeignSimplifiedType ( def_id) ) ,
141
140
ty:: Placeholder ( ..) | ty:: Bound ( ..) | ty:: Infer ( _) | ty:: Error ( _) => None ,
0 commit comments