@@ -93,10 +93,46 @@ fn implicit_dereference() {
93
93
let _y = x. is_positive ( ) ; // $ MISSING: target=is_positive type=_y:bool
94
94
}
95
95
96
+ mod implicit_deref_coercion_cycle {
97
+ use std:: collections:: HashMap ;
98
+
99
+ #[ derive( Hash , PartialEq , Eq , PartialOrd , Ord , Debug , Clone , Copy ) ]
100
+ pub struct Key { }
101
+
102
+ // This example can trigger a cycle in type inference due to an implicit
103
+ // dereference if we are not careful and accurate enough.
104
+ //
105
+ // To explain how a cycle might happen, we let `[V]` denote the type of the
106
+ // type parameter `V` of `key_to_key` (i.e., the type of the values in the
107
+ // map) and `[key]` denote the type of `key`.
108
+ //
109
+ // 1. From the first two lines we infer `[V] = &Key` and `[key] = &Key`
110
+ // 2. At the 3. line we infer the type of `ref_key` to be `&[V]`.
111
+ // 3. At the 4. line we impose the equality `[key] = &[V]`, not accounting
112
+ // for the implicit deref caused by a coercion.
113
+ // 4. At the last line we infer `[key] = [V]`.
114
+ //
115
+ // Putting the above together we have `[V] = [key] = &[V]` which is a cycle.
116
+ // This means that `[key]` is both `&Key`, `&&Key`, `&&&Key`, and so on ad
117
+ // infinitum.
118
+
119
+ #[ rustfmt:: skip]
120
+ pub fn test ( ) {
121
+ let mut key_to_key = HashMap :: < & Key , & Key > :: new ( ) ; // $ target=new
122
+ let mut key = & Key { } ; // Initialize key2 to a reference
123
+ if let Some ( ref_key) = key_to_key. get ( key) { // $ target=get
124
+ // Below `ref_key` is implicitly dereferenced from `&&Key` to `&Key`
125
+ key = ref_key;
126
+ }
127
+ key_to_key. insert ( key, key) ; // $ target=insert
128
+ }
129
+ }
130
+
96
131
pub fn test ( ) {
97
132
explicit_monomorphic_dereference ( ) ; // $ target=explicit_monomorphic_dereference
98
133
explicit_polymorphic_dereference ( ) ; // $ target=explicit_polymorphic_dereference
99
134
explicit_ref_dereference ( ) ; // $ target=explicit_ref_dereference
100
135
explicit_box_dereference ( ) ; // $ target=explicit_box_dereference
101
136
implicit_dereference ( ) ; // $ target=implicit_dereference
137
+ implicit_deref_coercion_cycle:: test ( ) ; // $ target=test
102
138
}
0 commit comments