error.ml 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. open Globals
  2. open TType
  3. open TUnification
  4. open TFunctions
  5. open TPrinting
  6. open TOther
  7. type call_error =
  8. | Not_enough_arguments of (string * bool * t) list
  9. | Too_many_arguments
  10. | Could_not_unify of error_msg
  11. | Cannot_skip_non_nullable of string
  12. and error_msg =
  13. | Module_not_found of path
  14. | Type_not_found of path * string * type_not_found_reason
  15. | Unify of unify_error list
  16. | Custom of string
  17. | Unknown_ident of string
  18. | Stack of error_msg * error_msg
  19. | Call_error of call_error
  20. | No_constructor of module_type
  21. and type_not_found_reason =
  22. | Private_type
  23. | Not_defined
  24. exception Fatal_error of string * Globals.pos
  25. exception Error of error_msg * Globals.pos
  26. let string_source t = match follow t with
  27. | TInst(c,tl) -> PMap.foldi (fun s _ acc -> s :: acc) (TClass.get_all_fields c tl) []
  28. | TAnon a -> PMap.fold (fun cf acc -> cf.cf_name :: acc) a.a_fields []
  29. | TAbstract({a_impl = Some c},_) -> List.map (fun cf -> cf.cf_name) c.cl_ordered_statics
  30. | _ -> []
  31. let short_type ctx t =
  32. let tstr = s_type ctx t in
  33. if String.length tstr > 150 then String.sub tstr 0 147 ^ "..." else tstr
  34. (**
  35. Should be called for each complementary error message.
  36. *)
  37. let compl_msg s = "... " ^ s
  38. let unify_error_msg ctx err = match err with
  39. | Cannot_unify (t1,t2) ->
  40. s_type ctx t1 ^ " should be " ^ s_type ctx t2
  41. | Invalid_field_type s ->
  42. "Invalid type for field " ^ s ^ " :"
  43. | Has_no_field (t,n) ->
  44. StringError.string_error n (string_source t) (short_type ctx t ^ " has no field " ^ n)
  45. | Has_no_runtime_field (t,n) ->
  46. s_type ctx t ^ "." ^ n ^ " is not accessible at runtime"
  47. | Has_extra_field (t,n) ->
  48. short_type ctx t ^ " has extra field " ^ n
  49. | Invalid_kind (f,a,b) ->
  50. (match a, b with
  51. | Var va, Var vb ->
  52. let name, stra, strb = if va.v_read = vb.v_read then
  53. "setter", s_access false va.v_write, s_access false vb.v_write
  54. else if va.v_write = vb.v_write then
  55. "getter", s_access true va.v_read, s_access true vb.v_read
  56. else
  57. "access", "(" ^ s_access true va.v_read ^ "," ^ s_access false va.v_write ^ ")", "(" ^ s_access true vb.v_read ^ "," ^ s_access false vb.v_write ^ ")"
  58. in
  59. "Inconsistent " ^ name ^ " for field " ^ f ^ " : " ^ stra ^ " should be " ^ strb
  60. | _ ->
  61. "Field " ^ f ^ " is " ^ s_kind a ^ " but should be " ^ s_kind b)
  62. | Invalid_visibility n ->
  63. "The field " ^ n ^ " is not public"
  64. | Not_matching_optional n ->
  65. "Optional attribute of parameter " ^ n ^ " differs"
  66. | Cant_force_optional ->
  67. "Optional parameters can't be forced"
  68. | Invariant_parameter _ ->
  69. "Type parameters are invariant"
  70. | Constraint_failure name ->
  71. "Constraint check failure for " ^ name
  72. | Missing_overload (cf, t) ->
  73. cf.cf_name ^ " has no overload for " ^ s_type ctx t
  74. | FinalInvariance ->
  75. "Cannot unify final and non-final fields"
  76. | Invalid_function_argument(i,_) ->
  77. Printf.sprintf "Cannot unify argument %i" i
  78. | Invalid_return_type ->
  79. "Cannot unify return types"
  80. | Unify_custom msg ->
  81. msg
  82. module BetterErrors = struct
  83. type access_kind =
  84. | Field of string
  85. | FunctionArgument of int * int
  86. | FunctionReturn
  87. | TypeParameter of int
  88. | Root
  89. type access = {
  90. acc_kind : access_kind;
  91. mutable acc_expected : TType.t;
  92. mutable acc_actual : TType.t;
  93. mutable acc_messages : unify_error list;
  94. mutable acc_next : access option;
  95. }
  96. let s_access_kind = function
  97. | Field s -> "Field " ^ s
  98. | FunctionArgument(i,l) -> Printf.sprintf "FunctionArgument(%i, %i)" i l
  99. | FunctionReturn -> "FunctionReturn"
  100. | TypeParameter i -> Printf.sprintf "TypeParameter %i" i
  101. | Root -> "Root"
  102. let get_access_chain ctx l =
  103. let make_acc kind actual expected = {
  104. acc_kind = kind;
  105. acc_expected = expected;
  106. acc_actual = actual;
  107. acc_messages = [];
  108. acc_next = None;
  109. } in
  110. let root_acc = make_acc Root t_dynamic t_dynamic in
  111. let current_acc = ref root_acc in
  112. let add_message msg =
  113. !current_acc.acc_messages <- msg :: !current_acc.acc_messages
  114. in
  115. let add_access kind =
  116. let acc = make_acc kind t_dynamic t_dynamic in
  117. !current_acc.acc_next <- Some acc;
  118. current_acc := acc;
  119. in
  120. List.iter (fun err -> match err with
  121. | Cannot_unify(t1,t2) ->
  122. !current_acc.acc_actual <- t1;
  123. !current_acc.acc_expected <- t2;
  124. add_message err
  125. | Invalid_field_type s ->
  126. add_access (Field s);
  127. | Invalid_function_argument(i,l) ->
  128. add_access (FunctionArgument(i,l));
  129. | Invalid_return_type ->
  130. add_access FunctionReturn;
  131. | Invariant_parameter i ->
  132. add_access (TypeParameter i);
  133. | _ ->
  134. add_message err
  135. ) l;
  136. root_acc
  137. (* non-recursive s_type *)
  138. let rec s_type ctx t =
  139. match t with
  140. | TMono r ->
  141. (match r.tm_type with
  142. | None -> Printf.sprintf "Unknown<%d>" (try List.assq t (!ctx) with Not_found -> let n = List.length !ctx in ctx := (t,n) :: !ctx; n)
  143. | Some t -> s_type ctx t)
  144. | TEnum (e,tl) ->
  145. s_type_path e.e_path ^ s_type_params ctx tl
  146. | TInst (c,tl) ->
  147. (match c.cl_kind with
  148. | KExpr e -> Ast.Printer.s_expr e
  149. | _ -> s_type_path c.cl_path ^ s_type_params ctx tl)
  150. | TType (t,tl) ->
  151. s_type_path t.t_path ^ s_type_params ctx tl
  152. | TAbstract (a,tl) ->
  153. s_type_path a.a_path ^ s_type_params ctx tl
  154. | TFun ([],_) ->
  155. "() -> ..."
  156. | TFun (l,t) ->
  157. let args = match l with
  158. | [] -> "()"
  159. | ["",b,t] -> ("...")
  160. | _ ->
  161. let args = String.concat ", " (List.map (fun (s,b,t) ->
  162. (if b then "?" else "") ^ ("...")
  163. ) l) in
  164. "(" ^ args ^ ")"
  165. in
  166. Printf.sprintf "%s -> ..." args
  167. | TAnon a ->
  168. begin
  169. match !(a.a_status) with
  170. | Statics c -> Printf.sprintf "{ Statics %s }" (s_type_path c.cl_path)
  171. | EnumStatics e -> Printf.sprintf "{ EnumStatics %s }" (s_type_path e.e_path)
  172. | AbstractStatics a -> Printf.sprintf "{ AbstractStatics %s }" (s_type_path a.a_path)
  173. | _ ->
  174. let fl = PMap.fold (fun f acc -> ((if Meta.has Meta.Optional f.cf_meta then " ?" else " ") ^ f.cf_name) :: acc) a.a_fields [] in
  175. "{" ^ String.concat "," fl ^ " }"
  176. end
  177. | TDynamic ->
  178. "Dynamic"
  179. | TLazy f ->
  180. s_type ctx (lazy_type f)
  181. and s_type_params ctx = function
  182. | [] -> ""
  183. | l -> "<" ^ String.concat ", " (List.map (fun _ -> "...") l) ^ ">"
  184. let better_error_message l =
  185. let ctx = print_context() in
  186. let rec loop acc l = match l with
  187. | (Cannot_unify _) as err1 :: (Cannot_unify _) :: l ->
  188. loop acc (err1 :: l)
  189. | x :: l ->
  190. loop (x :: acc) l
  191. | [] ->
  192. List.rev acc
  193. in
  194. let l = loop [] l in
  195. let access = get_access_chain ctx l in
  196. let message_buffer = Buffer.create 0 in
  197. let rec fill s i acc k l =
  198. if l = 0 then
  199. List.rev acc
  200. else begin
  201. if k = i then fill s i (s :: acc) (k + 1) (l - 1)
  202. else fill s i ("..." :: acc) (k + 1) (l - 1)
  203. end
  204. in
  205. let rec loop access access_prev =
  206. let loop () = match access.acc_next with
  207. | Some access' -> loop access' access
  208. | None ->
  209. begin match access.acc_messages with
  210. | err :: _ ->
  211. let msg = unify_error_msg ctx err in
  212. Buffer.add_string message_buffer msg;
  213. | [] ->
  214. ()
  215. end;
  216. s_type ctx access.acc_actual,s_type ctx access.acc_expected
  217. in
  218. begin match access.acc_kind with
  219. | Field s ->
  220. let s1,s2 = loop() in
  221. Printf.sprintf "{ %s: %s }" s s1,Printf.sprintf "{ %s: %s }" s s2
  222. | FunctionArgument(i,l) ->
  223. let s1,s2 = loop() in
  224. let sl1 = fill s1 i [] 1 l in
  225. let sl2 = fill s2 i [] 1 l in
  226. Printf.sprintf "(%s) -> ..." (String.concat ", " sl2),Printf.sprintf "(%s) -> ..." (String.concat ", " sl1)
  227. | FunctionReturn ->
  228. let s1,s2 = loop() in
  229. Printf.sprintf "(...) -> %s" s1,Printf.sprintf "(...) -> %s" s2
  230. | TypeParameter i ->
  231. let rec get_params t = match t with
  232. | TInst({cl_path = path},params) | TEnum({e_path = path},params) | TAbstract({a_path = path},params) | TType({t_path = path},params) ->
  233. path,params
  234. | _ ->
  235. die "" __LOC__
  236. in
  237. let s1,s2 = loop() in
  238. let path1,params1 = get_params access_prev.acc_actual in
  239. let path2,params2 = get_params access_prev.acc_expected in
  240. let sl1 = fill s1 i [] 1 (List.length params1) in
  241. let sl2 = fill s2 i [] 1 (List.length params2) in
  242. Printf.sprintf "%s<%s>" (s_type_path path1) (String.concat ", " sl1),Printf.sprintf "%s<%s>" (s_type_path path2) (String.concat ", " sl2)
  243. | Root ->
  244. loop()
  245. end;
  246. in
  247. match access.acc_next with
  248. | None ->
  249. String.concat "\n" (List.rev_map (unify_error_msg ctx) access.acc_messages)
  250. | Some access_next ->
  251. let slhs,srhs = loop access_next access in
  252. Printf.sprintf "error: %s\nhave: %s\nwant: %s" (Buffer.contents message_buffer) slhs srhs
  253. end
  254. let rec error_msg = function
  255. | Module_not_found m -> "Type not found : " ^ s_type_path m
  256. | Type_not_found (m,t,Private_type) -> "Cannot access private type " ^ t ^ " in module " ^ s_type_path m
  257. | Type_not_found (m,t,Not_defined) -> "Module " ^ s_type_path m ^ " does not define type " ^ t
  258. | Unify l -> BetterErrors.better_error_message l
  259. | Unknown_ident s -> "Unknown identifier : " ^ s
  260. | Custom s -> s
  261. | Stack (m1,m2) -> error_msg m1 ^ "\n" ^ error_msg m2
  262. | Call_error err -> s_call_error err
  263. | No_constructor mt -> (s_type_path (t_infos mt).mt_path ^ " does not have a constructor")
  264. and s_call_error = function
  265. | Not_enough_arguments tl ->
  266. let pctx = print_context() in
  267. "Not enough arguments, expected " ^ (String.concat ", " (List.map (fun (n,_,t) -> n ^ ":" ^ (short_type pctx t)) tl))
  268. | Too_many_arguments -> "Too many arguments"
  269. | Could_not_unify err -> error_msg err
  270. | Cannot_skip_non_nullable s -> "Cannot skip non-nullable argument " ^ s
  271. let error msg p = raise (Error (Custom msg,p))
  272. let raise_error err p = raise (Error(err,p))
  273. let error_require r p =
  274. if r = "" then
  275. error "This field is not available with the current compilation flags" p
  276. else
  277. let r = if r = "sys" then
  278. "a system platform (php,neko,cpp,etc.)"
  279. else try
  280. if String.sub r 0 5 <> "flash" then raise Exit;
  281. let _, v = ExtString.String.replace (String.sub r 5 (String.length r - 5)) "_" "." in
  282. "flash version " ^ v ^ " (use -swf-version " ^ v ^ ")"
  283. with _ ->
  284. "'" ^ r ^ "' to be enabled"
  285. in
  286. error ("Accessing this field requires " ^ r) p
  287. let invalid_assign p = error "Invalid assign" p