1+ use crate :: mir:: Mutability ;
12use crate :: ty:: { self , Ty , TyCtxt } ;
23use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
34use rustc_hir:: def_id:: DefId ;
2728 UintSimplifiedType ( ty:: UintTy ) ,
2829 FloatSimplifiedType ( ty:: FloatTy ) ,
2930 AdtSimplifiedType ( D ) ,
31+ ForeignSimplifiedType ( D ) ,
3032 StrSimplifiedType ,
3133 ArraySimplifiedType ,
32- PtrSimplifiedType ,
34+ SliceSimplifiedType ,
35+ RefSimplifiedType ( Mutability ) ,
36+ PtrSimplifiedType ( Mutability ) ,
3337 NeverSimplifiedType ,
3438 TupleSimplifiedType ( usize ) ,
3539 /// A trait object, all of whose components are markers
@@ -42,22 +46,48 @@ where
4246 OpaqueSimplifiedType ( D ) ,
4347 FunctionSimplifiedType ( usize ) ,
4448 ParameterSimplifiedType ,
45- ForeignSimplifiedType ( DefId ) ,
4649}
4750
48- /// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc.
49- /// The idea is to get something simple that we can use to quickly decide if two types could unify
50- /// during method lookup.
51+ #[ derive( PartialEq , Eq , Debug , Clone , Copy ) ]
52+ pub enum SimplifyParams {
53+ Yes ,
54+ No ,
55+ }
56+
57+ #[ derive( PartialEq , Eq , Debug , Clone , Copy ) ]
58+ pub enum StripReferences {
59+ Yes ,
60+ No ,
61+ }
62+
63+ /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists.
64+ ///
65+ /// The idea is to get something simple that we can use to quickly decide if two types could unify,
66+ /// for example during method lookup.
5167///
52- /// If `can_simplify_params` is false, then we will fail to simplify type parameters entirely. This
53- /// is useful when those type parameters would be instantiated with fresh type variables, since
54- /// then we can't say much about whether two types would unify. Put another way,
55- /// `can_simplify_params` should be true if type parameters appear free in `ty` and `false` if they
56- /// are to be considered bound.
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.
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.
75+ ///
76+ /// For diagnostics we strip references with `StripReferences::Yes`. This is currently the best
77+ /// 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.
5786pub fn simplify_type (
5887 tcx : TyCtxt < ' _ > ,
5988 ty : Ty < ' _ > ,
60- can_simplify_params : bool ,
89+ can_simplify_params : SimplifyParams ,
90+ strip_references : StripReferences ,
6191) -> Option < SimplifiedType > {
6292 match * ty. kind ( ) {
6393 ty:: Bool => Some ( BoolSimplifiedType ) ,
@@ -67,19 +97,24 @@ pub fn simplify_type(
6797 ty:: Float ( float_type) => Some ( FloatSimplifiedType ( float_type) ) ,
6898 ty:: Adt ( def, _) => Some ( AdtSimplifiedType ( def. did ) ) ,
6999 ty:: Str => Some ( StrSimplifiedType ) ,
70- ty:: Array ( ..) | ty:: Slice ( _) => Some ( ArraySimplifiedType ) ,
71- ty:: RawPtr ( _) => Some ( PtrSimplifiedType ) ,
100+ ty:: Array ( ..) => Some ( ArraySimplifiedType ) ,
101+ ty:: Slice ( ..) => Some ( SliceSimplifiedType ) ,
102+ ty:: RawPtr ( ptr) => Some ( PtrSimplifiedType ( ptr. mutbl ) ) ,
72103 ty:: Dynamic ( ref trait_info, ..) => match trait_info. principal_def_id ( ) {
73104 Some ( principal_def_id) if !tcx. trait_is_auto ( principal_def_id) => {
74105 Some ( TraitSimplifiedType ( principal_def_id) )
75106 }
76107 _ => Some ( MarkerTraitObjectSimplifiedType ) ,
77108 } ,
78- ty:: Ref ( _, ty, _) => {
79- // since we introduce auto-refs during method lookup, we
80- // just treat &T and T as equivalent from the point of
81- // view of possibly unifying
82- simplify_type ( tcx, ty, can_simplify_params)
109+ ty:: Ref ( _, ty, mutbl) => {
110+ if strip_references == StripReferences :: Yes {
111+ // For diagnostics, when recommending similar impls we want to
112+ // recommend impls even when there is a reference mismatch,
113+ // so we treat &T and T equivalently in that case.
114+ simplify_type ( tcx, ty, can_simplify_params, strip_references)
115+ } else {
116+ Some ( RefSimplifiedType ( mutbl) )
117+ }
83118 }
84119 ty:: FnDef ( def_id, _) | ty:: Closure ( def_id, _) => Some ( ClosureSimplifiedType ( def_id) ) ,
85120 ty:: Generator ( def_id, _, _) => Some ( GeneratorSimplifiedType ( def_id) ) ,
@@ -90,7 +125,7 @@ pub fn simplify_type(
90125 ty:: Tuple ( ref tys) => Some ( TupleSimplifiedType ( tys. len ( ) ) ) ,
91126 ty:: FnPtr ( ref f) => Some ( FunctionSimplifiedType ( f. skip_binder ( ) . inputs ( ) . len ( ) ) ) ,
92127 ty:: Projection ( _) | ty:: Param ( _) => {
93- if can_simplify_params {
128+ if can_simplify_params == SimplifyParams :: Yes {
94129 // In normalized types, projections don't unify with
95130 // anything. when lazy normalization happens, this
96131 // will change. It would still be nice to have a way
@@ -120,9 +155,12 @@ impl<D: Copy + Debug + Ord + Eq> SimplifiedTypeGen<D> {
120155 UintSimplifiedType ( t) => UintSimplifiedType ( t) ,
121156 FloatSimplifiedType ( t) => FloatSimplifiedType ( t) ,
122157 AdtSimplifiedType ( d) => AdtSimplifiedType ( map ( d) ) ,
158+ ForeignSimplifiedType ( d) => ForeignSimplifiedType ( map ( d) ) ,
123159 StrSimplifiedType => StrSimplifiedType ,
124160 ArraySimplifiedType => ArraySimplifiedType ,
125- PtrSimplifiedType => PtrSimplifiedType ,
161+ SliceSimplifiedType => SliceSimplifiedType ,
162+ RefSimplifiedType ( m) => RefSimplifiedType ( m) ,
163+ PtrSimplifiedType ( m) => PtrSimplifiedType ( m) ,
126164 NeverSimplifiedType => NeverSimplifiedType ,
127165 MarkerTraitObjectSimplifiedType => MarkerTraitObjectSimplifiedType ,
128166 TupleSimplifiedType ( n) => TupleSimplifiedType ( n) ,
@@ -133,7 +171,6 @@ impl<D: Copy + Debug + Ord + Eq> SimplifiedTypeGen<D> {
133171 OpaqueSimplifiedType ( d) => OpaqueSimplifiedType ( map ( d) ) ,
134172 FunctionSimplifiedType ( n) => FunctionSimplifiedType ( n) ,
135173 ParameterSimplifiedType => ParameterSimplifiedType ,
136- ForeignSimplifiedType ( d) => ForeignSimplifiedType ( d) ,
137174 }
138175 }
139176}
@@ -149,12 +186,13 @@ where
149186 | CharSimplifiedType
150187 | StrSimplifiedType
151188 | ArraySimplifiedType
152- | PtrSimplifiedType
189+ | SliceSimplifiedType
153190 | NeverSimplifiedType
154191 | ParameterSimplifiedType
155192 | MarkerTraitObjectSimplifiedType => {
156193 // nothing to do
157194 }
195+ RefSimplifiedType ( m) | PtrSimplifiedType ( m) => m. hash_stable ( hcx, hasher) ,
158196 IntSimplifiedType ( t) => t. hash_stable ( hcx, hasher) ,
159197 UintSimplifiedType ( t) => t. hash_stable ( hcx, hasher) ,
160198 FloatSimplifiedType ( t) => t. hash_stable ( hcx, hasher) ,
0 commit comments