@@ -2079,24 +2079,47 @@ let to_pos : type ph. ph t_ -> Pos_or_decl.t =
2079
2079
(* Translate a reason to a (pos, string) list, suitable for error_l. This
2080
2080
* previously returned a string, however the need to return multiple lines with
2081
2081
* multiple locations meant that it needed to more than convert to a string *)
2082
- let rec to_string : type a. string -> a t_ -> (Pos_or_decl.t * string) list =
2083
- fun prefix r ->
2082
+ let rec to_string_help :
2083
+ type a .
2084
+ string -> locl_phase t_ Tvid.Map. t -> a t_ -> (Pos_or_decl. t * string ) list
2085
+ =
2086
+ fun prefix solutions r ->
2084
2087
let p = to_pos r in
2085
2088
match r with
2086
2089
| No_reason -> [(p, prefix)]
2087
2090
| Missing_field -> [(p, prefix)]
2088
2091
| Invalid -> [(p, prefix)]
2092
+ | From_witness_locl
2093
+ (Type_variable_generics (_, _, _, tvid) | Type_variable (_, tvid))
2094
+ when Tvid.Map. mem tvid solutions ->
2095
+ let r = Tvid.Map. find tvid solutions in
2096
+ let solutions = Tvid.Map. remove tvid solutions in
2097
+ to_string_help prefix solutions r
2089
2098
| From_witness_locl witness -> [witness_locl_to_string prefix witness]
2090
2099
| From_witness_decl witness -> [witness_decl_to_string prefix witness]
2091
- | Flow { from = r; _ }
2092
2100
| Upper_bound { bound = r; _ }
2093
2101
| Lower_bound { bound = r; _ }
2094
2102
| Axiom { next = r; _ }
2095
2103
| Def (_, r)
2096
2104
| Prj_both { sub_prj = r; _ }
2097
- | Prj_one { part = r; _ }
2098
- | Solved { solution = r ; _ } ->
2099
- to_string prefix r
2105
+ | Prj_one { part = r ; _ } ->
2106
+ to_string_help prefix solutions r
2107
+ (* If we don't have a solution for a type variable use the origin of the flow *)
2108
+ | Flow { from = r ; _ } when Tvid.Map. is_empty solutions ->
2109
+ to_string_help prefix solutions r
2110
+ (* otherwise, follow the flow until we reach the type variable *)
2111
+ | Flow { from; into; _ } ->
2112
+ (match from with
2113
+ | From_witness_locl
2114
+ (Type_variable_generics (_, _, _, tvid) | Type_variable (_, tvid))
2115
+ when Tvid.Map. mem tvid solutions ->
2116
+ let r = Tvid.Map. find tvid solutions in
2117
+ let solutions = Tvid.Map. remove tvid solutions in
2118
+ to_string_help prefix solutions r
2119
+ | _ -> to_string_help prefix solutions into)
2120
+ | Solved { solution; of_; in_ = r } ->
2121
+ let solutions = Tvid.Map. add of_ solution solutions in
2122
+ to_string_help prefix solutions r
2100
2123
| Idx (_ , r2 ) ->
2101
2124
[(p, prefix)]
2102
2125
@ [
@@ -2121,8 +2144,9 @@ let rec to_string : type a. string -> a t_ -> (Pos_or_decl.t * string) list =
2121
2144
^ arg_pos_str s
2122
2145
^ " argument." );
2123
2146
]
2124
- @ to_string
2147
+ @ to_string_help
2125
2148
" Here is why I think the argument is a `float`: this is a `float`"
2149
+ solutions
2126
2150
r_last
2127
2151
| Arith_ret_num (_ , r , s ) ->
2128
2152
let rec find_last reason =
@@ -2140,8 +2164,9 @@ let rec to_string : type a. string -> a t_ -> (Pos_or_decl.t * string) list =
2140
2164
^ arg_pos_str s
2141
2165
^ " argument, and no `float`s." );
2142
2166
]
2143
- @ to_string
2167
+ @ to_string_help
2144
2168
" Here is why I think the argument is a `num`: this is a `num`"
2169
+ solutions
2145
2170
r_last
2146
2171
| Lost_info (s , r1 , Blame (p2 , source_of_loss )) ->
2147
2172
let s = strip_ns s in
@@ -2152,7 +2177,7 @@ let rec to_string : type a. string -> a t_ -> (Pos_or_decl.t * string) list =
2152
2177
| BSassignment -> " by this assignment"
2153
2178
| BSout_of_scope -> " because of scope change"
2154
2179
in
2155
- to_string prefix r1
2180
+ to_string_help prefix solutions r1
2156
2181
@ [
2157
2182
( p2 |> Pos_or_decl. of_raw_pos,
2158
2183
" All the local information about "
@@ -2169,13 +2194,14 @@ let rec to_string : type a. string -> a t_ -> (Pos_or_decl.t * string) list =
2169
2194
^ Markdown_lite. md_codify s
2170
2195
^ " format specifier"
2171
2196
in
2172
- (match to_string " " t with
2197
+ (match to_string_help " " solutions t with
2173
2198
| [(_, " " )] -> [(p, s)]
2174
2199
| el -> [(p, s)] @ el)
2175
2200
| Instantiate (r_orig , generic_name , r_inst ) ->
2176
- to_string prefix r_orig
2177
- @ to_string
2201
+ to_string_help prefix solutions r_orig
2202
+ @ to_string_help
2178
2203
(" via this generic " ^ Markdown_lite. md_codify generic_name)
2204
+ solutions
2179
2205
r_inst
2180
2206
| Typeconst (No_reason, (pos , tconst ), (lazy ty_str ), r_root ) ->
2181
2207
let prefix =
@@ -2191,42 +2217,45 @@ let rec to_string : type a. string -> a t_ -> (Pos_or_decl.t * string) list =
2191
2217
prefix
2192
2218
(Markdown_lite. md_codify tconst) );
2193
2219
]
2194
- @ to_string (" on " ^ ty_str) r_root
2220
+ @ to_string_help (" on " ^ ty_str) solutions r_root
2195
2221
| Typeconst (r_orig , (pos , tconst ), (lazy ty_str ), r_root ) ->
2196
- to_string prefix r_orig
2222
+ to_string_help prefix solutions r_orig
2197
2223
@ [
2198
2224
(pos, sprintf " resulting from accessing the type constant '%s'" tconst);
2199
2225
]
2200
- @ to_string (" on " ^ ty_str) r_root
2226
+ @ to_string_help (" on " ^ ty_str) solutions r_root
2201
2227
| Type_access (Typeconst (No_reason, _ , _ , _ ), (r , _ ) :: l ) ->
2202
- to_string prefix (Type_access (r, l))
2228
+ to_string_help prefix solutions (Type_access (r, l))
2203
2229
| Type_access (Typeconst (r , _ , _ , _ ), x ) ->
2204
- to_string prefix (Type_access (r, x))
2230
+ to_string_help prefix solutions (Type_access (r, x))
2205
2231
| Type_access (Type_access (r , expand2 ), expand1 ) ->
2206
- to_string prefix (Type_access (r, expand1 @ expand2))
2207
- | Type_access (r , [] ) -> to_string prefix r
2232
+ to_string_help prefix solutions (Type_access (r, expand1 @ expand2))
2233
+ | Type_access (r , [] ) -> to_string_help prefix solutions r
2208
2234
| Type_access (r , (r_hd , (lazy tconst )) :: tail ) ->
2209
- to_string prefix r
2210
- @ to_string
2235
+ to_string_help prefix solutions r
2236
+ @ to_string_help
2211
2237
(" resulting from expanding the type constant "
2212
2238
^ Markdown_lite. md_codify tconst)
2239
+ solutions
2213
2240
r_hd
2214
2241
@ List. concat_map tail ~f: (fun (r , (lazy s )) ->
2215
- to_string
2242
+ to_string_help
2216
2243
(" then expanding the type constant " ^ Markdown_lite. md_codify s)
2244
+ solutions
2217
2245
r)
2218
2246
| Expr_dep_type (r , p , e ) ->
2219
- to_string prefix r @ [(p, " " ^ expr_dep_type_reason_string e)]
2247
+ to_string_help prefix solutions r
2248
+ @ [(p, " " ^ expr_dep_type_reason_string e)]
2220
2249
| Contravariant_generic (r_orig , class_name ) ->
2221
- to_string prefix r_orig
2250
+ to_string_help prefix solutions r_orig
2222
2251
@ [
2223
2252
( p,
2224
2253
" This type argument to "
2225
2254
^ (strip_ns class_name |> Markdown_lite. md_codify)
2226
2255
^ " only allows supertypes (it is contravariant)" );
2227
2256
]
2228
2257
| Invariant_generic (r_orig , class_name ) ->
2229
- to_string prefix r_orig
2258
+ to_string_help prefix solutions r_orig
2230
2259
@ [
2231
2260
( p,
2232
2261
" This type argument to "
@@ -2235,35 +2264,44 @@ let rec to_string : type a. string -> a t_ -> (Pos_or_decl.t * string) list =
2235
2264
]
2236
2265
(* If type originated with an unannotated lambda parameter with type variable type,
2237
2266
* suggested annotating the lambda parameter. Otherwise defer to original reason. *)
2267
+ | Lambda_param
2268
+ ( _,
2269
+ From_witness_locl
2270
+ (Type_variable_generics (_, _, _, tvid) | Type_variable (_, tvid)) )
2271
+ when Tvid.Map. mem tvid solutions ->
2272
+ let r = Tvid.Map. find tvid solutions in
2273
+ let solutions = Tvid.Map. remove tvid solutions in
2274
+ to_string_help prefix solutions r
2238
2275
| Lambda_param
2239
2276
( _,
2240
2277
( From_witness_decl (Solve_fail _)
2241
- | From_witness_locl (Type_variable_generics _ | Type_variable _)
2242
- | Instantiate _ ) ) ->
2278
+ | From_witness_locl (Type_variable_generics _ | Type_variable _ ) ) ) ->
2243
2279
[
2244
2280
( p,
2245
2281
prefix
2246
2282
^ " because the type of the lambda parameter could not be determined. "
2247
2283
^ " Please add a type hint to the parameter" );
2248
2284
]
2249
- | Lambda_param (_ , r_orig ) -> to_string prefix r_orig
2250
- | Dynamic_coercion r -> to_string prefix r
2285
+ | Lambda_param (_ , r_orig ) -> to_string_help prefix solutions r_orig
2286
+ | Dynamic_coercion r -> to_string_help prefix solutions r
2251
2287
| Dynamic_partial_enforcement (p , cn , r_orig ) ->
2252
- to_string prefix r_orig
2288
+ to_string_help prefix solutions r_orig
2253
2289
@ [(p, " while allowing dynamic to flow into " ^ Utils. strip_all_ns cn)]
2254
2290
| Rigid_tvar_escape (p , what , tvar , r_orig ) ->
2255
2291
let tvar = Markdown_lite. md_codify tvar in
2256
2292
( Pos_or_decl. of_raw_pos p,
2257
2293
prefix ^ " because " ^ tvar ^ " escaped from " ^ what )
2258
- :: to_string (" where " ^ tvar ^ " originates from" ) r_orig
2294
+ :: to_string_help (" where " ^ tvar ^ " originates from" ) solutions r_orig
2259
2295
| Opaque_type_from_module (p , module_ , r_orig ) ->
2260
2296
( p,
2261
2297
prefix
2262
2298
^ " because this is an internal symbol from module "
2263
2299
^ module_
2264
2300
^ " , which is opaque outside of the module." )
2265
- :: to_string " The type originated from here" r_orig
2301
+ :: to_string_help " The type originated from here" solutions r_orig
2266
2302
2303
+ let to_string : type a. string -> a t_ -> (Pos_or_decl.t * string) list =
2304
+ (fun prefix r -> to_string_help prefix Tvid.Map. empty r)
2267
2305
(* -- Constructors ---------------------------------------------------------- *)
2268
2306
2269
2307
module Constructors = struct
0 commit comments