2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
11 open Reordered_argument_collections
14 type error_code
= int [@@deriving eq
]
16 (** We use `Pos.t message` on the server and convert to `Pos.absolute message`
17 * before sending it to the client *)
18 type 'a message
= 'a
* string [@@deriving eq
]
20 let get_message_pos (msg
: 'a message
) = fst msg
22 let get_message_str (msg
: 'a message
) = snd msg
41 type typing_error_callback
= ?code
:int -> (Pos.t
* string) list
-> unit
46 | TypeNamespace
(** Classes, interfaces, traits, records and type aliases.*)
47 (* The following are all subsets of TypeNamespace, used when we can
48 give a more specific naming error. E.g. `use Foo;` only allows
54 (* The file and phase of analysis being currently performed *)
55 let current_context : (Relative_path.t
* phase
) ref =
56 ref (Relative_path.default
, Typing
)
58 let current_span : Pos.t
ref = ref Pos.none
60 let allow_errors_in_default_path = ref true
62 module PhaseMap
= Reordered_argument_map
(WrappedMap.Make
(struct
72 let compare x y
= rank x
- rank y
75 (** Results of single file analysis. *)
76 type 'a file_t
= 'a list
PhaseMap.t
[@@deriving eq
]
78 (** Results of multi-file analysis. *)
79 type 'a files_t
= 'a file_t
Relative_path.Map.t
[@@deriving eq
]
81 let files_t_fold v ~f ~init
=
82 Relative_path.Map.fold v ~init ~f
:(fun path v acc
->
83 PhaseMap.fold v ~init
:acc ~f
:(fun phase v acc
-> f path phase v acc
))
85 let files_t_map v ~f
= Relative_path.Map.map v ~f
:(fun v
-> PhaseMap.map v ~f
)
87 let files_t_merge ~f x y
=
88 (* Using fold instead of merge to make the runtime proportional to the size
89 * of first argument (like List.rev_append ) *)
90 Relative_path.Map.fold x ~init
:y ~f
:(fun k x acc
->
92 Option.value (Relative_path.Map.find_opt
y k
) ~default
:PhaseMap.empty
97 (PhaseMap.merge x
y ~f
:(fun phase x
y -> f phase k x
y)))
99 let files_t_to_list x
=
100 files_t_fold x ~f
:(fun _ _ x acc
-> List.rev_append x acc
) ~init
:[]
103 let list_to_files_t = function
104 | [] -> Relative_path.Map.empty
106 (* Values constructed here should not be used with incremental mode.
107 * See assert in incremental_update. *)
108 Relative_path.Map.singleton
109 Relative_path.default
110 (PhaseMap.singleton Typing x
)
112 let get_code_severity code
=
115 = Error_codes.Init.err_code
Error_codes.Init.ForwardCompatibilityNotCurrent
121 (* Get most recently-ish added error. *)
122 let get_last error_map
=
123 (* If this map has more than one element, we pick an arbitrary file. Because
124 * of that, we might not end up with the most recent error and generate a
125 * less-specific error message. This should be rare. *)
126 match Relative_path.Map.max_binding_opt error_map
with
128 | Some
(_
, phase_map
) ->
130 PhaseMap.max_binding_opt phase_map
|> Option.value_map ~f
:snd ~default
:[]
132 (match List.rev
error_list with
136 type 'a error_
= error_code
* 'a message list
[@@deriving eq
]
138 type error
= Pos.t error_
[@@deriving eq
]
140 type applied_fixme
= Pos.t
* int [@@deriving eq
]
142 let applied_fixmes : applied_fixme files_t
ref = ref Relative_path.Map.empty
144 let (error_map
: error files_t
ref) = ref Relative_path.Map.empty
146 let accumulate_errors = ref false
148 (* Some filename when declaring *)
149 let in_lazy_decl = ref None
151 let (is_hh_fixme
: (Pos.t
-> error_code
-> bool) ref) = ref (fun _ _
-> false)
155 "There is an error somewhere in this file. However the type checker reports that the error is in another file. %s"
156 Error_message_sentinel.please_file_a_bug_message
158 let badpos_message_2 =
160 "There is an error somewhere in this definition. However the type checker reports that the error is elsewhere. %s"
161 Error_message_sentinel.please_file_a_bug_message
163 let try_with_result f1 f2
=
164 let error_map_copy = !error_map
in
165 let accumulate_errors_copy = !accumulate_errors in
166 let is_hh_fixme_copy = !is_hh_fixme
in
167 (is_hh_fixme
:= (fun _ _
-> false));
168 error_map
:= Relative_path.Map.empty
;
169 accumulate_errors := true;
170 let (result
, errors
) =
175 let result = f1
() in
181 error_map
:= error_map_copy;
182 accumulate_errors := accumulate_errors_copy;
183 is_hh_fixme
:= is_hh_fixme_copy
186 match get_last errors
with
189 (* Remove bad position sentinel if present: we might be about to add a new primary
194 when String.equal msg
badpos_message
195 || String.equal msg
badpos_message_2 ->
202 let error_map_copy = !error_map
in
203 let accumulate_errors_copy = !accumulate_errors in
204 let applied_fixmes_copy = !applied_fixmes in
205 error_map
:= Relative_path.Map.empty
;
206 applied_fixmes := Relative_path.Map.empty
;
207 accumulate_errors := true;
208 let (result, out_errors
, out_applied_fixmes
) =
214 (result, !error_map
, !applied_fixmes)
219 error_map
:= error_map_copy;
220 applied_fixmes := applied_fixmes_copy;
221 accumulate_errors := accumulate_errors_copy
224 let out_errors = files_t_map ~f
:List.rev
out_errors in
225 ((out_errors, out_applied_fixmes
), result)
227 let run_in_context path phase f
=
228 let context_copy = !current_context in
229 current_context := (path
, phase
);
230 Utils.try_finally ~f ~finally
:(fun () -> current_context := context_copy)
232 let run_with_span span f
=
233 let old_span = !current_span in
234 current_span := span
;
235 Utils.try_finally ~f ~finally
:(fun () -> current_span := old_span)
237 (* Log important data if lazy_decl triggers a crash *)
238 let lazy_decl_error_logging error error_map to_absolute to_string
=
239 let error_list = files_t_to_list !error_map
in
240 (* Print the current error list, which should be empty *)
241 Printf.eprintf
"%s" "Error list(should be empty):\n";
242 List.iter
error_list ~f
:(fun err
->
243 let msg = err
|> to_absolute
|> to_string
in
244 Printf.eprintf
"%s\n" msg);
245 Printf.eprintf
"%s" "Offending error:\n";
246 Printf.eprintf
"%s" error
;
248 (* Print out a larger stack trace *)
249 Printf.eprintf
"%s" "Callstack:\n";
252 (Caml.Printexc.raw_backtrace_to_string
(Caml.Printexc.get_callstack
500));
254 (* Exit with special error code so we can see the log after *)
255 Exit_status.exit
Exit_status.Lazy_decl_bug
257 (*****************************************************************************)
258 (* Error code printing. *)
259 (*****************************************************************************)
261 let error_kind error_code
=
262 match error_code
/ 1000 with
271 let error_code_to_string error_code
=
272 let error_kind = error_kind error_code
in
273 let error_number = Printf.sprintf
"%04d" error_code
in
274 error_kind ^
"[" ^
error_number ^
"]"
276 let phase_to_string (phase
: phase
) : string =
279 | Parsing
-> "Parsing"
284 let phase_of_string (value : string) : phase
option =
285 match Caml.String.lowercase_ascii
value with
286 | "init" -> Some Init
287 | "parsing" -> Some Parsing
288 | "naming" -> Some Naming
289 | "decl" -> Some Decl
290 | "typing" -> Some Typing
293 let (name_context_to_string
: name_context
-> string) = function
294 | FunctionNamespace
-> "function"
295 | ConstantNamespace
-> "constant"
296 | TypeNamespace
-> "type"
297 | TraitContext
-> "trait"
298 | ClassContext
-> "class"
299 | RecordContext
-> "record"
301 let get_message (error
: error
) =
302 (* We get the position of the first item in the message error list, which
303 represents the location of the error (error claim). Other messages represent
304 the reason for the error (the warrant and the grounds). *)
305 let message_list = snd error
in
306 let first_message = List.hd_exn
message_list in
309 let get_pos (error
: error
) = fst
(get_message error
)
312 let rec compare (x_code
, x_messages
) (y_code
, y_messages
) =
313 match (x_messages
, y_messages
) with
315 | (_x_messages
, []) -> -1
316 | ([], _y_messages
) -> 1
317 | (x_message
:: x_messages
, y_message
:: y_messages
) ->
318 (* The primary sort order is position *)
319 let comparison = Pos.compare (fst x_message
) (fst y_message
) in
320 (* If the positions are the same, sort by error code *)
322 if comparison = 0 then
323 Int.compare x_code y_code
327 (* If the error codes are also the same, sort by message text *)
329 if comparison = 0 then
330 String.compare (snd x_message
) (snd y_message
)
334 (* Finally, if the message text is also the same, then continue comparing
335 the rest of the messages (which indicate the reason why Hack believes
336 there is an error reported in the 1st message) *)
337 if comparison = 0 then
338 compare (x_code
, x_messages
) (y_code
, y_messages
)
342 let equal x
y = compare x
y = 0 in
343 List.sort ~
compare err
|> List.remove_consecutive_duplicates ~
equal
345 let get_sorted_error_list (err
, _
) = sort (files_t_to_list err
)
347 (* Getters and setter for passed-in map, based on current context *)
348 let get_current_file_t file_t_map
=
349 let current_file = fst
!current_context in
350 Relative_path.Map.find_opt file_t_map
current_file
351 |> Option.value ~default
:PhaseMap.empty
353 let get_current_list file_t_map
=
354 let current_phase = snd
!current_context in
355 get_current_file_t file_t_map
|> fun x
->
356 PhaseMap.find_opt x
current_phase |> Option.value ~default
:[]
358 let set_current_list file_t_map new_list
=
359 let (current_file, current_phase) = !current_context in
361 Relative_path.Map.add
364 (PhaseMap.add
(get_current_file_t !file_t_map
) current_phase new_list
)
366 let do_with_context path phase f
= run_in_context path phase
(fun () -> do_ f
)
368 (* Turn on lazy decl mode for the duration of the closure.
369 This runs without returning the original state,
370 since we collect it later in do_with_lazy_decls_
372 let run_in_decl_mode filename f
=
373 let old_in_lazy_decl = !in_lazy_decl in
374 in_lazy_decl := Some filename
;
375 Utils.try_finally ~f ~finally
:(fun () -> in_lazy_decl := old_in_lazy_decl)
377 and make_error code
(x
: (Pos.t
* string) list
) : error
= (code
, x
)
379 (*****************************************************************************)
381 (*****************************************************************************)
382 and get_code
(error
: 'a error_
) = (fst error
: error_code
)
384 let get_severity (error
: 'a error_
) = get_code_severity (get_code error
)
386 let to_list (error
: 'a error_
) = snd error
388 let to_absolute error
=
389 let (code
, msg_l
) = (get_code error
, to_list error
) in
390 let msg_l = List.map
msg_l (fun (p
, s
) -> (Pos.to_absolute p
, s
)) in
393 let make_absolute_error code
(x
: (Pos.absolute
* string) list
) :
394 Pos.absolute error_
=
397 let read_lines path
= In_channel.read_lines path
399 let num_digits x
= int_of_float
(Float.log10
(float_of_int x
)) + 1
401 (** Sort messages such that messages in the same file are together.
402 Do not reorder the files or messages within a file.
404 let group_messages_by_file (error
: Pos.absolute error_
) :
405 Pos.absolute message list
=
406 let msgs = to_list error
in
407 let rec build_map msgs grouped filenames
=
410 let filename = Pos.filename (fst
msg) in
411 (match String.Map.find grouped
filename with
414 String.Map.set
grouped ~key
:filename ~data
:(file_msgs
@ [msg])
416 build_map msgs grouped filenames
418 let grouped = String.Map.set
grouped ~key
:filename ~data
:[msg] in
419 build_map msgs grouped (filename :: filenames
))
420 | [] -> (grouped, filenames
)
422 let (grouped, filenames
) = build_map msgs String.Map.empty
[] in
423 List.concat_map
(List.rev filenames
) ~f
:(fun fn
->
424 String.Map.find_exn
grouped fn
)
426 (* E.g. "10 errors found." *)
427 let format_summary format errors dropped_count max_errors
: string option =
431 let total = List.length errors
+ dropped_count
in
432 let formatted_total =
442 match max_errors
with
443 | Some max_errors
when dropped_count
> 0 ->
445 " (only showing first %d, dropped %d).\n"
450 Some
(formatted_total ^
truncated)
453 let to_absolute_for_test error
=
454 let (code
, msg_l) = (get_code error
, to_list error
) in
456 List.map
msg_l (fun (p
, s
) ->
457 let path = Pos.filename p
in
458 let path_without_prefix = Relative_path.suffix
path in
461 (Relative_path.create
Relative_path.Dummy
path_without_prefix)
464 (Pos.to_absolute p, s
))
468 let to_string ?
(indent
= false) (error
: Pos.absolute error_
) : string =
469 let (error_code
, msgl
) = (get_code error
, to_list error
) in
470 let buf = Buffer.create
50 in
473 | (pos1
, msg1
) :: rest_of_error
->
477 let error_code = error_code_to_string error_code in
478 Printf.sprintf
"%s\n%s (%s)\n" (Pos.string pos1
) msg1
error_code
486 List.iter rest_of_error
(fun (p, w
) ->
488 Printf.sprintf
"%s%s\n%s%s\n" indentstr (Pos.string p) indentstr w
490 Buffer.add_string
buf msg));
493 let add_error_impl error
=
494 if !accumulate_errors then
496 match !current_context with
498 when Relative_path.equal path Relative_path.default
499 && not
!allow_errors_in_default_path ->
501 "WARNING: adding an error in default path\n%s\n"
502 (Caml.Printexc.raw_backtrace_to_string
503 (Caml.Printexc.get_callstack
100))
506 (* Cheap test to avoid duplicating most recent error *)
507 let error_list = get_current_list !error_map
in
508 match error_list with
509 | old_error
:: _
when equal_error error old_error
-> ()
510 | _
-> set_current_list error_map
(error
:: error_list)
512 (* We have an error, but haven't handled it in any way *)
513 let msg = error
|> to_absolute |> to_string in
514 match !in_lazy_decl with
515 | Some _
-> lazy_decl_error_logging msg error_map
to_absolute to_string
516 | None
-> Utils.assert_false_log_backtrace
(Some
msg)
518 (* Whether we've found at least one error *)
519 let currently_has_errors () = not
(List.is_empty
(get_current_list !error_map
))
521 module Parsing
= Error_codes.Parsing
522 module Naming
= Error_codes.Naming
523 module NastCheck
= Error_codes.NastCheck
524 module Typing
= Error_codes.Typing
526 (*****************************************************************************)
528 (*****************************************************************************)
530 type t
= error files_t
* applied_fixme files_t
[@@deriving eq
]
532 module type Error_category
= sig
539 val of_enum
: int -> t
option
541 val show
: t
-> string
543 val err_code
: t
-> int
546 (*****************************************************************************)
548 (*****************************************************************************)
550 let error_codes_treated_strictly = ref (ISet.of_list
[])
552 let is_strict_code code
= ISet.mem code
!error_codes_treated_strictly
554 (* The 'phps FixmeAllHackErrors' tool must be kept in sync with this list *)
555 let hard_banned_codes =
558 Typing.err_code
Typing.InvalidIsAsExpressionHint
;
559 Typing.err_code
Typing.InvalidEnforceableTypeArgument
;
560 Typing.err_code
Typing.RequireArgsReify
;
561 Typing.err_code
Typing.InvalidReifiedArgument
;
562 Typing.err_code
Typing.GenericsNotAllowed
;
563 Typing.err_code
Typing.InvalidNewableTypeArgument
;
564 Typing.err_code
Typing.InvalidNewableTypeParamConstraints
;
565 Typing.err_code
Typing.NewWithoutNewable
;
566 Typing.err_code
Typing.NewStaticClassReified
;
567 Typing.err_code
Typing.MemoizeReified
;
568 Typing.err_code
Typing.ClassGetReified
;
569 Typing.err_code
Typing.PocketUniversesReservedSyntax
;
572 let allowed_fixme_codes_strict = ref ISet.empty
574 let allowed_fixme_codes_partial = ref ISet.empty
576 let codes_not_raised_partial = ref ISet.empty
578 let set_allow_errors_in_default_path x
= allow_errors_in_default_path := x
580 let is_allowed_code_strict code
= ISet.mem code
!allowed_fixme_codes_strict
582 let is_allowed_code_partial code
= ISet.mem code
!allowed_fixme_codes_partial
584 let is_not_raised_partial code
= ISet.mem code
!codes_not_raised_partial
586 let (get_hh_fixme_pos
: (Pos.t
-> error_code -> Pos.t
option) ref) =
587 ref (fun _ _
-> None
)
589 let (is_hh_fixme_disallowed
: (Pos.t
-> error_code -> bool) ref) =
590 ref (fun _ _
-> false)
592 (*****************************************************************************)
593 (* Errors accumulator. *)
594 (*****************************************************************************)
596 (* If primary position in error list isn't in current file, wrap with a sentinel error *)
597 let check_pos_msg pos_msg_l
=
598 let pos = fst
(List.hd_exn pos_msg_l
) in
599 let current_file = fst
!current_context in
600 let current_span = !current_span in
601 (* If error is reported inside the current span, or no span has been set but the error
602 * is reported in the current file, then accept the error *)
604 Pos.contains
current_span pos
605 || Pos.equal current_span Pos.none
606 && Relative_path.equal (Pos.filename pos) current_file
607 || Relative_path.equal current_file Relative_path.default
613 |> List.map ~f
:(fun (pos, msg) ->
614 Pos.print_verbose_relative
pos ^
": " ^
msg)
617 Exception.get_current_callstack_string
99 |> Exception.clean_stack
619 HackEventLogger.type_check_primary_position_bug
624 if Pos.equal current_span Pos.none
then
625 (Pos.make_from
current_file, badpos_message)
627 (current_span, badpos_message_2)
631 let add_error_with_fixme_error code explanation pos_msg_list
=
632 let (pos, _
) = List.hd_exn pos_msg_list
in
633 let pos = Option.value (!get_hh_fixme_pos
pos code
) ~default
:pos in
634 add_error_impl (make_error code pos_msg_list
);
635 add_error_impl (make_error code
[(pos, explanation
)])
637 let rec add_applied_fixme code
pos =
638 if ServerLoadFlag.get_no_load
() then
639 let applied_fixmes_list = get_current_list !applied_fixmes in
640 set_current_list applied_fixmes ((pos, code
) :: applied_fixmes_list)
644 and add code
pos msg = add_list code
[(pos, msg)]
646 and add_error_with_check
(error
: error
) : unit =
647 add_list
(fst error
) (snd error
)
649 and fixme_present
pos code
=
650 !is_hh_fixme
pos code
|| !is_hh_fixme_disallowed
pos code
652 and add_list code pos_msg_l
=
653 let pos = fst
(List.hd_exn pos_msg_l
) in
654 let pos_msg_l = check_pos_msg pos_msg_l in
656 if ISet.mem code
hard_banned_codes then
657 if fixme_present
pos code
then
660 "You cannot use HH_FIXME or HH_IGNORE_ERROR comments to suppress error %d, and this cannot be enabled by configuration"
663 add_error_with_fixme_error code
explanation pos_msg_l
665 add_error_impl (make_error code
pos_msg_l)
667 is_not_raised_partial code
&& Relative_path.is_partial
(Pos.filename pos)
670 else if not
(fixme_present
pos code
) then
671 (* Fixmes and banned decl fixmes are separated by the parser because Errors can't recover
672 * the position information after the fact. This is the default case, where an HH_FIXME
673 * comment is not present. Therefore, the remaining cases are variations on behavior when
674 * a fixme is present *)
675 add_error_impl (make_error code
pos_msg_l)
676 else if Relative_path.(is_hhi
(prefix
(Pos.filename pos))) then
677 add_applied_fixme code
pos
678 else if !is_hh_fixme_disallowed
pos code
then
681 "You cannot use HH_FIXME or HH_IGNORE_ERROR comments to suppress error %d in declarations"
684 add_error_with_fixme_error code
explanation pos_msg_l
688 (not
(ISet.is_empty
!allowed_fixme_codes_partial))
689 && Relative_path.is_partial
(Pos.filename pos)
691 is_allowed_code_partial
693 is_allowed_code_strict
695 if whitelist code
then
696 add_applied_fixme code
pos
700 "You cannot use HH_FIXME or HH_IGNORE_ERROR comments to suppress error %d"
703 add_error_with_fixme_error code
explanation pos_msg_l
705 and add_error
(code
, pos_msg_l) = add_list code
pos_msg_l
707 and merge
(err'
, fixmes'
) (err, fixmes
) =
709 let x = Option.value x ~default
:[] in
710 let y = Option.value y ~default
:[] in
711 Some
(List.rev_append
x y)
713 (files_t_merge ~f
:append err'
err, files_t_merge ~f
:append fixmes' fixmes
)
715 and merge_into_current errors
=
716 let merged = merge errors
(!error_map
, !applied_fixmes) in
717 error_map
:= fst
merged;
718 applied_fixmes := snd
merged
720 and incremental_update
:
721 type (* Need to write out the entire ugly type to convince OCaml it's polymorphic
722 * and can update both error_map as well as applied_fixmes map *)
726 ((* function folding over paths of rechecked files *)
728 (Relative_path.t
-> a files_t
-> a files_t
) ->
732 fun old new_ fold phase
->
733 (* Helper to remove acc[path][phase]. If acc[path] becomes empty afterwards,
734 * remove it too (i.e do not store empty maps or lists ever). *)
735 let remove path phase acc
=
737 match Relative_path.Map.find_opt acc
path with
740 let new_phase_map = PhaseMap.remove phase_map phase
in
741 if PhaseMap.is_empty
new_phase_map then
746 match new_phase_map with
747 | None
-> Relative_path.Map.remove acc
path
748 | Some
x -> Relative_path.Map.add acc
path x
750 (* Replace old errors with new *)
752 files_t_merge new_ old ~f
:(fun phase
path new_ old
->
753 ( if Relative_path.equal path Relative_path.default
then
757 | Parsing
-> "Parsing"
762 Utils.assert_false_log_backtrace
764 ( "Default (untracked) error sources should not get into incremental "
765 ^
"mode. There might be a missing call to Errors.do_with_context/"
766 ^
"run_in_context somwhere or incorrectly used Errors.from_error_list."
770 | Some new_
-> Some
(List.rev new_
)
773 (* For files that were rechecked, but had no errors - remove them from maps *)
774 fold
res (fun path acc
->
776 match Relative_path.Map.find_opt new_
path with
778 | Some phase_map
-> PhaseMap.mem phase_map
phase
783 remove path phase acc
)
785 and incremental_update_set ~old ~new_ ~rechecked
phase =
787 Relative_path.Set.fold
796 ( incremental_update
(fst old
) (fst new_
) fold phase,
797 incremental_update
(snd old
) (snd new_
) fold phase )
799 and incremental_update_map ~old ~new_ ~rechecked
phase =
801 Relative_path.Map.fold
810 ( incremental_update
(fst old
) (fst new_
) fold phase,
811 incremental_update
(snd old
) (snd new_
) fold phase )
813 and empty
= (Relative_path.Map.empty
, Relative_path.Map.empty
)
815 and is_empty
(err, _fixmes
) = Relative_path.Map.is_empty
err
817 and count
(err, _fixmes
) =
818 files_t_fold err ~f
:(fun _ _
x acc
-> acc
+ List.length
x) ~init
:0
820 and get_error_list
(err, _fixmes
) = files_t_to_list err
822 and get_applied_fixmes
(_err
, fixmes
) = files_t_to_list fixmes
824 and from_error_list
err = (list_to_files_t err, Relative_path.Map.empty
)
826 (*****************************************************************************)
827 (* Accessors. (All methods delegated to the parameterized module.) *)
828 (*****************************************************************************)
830 let iter_error_list f
err = List.iter ~f
(get_sorted_error_list err)
832 let fold_errors ?
phase err ~init ~f
=
835 files_t_fold (fst
err) ~init ~f
:(fun source _ errors acc
->
836 List.fold_right errors ~init
:acc ~f
:(f source
))
838 Relative_path.Map.fold (fst
err) ~init ~f
:(fun source phases acc
->
839 match PhaseMap.find_opt phases
phase with
841 | Some errors
-> List.fold_right errors ~init
:acc ~f
:(f source
))
843 let fold_errors_in ?
phase err ~source ~init ~f
=
844 Relative_path.Map.find_opt
(fst
err) source
845 |> Option.value ~default
:PhaseMap.empty
846 |> PhaseMap.fold ~init ~f
:(fun p errors acc
->
848 | Some
x when not
(equal_phase
x p) -> acc
849 | _
-> List.fold_right errors ~init
:acc ~f
)
851 let get_failed_files err phase =
852 files_t_fold (fst
err) ~init
:Relative_path.Set.empty ~f
:(fun source
p _ acc
->
853 if not
(equal_phase
phase p) then
856 Relative_path.Set.add acc source
)
858 (*****************************************************************************)
859 (* Error code printing. *)
860 (*****************************************************************************)
862 let internal_error pos msg = add
0 pos ("Internal error: " ^
msg)
864 let unimplemented_feature pos msg = add
0 pos ("Feature not implemented: " ^
msg)
866 let experimental_feature pos msg =
867 add
0 pos ("Cannot use experimental feature: " ^
msg)
869 let strip_ns id
= id
|> Utils.strip_ns |> Hh_autoimport.reverse_type
871 let on_error_or_add (on_error
: typing_error_callback
option) code errl
=
873 | None
-> add_list code errl
874 | Some f
-> f ~code errl
876 (*****************************************************************************)
877 (* Parsing errors. *)
878 (*****************************************************************************)
880 let fixme_format pos =
882 (Parsing.err_code
Parsing.FixmeFormat
)
884 "HH_FIXME wrong format, expected '/* HH_FIXME[ERROR_NUMBER] */'"
886 let parsing_error (p, msg) = add
(Parsing.err_code
Parsing.ParsingError
) p msg
888 let xhp_parsing_error (p, msg) =
889 add
(Parsing.err_code
Parsing.XhpParsingError
) p msg
891 (*****************************************************************************)
892 (* Legacy AST / AAST errors *)
893 (*****************************************************************************)
895 let mk_unsupported_trait_use_as pos =
896 ( Naming.err_code
Naming.UnsupportedTraitUseAs
,
897 [(pos, "Trait use as is a PHP feature that is unsupported in Hack")] )
899 let unsupported_trait_use_as pos =
900 add_error_with_check
(mk_unsupported_trait_use_as pos)
902 let mk_unsupported_instead_of pos =
903 ( Naming.err_code
Naming.UnsupportedInsteadOf
,
904 [(pos, "insteadof is a PHP feature that is unsupported in Hack")] )
906 let unsupported_instead_of pos =
907 add_error_with_check
(mk_unsupported_instead_of pos)
909 let mk_invalid_trait_use_as_visibility pos =
910 ( Naming.err_code
Naming.InvalidTraitUseAsVisibility
,
911 [(pos, "Cannot redeclare trait method's visibility in this manner")] )
913 let invalid_trait_use_as_visibility pos =
914 add_error_with_check
(mk_invalid_trait_use_as_visibility pos)
916 (*****************************************************************************)
918 (*****************************************************************************)
920 let unexpected_arrow pos cname
=
922 (Naming.err_code
Naming.UnexpectedArrow
)
924 ("Keys may not be specified for " ^ cname ^
" initialization")
926 let missing_arrow pos cname
=
928 (Naming.err_code
Naming.MissingArrow
)
930 ("Keys must be specified for " ^ cname ^
" initialization")
932 let disallowed_xhp_type pos name
=
934 (Naming.err_code
Naming.DisallowedXhpType
)
936 (name ^
" is not a valid type. Use :xhp or XHPChild.")
938 let name_is_reserved name
pos =
939 let name = Utils.strip_all_ns
name in
941 (Naming.err_code
Naming.NameIsReserved
)
943 (name ^
" cannot be used as it is reserved.")
945 let dollardollar_unused pos =
947 (Naming.err_code
Naming.DollardollarUnused
)
949 ( "This expression does not contain a "
950 ^
"usage of the special pipe variable. Did you forget to use the ($$) "
953 let method_name_already_bound pos name =
955 (Naming.err_code
Naming.MethodNameAlreadyBound
)
957 ("Method name already bound: " ^
name)
959 let error_name_already_bound name name_prev
p p_prev
=
960 let name = strip_ns name in
961 let name_prev = strip_ns name_prev in
964 (p, "Name already bound: " ^
name);
966 if String.compare name name_prev = 0 then
967 "Previous definition is here"
969 "Previous definition "
971 ^
" differs only in capitalization " );
975 "This appears to be defined in an hhi file included in your project "
976 ^
"root. The hhi files for the standard library are now a part of the "
977 ^
"typechecker and must be removed from your project. Typically, you can "
978 ^
"do this by deleting the \"hhi\" directory you copied into your "
979 ^
"project when first starting with Hack."
982 if Relative_path.(is_hhi
(prefix
(Pos.filename p))) then
983 errs @ [(p_prev
, hhi_msg)]
984 else if Relative_path.(is_hhi
(prefix
(Pos.filename p_prev
))) then
985 errs @ [(p, hhi_msg)]
989 add_list
(Naming.err_code
Naming.ErrorNameAlreadyBound
) errs
991 let error_class_attribute_already_bound name name_prev p p_prev
=
992 let name = strip_ns name in
993 let name_prev = strip_ns name_prev in
997 "A class and an attribute class cannot share the same name. Conflicting class: "
999 (p_prev
, "Previous definition: " ^
name_prev);
1002 add_list
(Naming.err_code
Naming.AttributeClassNameConflict
) errs
1004 let unbound_name pos name kind
=
1007 | ConstantNamespace
-> " (a global constant)"
1008 | FunctionNamespace
-> " (a global function)"
1009 | TypeNamespace
-> ""
1010 | ClassContext
-> " (an object type)"
1011 | TraitContext
-> " (a trait)"
1012 | RecordContext
-> " (a record type)"
1015 (Naming.err_code
Naming.UnboundName
)
1017 ("Unbound name: " ^
strip_ns name ^
kind_str)
1019 let invalid_fun_pointer pos name =
1021 (Naming.err_code
Naming.InvalidFunPointer
)
1023 ( "Unbound global function: '"
1025 ^
"' is not a valid name for fun()" )
1027 let rx_move_invalid_location pos =
1029 (Naming.err_code
Naming.RxMoveInvalidLocation
)
1031 "Rx\\move is only allowed in argument position or as right hand side of the assignment."
1033 let undefined ~in_rx_scope
pos var_name did_you_mean
=
1037 "Variable %s is undefined, not always defined, or unset afterwards"
1040 Printf.sprintf
"Variable %s is undefined, or not always defined" var_name
1043 match did_you_mean
with
1044 | Some var_name
-> Printf.sprintf
" (did you mean %s instead?)" var_name
1047 add_list
(Naming.err_code
Naming.Undefined
) [(pos, msg ^
suggestion)]
1049 let this_reserved pos =
1051 (Naming.err_code
Naming.ThisReserved
)
1053 "The type parameter \"this\" is reserved"
1055 let start_with_T pos =
1057 (Naming.err_code
Naming.StartWith_T
)
1059 "Please make your type parameter start with the letter T (capital)"
1061 let already_bound pos name =
1063 (Naming.err_code
Naming.NameAlreadyBound
)
1065 ("Argument already bound: " ^
name)
1067 let unexpected_typedef pos def_pos expected_kind
=
1068 let expected_type = name_context_to_string expected_kind
in
1070 (Naming.err_code
Naming.UnexpectedTypedef
)
1072 (pos, Printf.sprintf
"Expected a %s but got a type alias." expected_type);
1073 (def_pos
, "Alias definition is here.");
1076 let mk_fd_name_already_bound pos =
1077 ( Naming.err_code
Naming.FdNameAlreadyBound
,
1078 [(pos, "Field name already bound")] )
1080 let fd_name_already_bound pos =
1081 add_error_with_check
(mk_fd_name_already_bound pos)
1083 let repeated_record_field name pos prev_pos
=
1084 let msg = Printf.sprintf
"Duplicate record field `%s`" name in
1086 (NastCheck.err_code
NastCheck.RepeatedRecordFieldName
)
1087 [(pos, msg); (prev_pos
, "Previous field is here")]
1089 let unexpected_record_field_name ~field_name ~field_pos ~record_name ~decl_pos
=
1092 "Record `%s` has no field `%s`"
1093 (strip_ns record_name
)
1097 (Typing.err_code
Typing.RecordUnknownField
)
1098 [(field_pos
, msg); (decl_pos
, "Definition is here")]
1100 let missing_record_field_name ~field_name ~new_pos ~record_name ~field_decl_pos
1104 "Mising required field `%s` in `%s`"
1106 (strip_ns record_name
)
1109 (Typing.err_code
Typing.RecordMissingRequiredField
)
1110 [(new_pos
, msg); (field_decl_pos
, "Field definition is here")]
1112 let type_not_record id
pos =
1114 (Typing.err_code
Typing.NotARecord
)
1116 (Printf.sprintf
"Expected a record type, but got `%s`." (strip_ns id
))
1118 let primitive_toplevel pos =
1120 (Naming.err_code
Naming.PrimitiveToplevel
)
1122 "Primitive type annotations are always available and may no longer be referred to in the toplevel namespace."
1124 let primitive_invalid_alias pos used valid
=
1126 (Naming.err_code
Naming.PrimitiveInvalidAlias
)
1128 ( "Invalid Hack type. Using '"
1130 ^
"' in Hack is considered an error. Use '"
1132 ^
"' instead, to keep the codebase consistent." )
1134 let dynamic_new_in_strict_mode pos =
1136 (Naming.err_code
Naming.DynamicNewInStrictMode
)
1138 "Cannot use dynamic new."
1140 let invalid_type_access_root (pos, id
) =
1142 (Naming.err_code
Naming.InvalidTypeAccessRoot
)
1144 (id ^
" must be an identifier for a class, \"self\", or \"this\"")
1146 let duplicate_user_attribute (pos, name) existing_attr_pos
=
1148 (Naming.err_code
Naming.DuplicateUserAttribute
)
1150 (pos, "You cannot reuse the attribute " ^
name);
1151 (existing_attr_pos
, name ^
" was already used here");
1154 let unbound_attribute_name pos name =
1156 if string_starts_with
name "__" then
1157 "starts with __ but is not a standard attribute"
1159 "does not have a class. Please declare a class for the attribute."
1162 (Naming.err_code
Naming.UnboundName
)
1164 ("Unrecognized user attribute: " ^
strip_ns name ^
" " ^
reason)
1166 let this_no_argument pos =
1168 (Naming.err_code
Naming.ThisNoArgument
)
1170 "\"this\" expects no arguments"
1172 let object_cast pos =
1174 (Naming.err_code
Naming.ObjectCast
)
1176 "Casts are only supported for bool, int, float and string."
1178 let this_hint_outside_class pos =
1180 (Naming.err_code
Naming.ThisHintOutsideClass
)
1182 "Cannot use \"this\" outside of a class"
1184 let this_type_forbidden pos =
1186 (Naming.err_code
Naming.ThisMustBeReturn
)
1188 "The type \"this\" cannot be used as a constraint on a class' generic, or as the type of a static member variable"
1190 let nonstatic_property_with_lsb pos =
1192 (Naming.err_code
Naming.NonstaticPropertyWithLSB
)
1194 "__LSB attribute may only be used on static properties"
1196 let lowercase_this pos type_
=
1198 (Naming.err_code
Naming.LowercaseThis
)
1200 ("Invalid Hack type \"" ^ type_ ^
"\". Use \"this\" instead")
1202 let classname_param pos =
1204 (Naming.err_code
Naming.ClassnameParam
)
1206 ( "Missing type parameter to classname; classname is entirely"
1207 ^
" meaningless without one" )
1209 (** Used if higher-kinded types are disabled *)
1210 let typaram_applied_to_type pos x =
1212 (Naming.err_code
Naming.HigherKindedTypesUnsupportedFeature
)
1215 "%s is a type parameter. Type parameters cannot take type arguments (e.g. %s<int> isn't allowed)"
1219 (** Used if higher-kinded types are disabled *)
1220 let tparam_with_tparam pos x =
1224 | _
-> x ^
" is a type parameter. "
1227 (Naming.err_code
Naming.HigherKindedTypesUnsupportedFeature
)
1230 "%sType parameters cannot themselves have type parameters"
1233 let shadowed_type_param p pos name =
1235 (Naming.err_code
Naming.ShadowedTypeParam
)
1237 (p, Printf.sprintf
"You cannot re-bind the type parameter %s" name);
1238 (pos, Printf.sprintf
"%s is already bound here" name);
1241 let missing_typehint pos =
1242 add
(Naming.err_code
Naming.MissingTypehint
) pos "Please add a type hint"
1244 let expected_variable pos =
1246 (Naming.err_code
Naming.ExpectedVariable
)
1248 "Was expecting a variable name"
1250 let clone_too_many_arguments pos =
1252 (Naming.err_code
Naming.NamingTooManyArguments
)
1254 "__clone method cannot take arguments"
1256 let naming_too_few_arguments pos =
1257 add
(Naming.err_code
Naming.NamingTooFewArguments
) pos "Too few arguments"
1259 let naming_too_many_arguments pos =
1260 add
(Naming.err_code
Naming.NamingTooManyArguments
) pos "Too many arguments"
1262 let expected_collection pos cn
=
1264 (Naming.err_code
Naming.ExpectedCollection
)
1266 ("Unexpected collection type " ^
strip_ns cn
)
1268 let illegal_CLASS pos =
1270 (Naming.err_code
Naming.IllegalClass
)
1272 "Using __CLASS__ outside a class or trait"
1274 let illegal_TRAIT pos =
1276 (Naming.err_code
Naming.IllegalTrait
)
1278 "Using __TRAIT__ outside a trait"
1280 let lvar_in_obj_get pos =
1282 (Naming.err_code
Naming.LvarInObjGet
)
1284 "Dynamic method or attribute access is not allowed on a non-dynamic value."
1286 let nullsafe_property_write_context pos =
1288 (Typing.err_code
Typing.NullsafePropertyWriteContext
)
1290 "?-> syntax not supported here, this function effectively does a write"
1292 let illegal_fun pos =
1294 "The argument to fun() must be a single-quoted, constant "
1295 ^
"literal string representing a valid function name."
1297 add
(Naming.err_code
Naming.IllegalFun
) pos msg
1299 let illegal_member_variable_class pos =
1301 "Cannot declare a constant named 'class'. The name 'class' is reserved for the class constant that represents the name of the class"
1303 add
(Naming.err_code
Naming.IllegalMemberVariableClass
) pos msg
1305 let illegal_meth_fun pos =
1307 "String argument to fun() contains ':';"
1308 ^
" for static class methods, use"
1309 ^
" class_meth(Cls::class, 'method_name'), not fun('Cls::method_name')"
1311 add
(Naming.err_code
Naming.IllegalMethFun
) pos msg
1313 let illegal_inst_meth pos =
1315 "The argument to inst_meth() must be an expression and a "
1316 ^
"constant literal string representing a valid method name."
1318 add
(Naming.err_code
Naming.IllegalInstMeth
) pos msg
1320 let illegal_meth_caller pos =
1322 "The two arguments to meth_caller() must be:"
1323 ^
"\n - first: ClassOrInterface::class"
1324 ^
"\n - second: a single-quoted string literal containing the name"
1325 ^
" of a non-static method of that class"
1327 add
(Naming.err_code
Naming.IllegalMethCaller
) pos msg
1329 let illegal_class_meth pos =
1331 "The two arguments to class_meth() must be:"
1332 ^
"\n - first: ValidClassname::class"
1333 ^
"\n - second: a single-quoted string literal containing the name"
1334 ^
" of a static method of that class"
1336 add
(Naming.err_code
Naming.IllegalClassMeth
) pos msg
1338 let class_meth_non_final_self pos class_name
=
1340 "`class_meth` with `self::class` does not preserve class calling context.\n"
1341 ^
"Use `static::class`, or `"
1342 ^
strip_ns class_name
1343 ^
"::class` explicitly"
1345 add
(Naming.err_code
Naming.ClassMethNonFinalSelf
) pos msg
1347 let assert_arity pos =
1349 (Naming.err_code
Naming.AssertArity
)
1351 "assert expects exactly one argument"
1353 let unexpected_ty_in_tast pos ~actual_ty ~expected_ty
=
1355 (Typing.err_code
Typing.UnexpectedTy
)
1357 ("Unexpected type in TAST: expected " ^ expected_ty ^
", got " ^ actual_ty
)
1359 let uninstantiable_class usage_pos decl_pos
name reason_msgl
=
1360 let name = strip_ns name in
1363 (usage_pos
, name ^
" is uninstantiable"); (decl_pos
, "Declaration is here");
1367 match reason_msgl
with
1368 | (reason_pos
, reason_str
) :: tail
->
1369 ((reason_pos
, reason_str ^
" which must be instantiable") :: tail
) @ msgl
1372 add_list
(Typing.err_code
Typing.UninstantiableClass
) msgl
1374 let new_abstract_record (pos, name) =
1375 let name = strip_ns name in
1377 (Typing.err_code
Typing.NewAbstractRecord
)
1379 (Printf.sprintf
"Cannot create instance of abstract record `%s`" name)
1381 let abstract_const_usage usage_pos decl_pos
name =
1382 let name = strip_ns name in
1384 (Typing.err_code
Typing.AbstractConstUsage
)
1386 (usage_pos
, "Cannot reference abstract constant " ^
name ^
" directly");
1387 (decl_pos
, "Declaration is here");
1390 let concrete_const_interface_override
1391 child_pos parent_pos parent_origin
name (on_error
: typing_error_callback
) =
1392 let parent_origin = strip_ns parent_origin in
1394 ~code
:(Typing.err_code
Typing.ConcreteConstInterfaceOverride
)
1397 "Non-abstract constants defined in an interface cannot be overridden when implementing or extending that interface."
1400 "You could make " ^
name ^
" abstract in " ^
parent_origin ^
"." );
1403 let const_without_typehint sid
=
1404 let (pos, name) = sid
in
1407 "Please add a type hint 'const SomeType %s'"
1408 (Utils.strip_all_ns
name)
1410 add
(Naming.err_code
Naming.AddATypehint
) pos msg
1412 let prop_without_typehint visibility sid
=
1413 let (pos, name) = sid
in
1415 Printf.sprintf
"Please add a type hint '%s SomeType %s'" visibility
name
1417 add
(Naming.err_code
Naming.AddATypehint
) pos msg
1419 let illegal_constant pos =
1420 add
(Naming.err_code
Naming.IllegalConstant
) pos "Illegal constant value"
1422 let invalid_req_implements pos =
1424 (Naming.err_code
Naming.InvalidReqImplements
)
1426 "Only traits may use 'require implements'"
1428 let invalid_req_extends pos =
1430 (Naming.err_code
Naming.InvalidReqExtends
)
1432 "Only traits and interfaces may use 'require extends'"
1434 let did_you_mean_naming pos name suggest_pos suggest_name
=
1436 (Naming.err_code
Naming.DidYouMeanNaming
)
1438 (pos, "Could not find " ^
strip_ns name);
1439 (suggest_pos
, "Did you mean " ^
strip_ns suggest_name ^
"?");
1442 let using_internal_class pos name =
1444 (Naming.err_code
Naming.UsingInternalClass
)
1446 (name ^
" is an implementation internal class that cannot be used directly")
1448 let too_few_type_arguments p =
1450 (Naming.err_code
Naming.TooFewTypeArguments
)
1452 "Too few type arguments for this type"
1454 let goto_label_already_defined
1455 label_name redeclaration_pos original_delcaration_pos
=
1457 (Naming.err_code
Naming.GotoLabelAlreadyDefined
)
1459 (redeclaration_pos
, "Cannot redeclare the goto label '" ^ label_name ^
"'");
1460 (original_delcaration_pos
, "Declaration is here");
1463 let goto_label_undefined pos label_name
=
1465 (Naming.err_code
Naming.GotoLabelUndefined
)
1467 ("Undefined goto label: " ^ label_name
)
1469 let goto_label_defined_in_finally pos =
1471 (Naming.err_code
Naming.GotoLabelDefinedInFinally
)
1473 "It is illegal to define a goto label within a finally block."
1475 let goto_invoked_in_finally pos =
1477 (Naming.err_code
Naming.GotoInvokedInFinally
)
1479 "It is illegal to invoke goto within a finally block."
1481 let mk_method_needs_visibility pos =
1482 ( Naming.err_code
Naming.MethodNeedsVisibility
,
1483 [(pos, "Methods need to be marked public, private, or protected.")] )
1485 let method_needs_visibility pos =
1486 add_error_with_check
(mk_method_needs_visibility pos)
1488 let dynamic_class_name_in_strict_mode pos =
1490 (Naming.err_code
Naming.DynamicClassNameInStrictMode
)
1492 "Cannot use dynamic class name in strict mode"
1494 let xhp_optional_required_attr pos id
=
1496 (Naming.err_code
Naming.XhpOptionalRequiredAttr
)
1498 ("XHP attribute " ^ id ^
" cannot be marked as nullable and required")
1500 let xhp_required_with_default pos id
=
1502 (Naming.err_code
Naming.XhpRequiredWithDefault
)
1506 ^
" cannot be marked as required and provide a default" )
1508 let array_typehints_disallowed pos =
1510 (Naming.err_code
Naming.ArrayTypehintsDisallowed
)
1512 "Array typehints are no longer legal; use varray or darray instead"
1514 let array_literals_disallowed pos =
1516 (Naming.err_code
Naming.ArrayLiteralsDisallowed
)
1518 "Array literals are no longer legal; use varray or darray instead"
1520 let wildcard_disallowed pos =
1522 (Naming.err_code
Naming.WildcardDisallowed
)
1524 "Wildcard typehints are not allowed in this position"
1526 let misplaced_mutability_hint pos =
1528 (Naming.err_code
Naming.MisplacedMutabilityHint
)
1530 "Setting mutability via type hints is only allowed for parameters of reactive function types. For other cases consider using attributes."
1532 let mutability_hint_in_non_rx_function pos =
1534 (Naming.err_code
Naming.MutabilityHintInNonRx
)
1536 "Parameter with mutability hint cannot appear in non-reactive function type."
1538 let invalid_mutability_in_return_type_hint pos =
1540 (Naming.err_code
Naming.InvalidReturnMutableHint
)
1542 "OwnedMutable is the only mutability related hint allowed in return type annotation for reactive function types."
1544 let pu_case_in_trait pos kind
=
1546 (Naming.err_code
Naming.PocketUniversesNotInClass
)
1548 (sprintf
"Case %s is not allowed in traits" kind
)
1550 let pu_duplication pos kind
name seen
=
1551 let name = strip_ns name in
1552 let seen = strip_ns seen in
1554 (Naming.err_code
Naming.PocketUniversesDuplication
)
1556 (sprintf
"Pocket Universe %s %s is already declared in %s" kind
name seen)
1558 let pu_duplication_in_instance pos kind
name seen =
1559 let name = strip_ns name in
1560 let seen = strip_ns seen in
1562 (Naming.err_code
Naming.PocketUniversesDuplication
)
1564 (sprintf
"%s %s is already assigned in %s" kind
name seen)
1566 let pu_not_in_class pos name loc
=
1567 let name = strip_ns name in
1568 let loc = strip_ns loc in
1570 (Naming.err_code
Naming.PocketUniversesNotInClass
)
1572 (sprintf
"Pocket Universe %s is defined outside a class (%s)" name loc)
1574 let pu_atom_missing pos name kind
loc missing
=
1575 let name = strip_ns name in
1576 let loc = strip_ns loc in
1578 (Naming.err_code
Naming.PocketUniversesAtomMissing
)
1581 "In Pocket Universe %s, atom %s is missing %s %s"
1587 let pu_atom_unknown pos name kind
loc unk
=
1588 let name = strip_ns name in
1589 let loc = strip_ns loc in
1591 (Naming.err_code
Naming.PocketUniversesAtomUnknown
)
1594 "In Pocket Universe %s, atom %s declares unknown %s %s"
1600 let pu_localize pos pu dep_ty
=
1601 let pu = strip_ns pu in
1602 let dep_ty = strip_ns dep_ty in
1604 (Naming.err_code
Naming.PocketUniversesLocalization
)
1606 (sprintf
"In the context of %s, cannot expand %s" pu dep_ty)
1608 let pu_invalid_access pos msg =
1610 (Naming.err_code
Naming.PocketUniversesLocalization
)
1612 ("Invalid Pocket Universe invocation" ^
msg)
1614 let pu_attribute_invalid pos =
1616 (Typing.err_code
Typing.PocketUniversesAttributes
)
1618 "Invalid __Pu attribute"
1620 let pu_attribute_dup pos kind s
=
1621 let s = strip_ns s in
1623 (Typing.err_code
Typing.PocketUniversesAttributes
)
1625 (sprintf
"Duplicated %s '%s' in __Pu attribute" kind
s)
1627 let pu_attribute_err pos kind class_name enum_name attr_name
=
1628 let class_name = strip_ns class_name in
1630 (Typing.err_code
Typing.PocketUniversesAttributes
)
1633 "Class/Trait %s has a %s attribute '%s' for enumeration %s"
1639 let pu_attribute_suggestion pos class_name content
=
1640 let class_name = strip_ns class_name in
1642 (Typing.err_code
Typing.PocketUniversesAttributes
)
1645 "Class/Trait %s should have the attribute:\n__Pu(%s)"
1649 let pu_attribute_not_necessary pos class_name =
1650 let class_name = strip_ns class_name in
1652 (Typing.err_code
Typing.PocketUniversesAttributes
)
1654 (sprintf
"Class/Trait %s does not need any __Pu attribute" class_name)
1656 let pu_reserved_syntax pos =
1658 (Typing.err_code
Typing.PocketUniversesReservedSyntax
)
1660 ( "This syntax is reserved for the Pocket Universes prototype.\n"
1661 ^
"It can only be used in the directories specified by the\n"
1662 ^
" pocket_universe_enabled_paths = nowhere|everywhere|dir1,..,dirn\noption in .hhconfig"
1665 let illegal_use_of_dynamically_callable attr_pos meth_pos visibility
=
1667 (Naming.err_code
Naming.IllegalUseOfDynamicallyCallable
)
1669 (attr_pos
, "__DynamicallyCallable can only be used on public methods");
1670 (meth_pos
, sprintf
"But this method is %s" visibility
);
1673 (*****************************************************************************)
1674 (* Init check errors *)
1675 (*****************************************************************************)
1677 let no_construct_parent pos =
1679 (NastCheck.err_code
NastCheck.NoConstructParent
)
1683 "You are extending a class that needs to be initialized\n";
1684 "Make sure you call parent::__construct.\n";
1687 let nonstatic_method_in_abstract_final_class pos =
1689 (NastCheck.err_code
NastCheck.NonstaticMethodInAbstractFinalClass
)
1691 "Abstract final classes cannot have nonstatic methods or constructors."
1693 let constructor_required (pos, name) prop_names
=
1694 let name = strip_ns name in
1695 let props_str = String.concat prop_names ~sep
:" " in
1697 (NastCheck.err_code
NastCheck.ConstructorRequired
)
1699 ( "Lacking __construct, class "
1701 ^
" does not initialize its private member(s): "
1704 let not_initialized (pos, cname
) prop_names
=
1705 let cname = strip_ns cname in
1707 List.fold_right prop_names ~f
:(fun x acc
-> x ^
" " ^ acc
) ~init
:""
1709 let (members
, verb
) =
1710 if 1 = List.length prop_names
then
1718 ~f
:(fun x acc
-> "$this->" ^
x ^
" " ^ acc
)
1722 (NastCheck.err_code
NastCheck.NotInitialized
)
1728 " does not initialize all of its members; ";
1731 " not always initialized.";
1732 "\nMake sure you systematically set ";
1734 "when the method __construct is called.";
1735 "\nAlternatively, you can define the ";
1737 " as nullable (?...)\n";
1740 let call_before_init pos cv
=
1742 (NastCheck.err_code
NastCheck.CallBeforeInit
)
1746 "Until the initialization of $this is over,";
1747 " you can only call private methods\n";
1748 "The initialization is not over because ";
1751 if String.equal cv
"parent::__construct" then
1752 ["you forgot to call parent::__construct"]
1754 ["$this->"; cv
; " can still potentially be null"] ))
1756 (*****************************************************************************)
1757 (* Nast errors check *)
1758 (*****************************************************************************)
1760 let type_arity use_pos def_pos ~expected ~actual
=
1762 (Typing.err_code
Typing.TypeArityMismatch
)
1766 "Wrong number of type arguments (expected %d, got %d)"
1769 (def_pos
, "Definition is here");
1772 let abstract_with_body (p, _
) =
1774 (NastCheck.err_code
NastCheck.AbstractWithBody
)
1776 "This method is declared as abstract, but has a body"
1778 let not_abstract_without_body (p, _
) =
1780 (NastCheck.err_code
NastCheck.NotAbstractWithoutBody
)
1782 "This method is not declared as abstract, it must have a body"
1784 let mk_not_abstract_without_typeconst (p, _
) =
1785 ( NastCheck.err_code
NastCheck.NotAbstractWithoutTypeconst
,
1788 "This type constant is not declared as abstract, it must have"
1789 ^
" an assigned type" );
1792 let not_abstract_without_typeconst node
=
1793 add_error_with_check
(mk_not_abstract_without_typeconst node
)
1795 let typeconst_depends_on_external_tparam pos ext_pos ext_name
=
1797 (NastCheck.err_code
NastCheck.TypeconstDependsOnExternalTparam
)
1800 "A type constant can only use type parameters declared in its own"
1801 ^
" type parameter list" );
1802 (ext_pos
, ext_name ^
" was declared as a type parameter here");
1805 let interface_with_partial_typeconst tconst_pos
=
1807 (NastCheck.err_code
NastCheck.InterfaceWithPartialTypeconst
)
1809 "An interface cannot contain a partially abstract type constant"
1811 let mk_multiple_xhp_category pos =
1812 ( NastCheck.err_code
NastCheck.MultipleXhpCategory
,
1813 [(pos, "XHP classes can only contain one category declaration")] )
1815 let multiple_xhp_category pos =
1816 add_error_with_check
(mk_multiple_xhp_category pos)
1818 let return_in_gen p =
1820 (NastCheck.err_code
NastCheck.ReturnInGen
)
1822 ( "You cannot return a value in a generator (a generator"
1823 ^
" is a function that uses yield)" )
1825 let return_in_finally p =
1827 (NastCheck.err_code
NastCheck.ReturnInFinally
)
1829 ( "Don't use return in a finally block;"
1830 ^
" there's nothing to receive the return value" )
1832 let toplevel_break p =
1834 (NastCheck.err_code
NastCheck.ToplevelBreak
)
1836 "break can only be used inside loops or switch statements"
1838 let toplevel_continue p =
1840 (NastCheck.err_code
NastCheck.ToplevelContinue
)
1842 "continue can only be used inside loops"
1844 let continue_in_switch p =
1846 (NastCheck.err_code
NastCheck.ContinueInSwitch
)
1848 ( "In PHP, 'continue;' inside a switch statement is equivalent to 'break;'."
1849 ^
" Hack does not support this; use 'break' if that is what you meant." )
1851 let await_in_sync_function p =
1853 (NastCheck.err_code
NastCheck.AwaitInSyncFunction
)
1855 "await can only be used inside async functions"
1857 let interface_use_trait p =
1859 (NastCheck.err_code
NastCheck.InterfaceUsesTrait
)
1861 "Interfaces cannot use traits"
1863 let await_in_coroutine p =
1865 (NastCheck.err_code
NastCheck.AwaitInCoroutine
)
1867 "await is not allowed in coroutines."
1869 let yield_in_coroutine p =
1871 (NastCheck.err_code
NastCheck.YieldInCoroutine
)
1873 "yield is not allowed in coroutines."
1875 let suspend_outside_of_coroutine p =
1877 (NastCheck.err_code
NastCheck.SuspendOutsideOfCoroutine
)
1879 "suspend is only allowed in coroutines."
1881 let suspend_in_finally p =
1883 (NastCheck.err_code
NastCheck.SuspendInFinally
)
1885 "suspend is not allowed inside finally blocks."
1887 let static_memoized_function p =
1889 (NastCheck.err_code
NastCheck.StaticMemoizedFunction
)
1891 "memoize is not allowed on static methods in classes that aren't final "
1895 (NastCheck.err_code
NastCheck.Magic
)
1897 (s ^
" is a magic method and cannot be called directly")
1899 let non_interface (p : Pos.t
) (c2
: string) (verb
: string) : 'a
=
1901 (NastCheck.err_code
NastCheck.NonInterface
)
1903 ("Cannot " ^ verb ^
" " ^
strip_ns c2 ^
" - it is not an interface")
1905 let toString_returns_string pos =
1907 (NastCheck.err_code
NastCheck.ToStringReturnsString
)
1909 "__toString should return a string"
1911 let toString_visibility pos =
1913 (NastCheck.err_code
NastCheck.ToStringVisibility
)
1915 "__toString must have public visibility and cannot be static"
1917 let uses_non_trait (p : Pos.t
) (n
: string) (t
: string) =
1919 (NastCheck.err_code
NastCheck.UsesNonTrait
)
1921 (strip_ns n ^
" is not a trait. It is " ^ t ^
".")
1923 let requires_non_class (p : Pos.t
) (n
: string) (t
: string) =
1925 (NastCheck.err_code
NastCheck.RequiresNonClass
)
1927 (strip_ns n ^
" is not a class. It is " ^ t ^
".")
1929 let requires_final_class (p : Pos.t
) (n
: string) =
1931 (NastCheck.err_code
NastCheck.RequiresFinalClass
)
1933 (strip_ns n ^
" is not an extendable class.")
1935 let abstract_body pos =
1937 (NastCheck.err_code
NastCheck.AbstractBody
)
1939 "This method shouldn't have a body"
1941 let interface_with_member_variable pos =
1943 (NastCheck.err_code
NastCheck.InterfaceWithMemberVariable
)
1945 "Interfaces cannot have member variables"
1947 let interface_with_static_member_variable pos =
1949 (NastCheck.err_code
NastCheck.InterfaceWithStaticMemberVariable
)
1951 "Interfaces cannot have static variables"
1953 let illegal_function_name pos mname
=
1955 (NastCheck.err_code
NastCheck.IllegalFunctionName
)
1957 ("Illegal function name: " ^
strip_ns mname
)
1959 let inout_params_in_coroutine pos =
1961 (NastCheck.err_code
NastCheck.InoutParamsInCoroutine
)
1963 "Inout parameters cannot be defined on coroutines."
1965 let mutable_attribute_on_function pos =
1967 (NastCheck.err_code
NastCheck.MutableAttributeOnFunction
)
1969 "<<__Mutable>> only makes sense on methods, or parameters on functions or methods."
1971 let maybe_mutable_attribute_on_function pos =
1973 (NastCheck.err_code
NastCheck.MaybeMutableAttributeOnFunction
)
1975 "<<__MaybeMutable>> only makes sense on methods, or parameters on functions or methods."
1977 let conflicting_mutable_and_maybe_mutable_attributes pos =
1979 (NastCheck.err_code
NastCheck.ConflictingMutableAndMaybeMutableAttributes
)
1981 "Declaration cannot have both <<__Mutable>> and <<__MaybeMutable>> attributtes."
1983 let mutable_methods_must_be_reactive pos name =
1985 (NastCheck.err_code
NastCheck.MutableMethodsMustBeReactive
)
1989 ^
" has a mutable parameter"
1990 ^
" (or mutable this), so it must be marked reactive with <<__Rx>>." )
1992 let mutable_return_annotated_decls_must_be_reactive kind
pos name =
1994 (NastCheck.err_code
NastCheck.MutableReturnAnnotatedDeclsMustBeReactive
)
2000 ^
" is annotated with <<__MutableReturn>>, "
2001 ^
" so it must be marked reactive with <<__Rx>>." )
2003 let maybe_mutable_methods_must_be_reactive pos name =
2005 (NastCheck.err_code
NastCheck.MaybeMutableMethodsMustBeReactive
)
2009 ^
" is annotated with <<__MaybeMutable> attribute, or has this attribute on one of parameters so it must be marked reactive."
2012 let entrypoint_arguments pos =
2014 (NastCheck.err_code
NastCheck.EntryPointArguments
)
2016 "__EntryPoint functions cannot take arguments."
2018 let variadic_memoize pos =
2020 (NastCheck.err_code
NastCheck.VariadicMemoize
)
2022 "Memoized functions cannot be variadic."
2024 let abstract_method_memoize pos =
2026 (NastCheck.err_code
NastCheck.AbstractMethodMemoize
)
2028 "Abstract methods cannot be memoized."
2030 let inout_params_special pos =
2032 (NastCheck.err_code
NastCheck.InoutParamsSpecial
)
2034 "Methods with special semantics cannot have inout parameters."
2036 let inout_params_memoize fpos
pos =
2037 let msg1 = (fpos
, "Functions with inout parameters cannot be memoized") in
2038 let msg2 = (pos, "This is an inout parameter") in
2039 add_list
(NastCheck.err_code
NastCheck.InoutParamsMemoize
) [msg1; msg2]
2041 let reading_from_append pos =
2043 (NastCheck.err_code
NastCheck.ReadingFromAppend
)
2045 "Cannot use [] for reading"
2047 let inout_argument_bad_expr pos =
2049 (NastCheck.err_code
NastCheck.InoutArgumentBadExpr
)
2051 ( "Arguments for inout parameters must be local variables or simple "
2052 ^
"subscript expressions on vecs, dicts, keysets, or arrays" )
2054 let illegal_destructor pos =
2056 (NastCheck.err_code
NastCheck.IllegalDestructor
)
2058 ( "Destructors are not supported in Hack; use other patterns like "
2059 ^
"IDisposable/using or try/catch instead." )
2061 let multiple_conditionally_reactive_annotations pos name =
2063 (NastCheck.err_code
NastCheck.MultipleConditionallyReactiveAnnotations
)
2065 ("Method '" ^
name ^
"' has multiple <<__OnlyRxIfImpl>> annotations.")
2067 let rx_is_enabled_invalid_location pos =
2069 (NastCheck.err_code
NastCheck.RxIsEnabledInvalidLocation
)
2071 ( "HH\\Rx\\IS_ENABLED must be the only condition in an if-statement, "
2072 ^
"and that if-statement must be the only statement in the function body."
2075 let atmost_rx_as_rxfunc_invalid_location pos =
2077 (NastCheck.err_code
NastCheck.MaybeRxInvalidLocation
)
2079 "<<__AtMostRxAsFunc>> attribute can only be put on parameters of conditionally reactive function or method annotated with <<__AtMostRxAsArgs>> attribute."
2081 let no_atmost_rx_as_rxfunc_for_rx_if_args pos =
2083 (NastCheck.err_code
NastCheck.NoOnlyrxIfRxfuncForRxIfArgs
)
2085 "Function or method annotated with <<__AtMostRxAsArgs>> attribute should have at least one parameter with <<__AtMostRxAsFunc>> or <<__OnlyRxIfImpl>> annotations."
2087 let conditionally_reactive_annotation_invalid_arguments ~is_method
pos =
2096 NastCheck.ConditionallyReactiveAnnotationInvalidArguments
)
2099 ^
" is marked with <<__OnlyRxIfImpl>> attribute that have "
2100 ^
"invalid arguments. This attribute must have one argument and it should be "
2101 ^
"'::class' class constant." )
2103 let coroutine_in_constructor pos =
2105 (NastCheck.err_code
NastCheck.CoroutineInConstructor
)
2107 "A class constructor may not be a coroutine"
2109 let switch_non_terminal_default pos =
2111 (NastCheck.err_code
NastCheck.SwitchNonTerminalDefault
)
2113 "Default case in switch must be terminal"
2115 let switch_multiple_default pos =
2117 (NastCheck.err_code
NastCheck.SwitchMultipleDefault
)
2119 "There can be only one default case in switch"
2121 (*****************************************************************************)
2122 (* Nast terminality *)
2123 (*****************************************************************************)
2125 let case_fallthrough pos1 pos2
=
2127 (NastCheck.err_code
NastCheck.CaseFallthrough
)
2130 "This switch has a case that implicitly falls through and is "
2131 ^
"not annotated with // FALLTHROUGH" );
2132 (pos2
, "This case implicitly falls through");
2135 let default_fallthrough pos =
2137 (NastCheck.err_code
NastCheck.DefaultFallthrough
)
2139 ( "This switch has a default case that implicitly falls "
2140 ^
"through and is not annotated with // FALLTHROUGH" )
2142 (*****************************************************************************)
2144 (*****************************************************************************)
2146 let visibility_extends
2147 vis
pos parent_pos parent_vis
(on_error
: typing_error_callback
) =
2148 let msg1 = (pos, "This member visibility is: " ^ vis
) in
2149 let msg2 = (parent_pos
, parent_vis ^
" was expected") in
2150 on_error ~code
:(Typing.err_code
Typing.VisibilityExtends
) [msg1; msg2]
2152 let member_not_implemented member_name parent_pos
pos defn_pos
=
2153 let msg1 = (pos, "This type doesn't implement the method " ^ member_name
) in
2154 let msg2 = (parent_pos
, "Which is required by this interface") in
2155 let msg3 = (defn_pos
, "As defined here") in
2156 add_list
(Typing.err_code
Typing.MemberNotImplemented
) [msg1; msg2; msg3]
2158 let bad_decl_override parent_pos parent_name
pos name msgl =
2163 ^
" does not correctly implement all required members " )
2167 "Some members are incompatible with those declared in type "
2168 ^
strip_ns parent_name
)
2170 (* This is a cascading error message *)
2171 add_list
(Typing.err_code
Typing.BadDeclOverride
) (msg1 :: msg2 :: msgl)
2173 let bad_method_override pos member_name
msgl (on_error
: typing_error_callback
)
2176 (pos, "The method " ^
strip_ns member_name ^
" has the wrong type")
2178 (* This is a cascading error message *)
2179 on_error ~code
:(Typing.err_code
Typing.BadMethodOverride
) (msg :: msgl)
2181 let bad_prop_override pos member_name
msgl (on_error
: typing_error_callback
) =
2183 (pos, "The property " ^
strip_ns member_name ^
" has the wrong type")
2185 (* This is a cascading error message *)
2186 on_error ~code
:(Typing.err_code
Typing.BadMethodOverride
) (msg :: msgl)
2188 let bad_enum_decl pos msgl =
2189 let msg = (pos, "This enum declaration is invalid.") in
2190 (* This is a cascading error message *)
2191 add_list
(Typing.err_code
Typing.BadEnumExtends
) (msg :: msgl)
2193 let missing_constructor pos (on_error
: typing_error_callback
) =
2195 ~code
:(Typing.err_code
Typing.MissingConstructor
)
2196 [(pos, "The constructor is not implemented")]
2198 let typedef_trail_entry pos = (pos, "Typedef definition comes from here")
2200 let abstract_tconst_not_allowed pos (p, tconst_name
) =
2202 (Typing.err_code
Typing.AbstractTconstNotAllowed
)
2204 (pos, "An abstract type constant is not allowed in this position.");
2205 (p, Printf.sprintf
"%s is abstract here." tconst_name
);
2208 let add_with_trail code
errs trail
=
2209 add_list code
(errs @ List.map trail
typedef_trail_entry)
2211 let enum_constant_type_bad pos ty_pos ty trail
=
2213 (Typing.err_code
Typing.EnumConstantTypeBad
)
2214 [(pos, "Enum constants must be an int or string"); (ty_pos
, "Not " ^ ty
)]
2217 let enum_type_bad pos ty trail
=
2219 (Typing.err_code
Typing.EnumTypeBad
)
2220 [(pos, "Enums must be int or string or arraykey, not " ^ ty
)]
2223 let enum_type_typedef_nonnull pos =
2225 (Typing.err_code
Typing.EnumTypeTypedefNonnull
)
2227 "Can't use typedef that resolves to nonnull in enum"
2229 let enum_switch_redundant const first_pos second_pos
=
2231 (Typing.err_code
Typing.EnumSwitchRedundant
)
2233 (second_pos
, "Redundant case statement");
2234 (first_pos
, const ^
" already handled here");
2237 let enum_switch_nonexhaustive pos missing enum_pos
=
2239 (Typing.err_code
Typing.EnumSwitchNonexhaustive
)
2242 "Switch statement nonexhaustive; the following cases are missing: "
2243 ^
String.concat ~sep
:", " missing
);
2244 (enum_pos
, "Enum declared here");
2247 let enum_switch_redundant_default pos enum_pos
=
2249 (Typing.err_code
Typing.EnumSwitchRedundantDefault
)
2252 "All cases already covered; a redundant default case prevents "
2253 ^
"detecting future errors. If your goal is to guard against "
2254 ^
"invalid values for this type, do an `is` check before the switch." );
2255 (enum_pos
, "Enum declared here");
2258 let enum_switch_not_const pos =
2260 (Typing.err_code
Typing.EnumSwitchNotConst
)
2262 "Case in switch on enum is not an enum constant"
2264 let enum_switch_wrong_class pos expected got
=
2266 (Typing.err_code
Typing.EnumSwitchWrongClass
)
2268 ("Switching on enum " ^ expected ^
" but using constant from " ^ got
)
2270 let invalid_shape_field_name p =
2272 (Typing.err_code
Typing.InvalidShapeFieldName
)
2274 "Was expecting a constant string, class constant, or int (for shape access)"
2276 let invalid_shape_field_name_empty p =
2278 (Typing.err_code
Typing.InvalidShapeFieldNameEmpty
)
2280 "A shape field name cannot be an empty string"
2282 let invalid_shape_field_type pos ty_pos ty trail
=
2284 (Typing.err_code
Typing.InvalidShapeFieldType
)
2286 (pos, "A shape field name must be an int or string"); (ty_pos
, "Not " ^ ty
);
2290 let invalid_shape_field_literal key_pos witness_pos
=
2292 (Typing.err_code
Typing.InvalidShapeFieldLiteral
)
2294 (key_pos
, "Shape uses literal string as field name");
2295 (witness_pos
, "But expected a class constant");
2298 let invalid_shape_field_const key_pos witness_pos
=
2300 (Typing.err_code
Typing.InvalidShapeFieldConst
)
2302 (key_pos
, "Shape uses class constant as field name");
2303 (witness_pos
, "But expected a literal string");
2306 let shape_field_class_mismatch key_pos witness_pos key_class witness_class
=
2308 (Typing.err_code
Typing.ShapeFieldClassMismatch
)
2310 (key_pos
, "Shape field name is class constant from " ^ key_class
);
2311 (witness_pos
, "But expected constant from " ^ witness_class
);
2314 let shape_field_type_mismatch key_pos witness_pos key_ty witness_ty
=
2316 (Typing.err_code
Typing.ShapeFieldTypeMismatch
)
2318 (key_pos
, "Shape field name is " ^ key_ty ^
" class constant");
2319 (witness_pos
, "But expected " ^ witness_ty
);
2322 let missing_field pos1 pos2
name (on_error
: typing_error_callback
) =
2324 ~code
:(Typing.err_code
Typing.MissingField
)
2326 (pos1
, "The field '" ^
name ^
"' is missing");
2327 (pos2
, "The field '" ^
name ^
"' is defined");
2330 let shape_fields_unknown pos1 pos2
(on_error
: typing_error_callback
) =
2332 ~code
:(Typing.err_code
Typing.ShapeFieldsUnknown
)
2335 "This shape type allows unknown fields, and so it may contain fields other than those explicitly declared in its declaration."
2338 "It is incompatible with a shape that does not allow unknown fields." );
2341 let invalid_shape_remove_key p =
2343 (Typing.err_code
Typing.InvalidShapeRemoveKey
)
2345 "You can only unset fields of local variables"
2347 let unification_cycle pos ty
=
2349 (Typing.err_code
Typing.UnificationCycle
)
2352 "Type circularity: in order to type-check this expression it "
2353 ^
"is necessary for a type [rec] to be equal to type "
2357 let violated_constraint
2358 p_cstr
(p_tparam
, tparam
) left right
(on_error
: typing_error_callback
) =
2360 ~code
:(Typing.err_code
Typing.TypeConstraintViolation
)
2362 (p_cstr
, "Some type constraint(s) are violated here");
2363 (p_tparam
, Printf.sprintf
"%s is a constrained type parameter" tparam
);
2368 let method_variance pos =
2370 (Typing.err_code
Typing.MethodVariance
)
2372 "Covariance or contravariance is not allowed in type parameter of method or function."
2374 let explain_constraint ~use_pos ~definition_pos ~param_name
msgl =
2375 let inst_msg = "Some type constraint(s) here are violated" in
2376 (* There may be multiple constraints instantiated at one spot; avoid
2377 * duplicating the instantiation message *)
2380 | (p, x) :: rest
when String.equal x inst_msg && Pos.equal p use_pos
-> rest
2383 let name = strip_ns param_name
in
2385 (Typing.err_code
Typing.TypeConstraintViolation
)
2387 (use_pos
, inst_msg);
2388 (definition_pos
, "'" ^
name ^
"' is a constrained type parameter");
2392 let explain_where_constraint ~in_class ~use_pos ~definition_pos
msgl =
2399 let definition_head =
2400 Printf.sprintf
"This is the %s with 'where' type constraints" callsite_ty
2402 let inst_msg = "A 'where' type constraint is violated here" in
2404 (Typing.err_code
Typing.TypeConstraintViolation
)
2405 ([(use_pos
, inst_msg); (definition_pos
, definition_head)] @ msgl)
2407 let explain_tconst_where_constraint ~use_pos ~definition_pos
msgl =
2408 let inst_msg = "A 'where' type constraint is violated here" in
2410 (Typing.err_code
Typing.TypeConstraintViolation
)
2412 (use_pos
, inst_msg);
2414 "This method's where constraints contain a generic type access" );
2418 let format_string pos snippet
s class_pos fname class_suggest
=
2420 (Typing.err_code
Typing.FormatString
)
2422 (pos, "Invalid format string " ^ snippet ^
" in \"" ^
s ^
"\"");
2424 "You can add a new format specifier by adding "
2430 let expected_literal_format_string pos =
2432 (Typing.err_code
Typing.ExpectedLiteralFormatString
)
2434 "This argument must be a literal format string"
2436 let re_prefixed_non_string pos non_strings
=
2438 (Typing.err_code
Typing.RePrefixedNonString
)
2440 (non_strings ^
" are not allowed to be to be `re`-prefixed")
2442 let bad_regex_pattern pos s =
2444 (Typing.err_code
Typing.BadRegexPattern
)
2446 ("Bad regex pattern; " ^
s ^
".")
2448 let generic_array_strict p =
2450 (Typing.err_code
Typing.GenericArrayStrict
)
2452 "You cannot have an array without generics in strict mode"
2454 let option_return_only_typehint p kind
=
2455 let (typehint
, reason) =
2457 | `void
-> ("?void", "only return implicitly")
2458 | `noreturn
-> ("?noreturn", "never return")
2461 (Typing.err_code
Typing.OptionReturnOnlyTypehint
)
2464 ^
" is a nonsensical typehint; a function cannot both "
2466 ^
" and return null." )
2468 let tuple_syntax p =
2470 (Typing.err_code
Typing.TupleSyntax
)
2472 "Did you want a tuple? Try (X,Y), not tuple<X,Y>"
2474 let redeclaring_missing_method p trait_method
=
2476 (Typing.err_code
Typing.RedeclaringMissingMethod
)
2478 ( "Attempting to redeclare a trait method "
2480 ^
" which was never inherited. "
2481 ^
"You might be trying to redeclare a non-static method as static or vice-versa."
2484 let expecting_type_hint p =
2485 add
(Typing.err_code
Typing.ExpectingTypeHint
) p "Was expecting a type hint"
2487 let expecting_type_hint_variadic p =
2489 (Typing.err_code
Typing.ExpectingTypeHintVariadic
)
2491 "Was expecting a type hint on this variadic parameter"
2493 let expecting_return_type_hint p =
2495 (Typing.err_code
Typing.ExpectingReturnTypeHint
)
2497 "Was expecting a return type hint"
2499 let expecting_awaitable_return_type_hint p =
2501 (Typing.err_code
Typing.ExpectingAwaitableReturnTypeHint
)
2503 "Was expecting an Awaitable return type hint"
2505 let duplicate_using_var pos =
2507 (Typing.err_code
Typing.DuplicateUsingVar
)
2509 "Local variable already used in 'using' statement"
2511 let illegal_disposable pos verb
=
2513 (Typing.err_code
Typing.IllegalDisposable
)
2515 ("Disposable objects must only be " ^ verb ^
" in a 'using' statement")
2517 let escaping_disposable pos =
2519 (Typing.err_code
Typing.EscapingDisposable
)
2521 "Variable from 'using' clause may only be used as receiver in method invocation or passed to function with <<__AcceptDisposable>> parameter attribute"
2523 let escaping_disposable_parameter pos =
2525 (Typing.err_code
Typing.EscapingDisposableParameter
)
2527 "Parameter with <<__AcceptDisposable>> attribute may only be used as receiver in method invocation or passed to another function with <<__AcceptDisposable>> parameter attribute"
2529 let escaping_this pos =
2531 (Typing.err_code
Typing.EscapingThis
)
2533 "$this implementing IDisposable or IAsyncDisposable may only be used as receiver in method invocation or passed to another function with <<__AcceptDisposable>> parameter attribute"
2535 let escaping_mutable_object pos =
2537 (Typing.err_code
Typing.EscapingMutableObject
)
2539 "Neither a Mutable nor MaybeMutable object may be captured by an anonymous function."
2541 let must_extend_disposable pos =
2543 (Typing.err_code
Typing.MustExtendDisposable
)
2545 "A disposable type may not extend a class or use a trait that is not disposable"
2547 let accept_disposable_invariant pos1 pos2
(on_error
: typing_error_callback
) =
2548 let msg1 = (pos1
, "This parameter is marked <<__AcceptDisposable>>") in
2549 let msg2 = (pos2
, "This parameter is not marked <<__AcceptDisposable>>") in
2550 on_error ~code
:(Typing.err_code
Typing.AcceptDisposableInvariant
) [msg1; msg2]
2552 let field_kinds pos1 pos2
=
2554 (Typing.err_code
Typing.FieldKinds
)
2556 (pos1
, "You cannot use this kind of field (value)");
2557 (pos2
, "Mixed with this kind of field (key => value)");
2560 let unbound_name_typing pos name =
2562 (Typing.err_code
Typing.UnboundNameTyping
)
2564 ("Unbound name (typing): " ^
strip_ns name)
2566 let previous_default p =
2568 (Typing.err_code
Typing.PreviousDefault
)
2570 ( "A previous parameter has a default value.\n"
2571 ^
"Remove all the default values for the preceding parameters,\n"
2572 ^
"or add a default value to this one." )
2574 let return_only_typehint p kind
=
2578 | `noreturn
-> "noreturn"
2581 (Naming.err_code
Naming.ReturnOnlyTypehint
)
2585 ^
" typehint can only be used to describe a function return type" )
2587 let unexpected_type_arguments p =
2589 (Naming.err_code
Naming.UnexpectedTypeArguments
)
2591 "Type arguments are not expected for this type"
2593 let too_many_type_arguments p =
2595 (Naming.err_code
Naming.TooManyTypeArguments
)
2597 "Too many type arguments for this type"
2599 let return_in_void pos1 pos2
=
2601 (Typing.err_code
Typing.ReturnInVoid
)
2602 [(pos1
, "You cannot return a value"); (pos2
, "This is a void function")]
2604 let this_var_outside_class p =
2606 (Typing.err_code
Typing.ThisVarOutsideClass
)
2608 "Can't use $this outside of a class"
2610 let unbound_global cst_pos
=
2612 (Typing.err_code
Typing.UnboundGlobal
)
2614 "Unbound global constant (Typing)"
2616 let private_inst_meth ~def_pos ~use_pos
=
2618 (Typing.err_code
Typing.PrivateInstMeth
)
2621 "You cannot use this method with inst_meth (whether you are in the same class or not)."
2623 (def_pos
, "It is declared as private here");
2626 let protected_inst_meth ~def_pos ~use_pos
=
2628 (Typing.err_code
Typing.ProtectedInstMeth
)
2631 "You cannot use this method with inst_meth (whether you are in the same class hierarchy or not)."
2633 (def_pos
, "It is declared as protected here");
2636 let private_class_meth ~def_pos ~use_pos
=
2638 (Typing.err_code
Typing.PrivateClassMeth
)
2641 "You cannot use this method with class_meth (whether you are in the same class or not)."
2643 (def_pos
, "It is declared as private here");
2646 let protected_class_meth ~def_pos ~use_pos
=
2648 (Typing.err_code
Typing.ProtectedClassMeth
)
2651 "You cannot use this method with class_meth (whether you are in the same class hierarchy or not)."
2653 (def_pos
, "It is declared as protected here");
2656 let array_cast pos =
2658 (Typing.err_code
Typing.ArrayCast
)
2660 "(array) cast forbidden; arrays with unspecified key and value types are not allowed"
2662 let string_cast pos ty
=
2663 add
(Typing.err_code
Typing.StringCast
) pos
2665 "Cannot cast a value of type %s to string.\nOnly primitives may be used in a (string) cast.\nIf you are trying to cast a Stringish type, please use `stringish_cast`.\nThis functionality is being removed from HHVM."
2668 let nullable_cast pos ty ty_pos
=
2670 (Typing.err_code
Typing.NullableCast
)
2672 (pos, "Casting from a nullable type is forbidden");
2673 (ty_pos
, "This is " ^ ty
);
2676 let static_outside_class pos =
2678 (Typing.err_code
Typing.StaticOutsideClass
)
2680 "'static' is undefined outside of a class"
2682 let self_outside_class pos =
2684 (Typing.err_code
Typing.SelfOutsideClass
)
2686 "'self' is undefined outside of a class"
2688 let new_inconsistent_construct new_pos
(cpos
, cname) kind
=
2689 let name = strip_ns cname in
2692 | `static
-> "Can't use new static() for " ^
name
2693 | `classname
-> "Can't use new on classname<" ^
name ^
">"
2696 (Typing.err_code
Typing.NewStaticInconsistent
)
2700 ^
"; __construct arguments are not guaranteed to be consistent in child classes"
2703 "This declaration is neither final nor uses the <<__ConsistentConstruct>> attribute"
2707 let undefined_parent pos =
2709 (Typing.err_code
Typing.UndefinedParent
)
2711 "The parent class is undefined"
2713 let parent_outside_class pos =
2715 (Typing.err_code
Typing.ParentOutsideClass
)
2717 "'parent' is undefined outside of a class"
2719 let parent_abstract_call meth_name call_pos decl_pos
=
2721 (Typing.err_code
Typing.AbstractCall
)
2723 (call_pos
, "Cannot call parent::" ^ meth_name ^
"(); it is abstract");
2724 (decl_pos
, "Declaration is here");
2727 let self_abstract_call meth_name call_pos decl_pos
=
2729 (Typing.err_code
Typing.AbstractCall
)
2732 "Cannot call self::"
2734 ^
"(); it is abstract. Did you mean static::"
2737 (decl_pos
, "Declaration is here");
2740 let classname_abstract_call cname meth_name call_pos decl_pos
=
2741 let cname = strip_ns cname in
2743 (Typing.err_code
Typing.AbstractCall
)
2746 "Cannot call " ^
cname ^
"::" ^ meth_name ^
"(); it is abstract" );
2747 (decl_pos
, "Declaration is here");
2750 let static_synthetic_method cname meth_name call_pos decl_pos
=
2751 let cname = strip_ns cname in
2753 (Typing.err_code
Typing.StaticSyntheticMethod
)
2762 ^
" is not defined in "
2764 (decl_pos
, "Declaration is here");
2767 let isset_in_strict pos =
2769 (Typing.err_code
Typing.IssetEmptyInStrict
)
2771 ( "isset tends to hide errors due to variable typos and so is limited to dynamic checks in "
2774 let unset_nonidx_in_strict pos msgs =
2776 (Typing.err_code
Typing.UnsetNonidxInStrict
)
2779 "In strict mode, unset is banned except on dynamic, "
2780 ^
"darray, keyset, or dict indexing" );
2784 let unpacking_disallowed_builtin_function pos name =
2785 let name = strip_ns name in
2787 (Typing.err_code
Typing.UnpackingDisallowed
)
2789 ("Arg unpacking is disallowed for " ^
name)
2791 let invalid_destructure pos1 pos2 ty
(on_error
: typing_error_callback
) =
2793 ~code
:(Typing.err_code
Typing.InvalidDestructure
)
2796 "This expression cannot be destructured with a list(...) expression" );
2797 (pos2
, "This is " ^ ty
);
2800 let unpack_array_required_argument p fp
(on_error
: typing_error_callback
) =
2802 ~code
:(Typing.err_code
Typing.SplatArrayRequired
)
2805 "An array cannot be unpacked into the required arguments of a function"
2807 (fp
, "Definition is here");
2810 let unpack_array_variadic_argument p fp
(on_error
: typing_error_callback
) =
2812 ~code
:(Typing.err_code
Typing.SplatArrayRequired
)
2815 "A function that receives an unpacked array as an argument must have a variadic parameter to accept the elements of the array"
2817 (fp
, "Definition is here");
2820 let array_get_arity pos1
name pos2
=
2822 (Typing.err_code
Typing.ArrayGetArity
)
2824 (pos1
, "You cannot use this " ^
strip_ns name);
2825 (pos2
, "It is missing its type parameters");
2828 let typing_error pos msg = add
(Typing.err_code
Typing.GenericUnify
) pos msg
2830 let undefined_field ~use_pos ~
name ~shape_type_pos
=
2832 (Typing.err_code
Typing.UndefinedField
)
2834 (use_pos
, "The field " ^
name ^
" is undefined");
2835 (shape_type_pos
, "Definition is here");
2838 let array_access code pos1 pos2 ty
=
2840 (Typing.err_code code
)
2841 ( (pos1
, "This is not an object of type KeyedContainer, this is " ^ ty
)
2843 ( if not
(phys_equal pos2
Pos.none
) then
2844 [(pos2
, "Definition is here")]
2848 let array_access_read = array_access Typing.ArrayAccessRead
2850 let array_access_write = array_access Typing.ArrayAccessWrite
2852 let keyset_set pos1 pos2
=
2854 (Typing.err_code
Typing.KeysetSet
)
2855 ( (pos1
, "Elements in a keyset cannot be assigned, use append instead.")
2857 ( if not
(phys_equal pos2
Pos.none
) then
2858 [(pos2
, "Definition is here")]
2862 let array_append pos1 pos2 ty
=
2864 (Typing.err_code
Typing.ArrayAppend
)
2865 ( (pos1
, ty ^
" does not allow array append")
2867 ( if not
(phys_equal pos2
Pos.none
) then
2868 [(pos2
, "Definition is here")]
2872 let const_mutation pos1 pos2 ty
=
2874 (Typing.err_code
Typing.ConstMutation
)
2875 ( (pos1
, "You cannot mutate this")
2877 ( if not
(phys_equal pos2
Pos.none
) then
2878 [(pos2
, "This is " ^ ty
)]
2882 let expected_class ?
(suffix
= "") pos =
2884 (Typing.err_code
Typing.ExpectedClass
)
2886 ("Was expecting a class" ^ suffix
)
2888 let unknown_type description
pos r
=
2889 let msg = "Was expecting " ^ description ^
" but type is unknown" in
2890 add_list
(Typing.err_code
Typing.UnknownType
) ([(pos, msg)] @ r
)
2892 let not_found_hint = function
2894 | `closest
(_pos
, v
) -> Printf.sprintf
" (did you mean static method '%s'?)" v
2895 | `did_you_mean
(_pos
, v
) -> Printf.sprintf
" (did you mean '%s'?)" v
2897 let snot_found_hint = function
2899 | `closest
(_pos
, v
) ->
2900 Printf.sprintf
" (did you mean instance method '%s'?)" v
2901 | `did_you_mean
(_pos
, v
) -> Printf.sprintf
" (did you mean '%s'?)" v
2903 let string_of_class_member_kind = function
2904 | `class_constant
-> "class constant"
2905 | `static_method
-> "static method"
2906 | `class_variable
-> "class variable"
2907 | `class_typeconst
-> "type constant"
2909 let smember_not_found
2915 (on_error
: typing_error_callback
) =
2916 let kind = string_of_class_member_kind kind in
2917 let class_name = strip_ns class_name in
2918 let msg = Printf.sprintf
"No %s '%s' in %s" kind member_name
class_name in
2920 ~code
:(Typing.err_code
Typing.SmemberNotFound
)
2922 (pos, msg ^
snot_found_hint hint
);
2923 (cpos
, "Declaration of " ^
class_name ^
" is here");
2926 let member_not_found
2933 (on_error
: typing_error_callback
) =
2934 let type_name = strip_ns type_name in
2937 | `method_
-> "method"
2938 | `property
-> "property"
2940 let msg = Printf.sprintf
"No %s '%s' in %s" kind member_name
type_name in
2942 ~code
:(Typing.err_code
Typing.MemberNotFound
)
2943 ( (pos, msg ^
not_found_hint hint
)
2944 :: (reason @ [(cpos
, "Declaration of " ^
type_name ^
" is here")]) )
2946 let parent_in_trait pos =
2948 (Typing.err_code
Typing.ParentInTrait
)
2950 ( "parent:: inside a trait is undefined"
2951 ^
" without 'require extends' of a class defined in <?hh" )
2953 let parent_undefined pos =
2954 add
(Typing.err_code
Typing.ParentUndefined
) pos "parent is undefined"
2956 let constructor_no_args pos =
2958 (Typing.err_code
Typing.ConstructorNoArgs
)
2960 "This constructor expects no argument"
2962 let visibility p msg1 p_vis
msg2 =
2963 add_list
(Typing.err_code
Typing.Visibility
) [(p, msg1); (p_vis
, msg2)]
2965 let typing_too_many_args expected actual
pos pos_def on_error
=
2968 (Typing.err_code
Typing.TypingTooManyArgs
)
2972 "Too many arguments (expected %d but got %d)"
2975 (pos_def
, "Definition is here");
2978 let typing_too_few_args required actual
pos pos_def on_error
=
2981 (Typing.err_code
Typing.TypingTooFewArgs
)
2985 "Too few arguments (required %d but got %d)"
2988 (pos_def
, "Definition is here");
2991 let bad_call pos ty
=
2993 (Typing.err_code
Typing.BadCall
)
2995 ("This call is invalid, this is not a function, it is " ^ ty
)
2997 let extend_final extend_pos decl_pos
name =
2998 let name = strip_ns name in
3000 (Typing.err_code
Typing.ExtendFinal
)
3002 (extend_pos
, "You cannot extend final class " ^
name);
3003 (decl_pos
, "Declaration is here");
3006 let extend_non_abstract_record name extend_pos decl_pos
=
3007 let name = strip_ns name in
3009 Printf.sprintf
"Cannot extend record `%s` because it isn't abstract" name
3012 (Typing.err_code
Typing.ExtendFinal
)
3013 [(extend_pos
, msg); (decl_pos
, "Declaration is here")]
3015 let extend_sealed child_pos parent_pos parent_name parent_kind verb
=
3016 let name = strip_ns parent_name
in
3018 (Typing.err_code
Typing.ExtendSealed
)
3020 (child_pos
, "You cannot " ^ verb ^
" sealed " ^ parent_kind ^
" " ^
name);
3021 (parent_pos
, "Declaration is here");
3024 let trait_prop_const_class pos x =
3026 (Typing.err_code
Typing.TraitPropConstClass
)
3028 ( "Trait declaration of non-const property "
3030 ^
" is incompatible with a const class" )
3040 let name = strip_ns parent_name
in
3042 if child_is_ppl
then
3044 ^
" annotated with <<__PPL>> cannot "
3052 ^
" must be annotated with <<__PPL>> to "
3060 (Typing.err_code
Typing.ExtendPPL
)
3061 [(child_pos
, warning); (parent_pos
, "Declaration is here")]
3063 let read_before_write (pos, v
) =
3065 (Typing.err_code
Typing.ReadBeforeWrite
)
3067 (Utils.sl
["Read access to $this->"; v
; " before initialization"])
3069 let final_property pos =
3071 (Typing.err_code
Typing.FinalProperty
)
3073 "Properties cannot be declared final"
3075 let implement_abstract ~is_final pos1 pos2
kind x =
3076 let name = "abstract " ^
kind ^
" '" ^
x ^
"'" in
3079 "This class was declared as final. It must provide an implementation for the "
3082 "This class must be declared abstract, or provide an implementation for the "
3086 (Typing.err_code
Typing.ImplementAbstract
)
3087 [(pos1
, msg1); (pos2
, "Declaration is here")]
3089 let generic_static pos x =
3091 (Typing.err_code
Typing.GenericStatic
)
3093 ("This static variable cannot use the type parameter " ^
x ^
".")
3095 let fun_too_many_args pos1 pos2
(on_error
: typing_error_callback
) =
3097 ~code
:(Typing.err_code
Typing.FunTooManyArgs
)
3099 (pos1
, "Too many mandatory arguments");
3100 (pos2
, "Because of this definition");
3103 let fun_too_few_args pos1 pos2
(on_error
: typing_error_callback
) =
3105 ~code
:(Typing.err_code
Typing.FunTooFewArgs
)
3106 [(pos1
, "Too few arguments"); (pos2
, "Because of this definition")]
3108 let fun_unexpected_nonvariadic pos1 pos2
(on_error
: typing_error_callback
) =
3110 ~code
:(Typing.err_code
Typing.FunUnexpectedNonvariadic
)
3112 (pos1
, "Should have a variadic argument");
3113 (pos2
, "Because of this definition");
3116 let fun_variadicity_hh_vs_php56 pos1 pos2
(on_error
: typing_error_callback
) =
3118 ~code
:(Typing.err_code
Typing.FunVariadicityHhVsPhp56
)
3120 (pos1
, "Variadic arguments: ...-style is not a subtype of ...$args");
3121 (pos2
, "Because of this definition");
3124 let ellipsis_strict_mode ~require
pos =
3128 "Cannot use ... without a type hint in strict mode. Please add a type hint."
3130 "Cannot use ... without a parameter name in strict mode. Please add a parameter name."
3131 | `Type_and_param_name
->
3132 "Cannot use ... without a type hint and parameter name in strict mode. Please add a type hint and parameter name."
3134 add
(Typing.err_code
Typing.EllipsisStrictMode
) pos msg
3136 let untyped_lambda_strict_mode pos =
3138 "Cannot determine types of lambda parameters in strict mode. Please add type hints on parameters."
3140 add
(Typing.err_code
Typing.UntypedLambdaStrictMode
) pos msg
3142 let echo_in_reactive_context pos =
3144 (Typing.err_code
Typing.EchoInReactiveContext
)
3146 "'echo' or 'print' are not allowed in reactive functions."
3149 ~use_pos ~definition_pos n
(on_error
: typing_error_callback
option) =
3156 | 0 -> "no type parameter"
3157 | 1 -> "a type parameter"
3158 | n
-> string_of_int n ^
" type parameters" );
3159 (definition_pos
, "Definition is here");
3162 on_error_or_add on_error
(Typing.err_code
Typing.ExpectedTparam
) errl
3164 let object_string pos1 pos2
=
3166 (Typing.err_code
Typing.ObjectString
)
3168 (pos1
, "You cannot use this object as a string");
3169 (pos2
, "This object doesn't implement __toString");
3172 let object_string_deprecated pos =
3174 (Typing.err_code
Typing.ObjectString
)
3176 "You cannot use this object as a string\nImplicit conversions of Stringish objects to string are deprecated."
3178 let cyclic_typedef def_pos use_pos
=
3180 (Typing.err_code
Typing.CyclicTypedef
)
3181 [(def_pos
, "Cyclic type definition"); (use_pos
, "Cyclic use is here")]
3183 let type_arity_mismatch pos1 n1 pos2 n2
(on_error
: typing_error_callback
) =
3185 ~code
:(Typing.err_code
Typing.TypeArityMismatch
)
3186 [(pos1
, "This type has " ^ n1 ^
" arguments"); (pos2
, "This one has " ^ n2
)]
3188 let this_final id pos2
=
3189 let n = strip_ns (snd id
) in
3190 let message1 = "Since " ^
n ^
" is not final" in
3191 let message2 = "this might not be a " ^
n in
3192 [(fst id
, message1); (pos2
, message2)]
3194 let exact_class_final id pos2
=
3195 let n = strip_ns (snd id
) in
3196 let message1 = "This requires the late-bound type to be exactly " ^
n in
3198 "Since " ^
n ^
" is not final this might be an instance of a child class"
3200 [(fst id
, message1); (pos2
, message2)]
3202 let fun_arity_mismatch pos1 pos2
(on_error
: typing_error_callback
) =
3204 ~code
:(Typing.err_code
Typing.FunArityMismatch
)
3206 (pos1
, "Number of arguments doesn't match");
3207 (pos2
, "Because of this definition");
3210 let fun_reactivity_mismatch
3211 pos1 kind1 pos2 kind2
(on_error
: typing_error_callback
) =
3212 let f k
= "This function is " ^ k ^
"." in
3214 ~code
:(Typing.err_code
Typing.FunReactivityMismatch
)
3215 [(pos1
, f kind1
); (pos2
, f kind2
)]
3217 let inconsistent_mutability pos1 mut1 p2_opt
=
3219 | Some
(pos2
, mut2
) ->
3221 (Typing.err_code
Typing.InconsistentMutability
)
3224 "Inconsistent mutability of local variable, here local is " ^ mut1
);
3225 (pos2
, "But here it is " ^ mut2
);
3229 (Typing.err_code
Typing.InconsistentMutability
)
3231 ("Local is " ^ mut1 ^
" in one scope and immutable in another.")
3233 let inconsistent_mutability_for_conditional p_mut p_other
=
3235 (Typing.err_code
Typing.InconsistentMutability
)
3238 "Inconsistent mutability of conditional expression, this branch returns owned mutable value"
3240 (p_other
, "But this one does not.");
3243 let invalid_mutability_flavor pos mut1 mut2
=
3245 (Typing.err_code
Typing.InvalidMutabilityFlavorInAssignment
)
3251 ^
" local variable. Mutability flavor of local variable cannot be altered."
3254 let reassign_mutable_var ~in_collection pos1
=
3256 if in_collection
then
3257 "This variable is mutable. You cannot create a new reference to it by putting it into the collection."
3259 "This variable is mutable. You cannot create a new reference to it."
3261 add
(Typing.err_code
Typing.ReassignMutableVar
) pos1
msg
3263 let reassign_mutable_this ~in_collection ~is_maybe_mutable pos1
=
3265 if is_maybe_mutable
then
3271 if in_collection
then
3274 ^
". You cannot create a new reference to it by putting it into the collection."
3276 "$this here is " ^
kind ^
". You cannot create a new reference to it."
3278 add
(Typing.err_code
Typing.ReassignMutableThis
) pos1
msg
3280 let mutable_expression_as_multiple_mutable_arguments
3281 pos param_kind prev_pos prev_param_kind
=
3283 (Typing.err_code
Typing.MutableExpressionAsMultipleMutableArguments
)
3286 "A mutable expression may not be passed as multiple arguments where at least one matching parameter is mutable. Matching parameter here is "
3289 "This is where it was used before, being passed as " ^ prev_param_kind
3293 let reassign_maybe_mutable_var ~in_collection pos1
=
3295 if in_collection
then
3296 "This variable is maybe mutable. You cannot create a new reference to it by putting it into the collection."
3298 "This variable is maybe mutable. You cannot create a new reference to it."
3300 add
(Typing.err_code
Typing.ReassignMaybeMutableVar
) pos1
msg
3302 let mutable_call_on_immutable fpos pos1 rx_mutable_hint_pos
=
3304 match rx_mutable_hint_pos
with
3308 "Consider wrapping this expression with Rx\\mutable to forward mutability."
3314 (pos1
, "Cannot call mutable function on immutable expression")
3316 "This function is marked <<__Mutable>>, so it has a mutable $this." )
3319 add_list
(Typing.err_code
Typing.MutableCallOnImmutable
) l
3321 let immutable_call_on_mutable fpos pos1
=
3323 (Typing.err_code
Typing.ImmutableCallOnMutable
)
3325 (pos1
, "Cannot call non-mutable function on mutable expression");
3326 (fpos
, "This function is not marked as <<__Mutable>>.");
3329 let mutability_mismatch
3330 ~is_receiver pos1 mut1 pos2 mut2
(on_error
: typing_error_callback
) =
3334 "Receiver of this function"
3341 ~code
:(Typing.err_code
Typing.MutabilityMismatch
)
3342 [(pos1
, "Incompatible mutabilities:"); (pos1
, msg mut1
); (pos2
, msg mut2
)]
3344 let invalid_call_on_maybe_mutable ~fun_is_mutable
pos fpos
=
3347 ^
( if fun_is_mutable
then
3351 ^
" function on maybe mutable value."
3354 (Typing.err_code
Typing.InvalidCallMaybeMutable
)
3355 [(pos, msg); (fpos
, "This function is not marked as <<__MaybeMutable>>.")]
3357 let mutable_argument_mismatch param_pos arg_pos
=
3359 (Typing.err_code
Typing.MutableArgumentMismatch
)
3361 (arg_pos
, "Invalid argument");
3362 (param_pos
, "This parameter is marked mutable");
3363 (arg_pos
, "But this expression is not");
3366 let immutable_argument_mismatch param_pos arg_pos
=
3368 (Typing.err_code
Typing.ImmutableArgumentMismatch
)
3370 (arg_pos
, "Invalid argument");
3371 (param_pos
, "This parameter is not marked as mutable");
3372 (arg_pos
, "But this expression is mutable");
3375 let mutably_owned_argument_mismatch ~arg_is_owned_local param_pos arg_pos
=
3377 if arg_is_owned_local
then
3378 "Owned mutable locals used as argument should be passed via Rx\\move function"
3380 "But this expression is not owned mutable"
3383 (Typing.err_code
Typing.ImmutableArgumentMismatch
)
3385 (arg_pos
, "Invalid argument");
3386 (param_pos
, "This parameter is marked with <<__OwnedMutable>>");
3390 let maybe_mutable_argument_mismatch param_pos arg_pos
=
3392 (Typing.err_code
Typing.MaybeMutableArgumentMismatch
)
3394 (arg_pos
, "Invalid argument");
3395 (param_pos
, "This parameter is not marked <<__MaybeMutable>>");
3396 (arg_pos
, "But this expression is maybe mutable");
3399 let invalid_mutable_return_result error_pos function_pos value_kind
=
3401 (Typing.err_code
Typing.InvalidMutableReturnResult
)
3404 "Functions marked <<__MutableReturn>> must return mutably owned values: mutably owned local variables and results of calling Rx\\mutable."
3406 (function_pos
, "This function is marked <<__MutableReturn>>");
3407 (error_pos
, "This expression is " ^ value_kind
);
3410 let freeze_in_nonreactive_context pos1
=
3412 (Typing.err_code
Typing.FreezeInNonreactiveContext
)
3414 "\\HH\\Rx\\freeze can only be used in reactive functions"
3416 let mutable_in_nonreactive_context pos =
3418 (Typing.err_code
Typing.MutableInNonreactiveContext
)
3420 "\\HH\\Rx\\mutable can only be used in reactive functions"
3422 let move_in_nonreactive_context pos =
3424 (Typing.err_code
Typing.MoveInNonreactiveContext
)
3426 "\\HH\\Rx\\move can only be used in reactive functions"
3428 let invalid_argument_type_for_condition_in_rx
3429 ~is_receiver f_pos def_pos arg_pos
expected_type actual_type
=
3438 ^
" must be a subtype of "
3445 (Typing.err_code
Typing.InvalidConditionallyReactiveCall
)
3448 "Cannot invoke conditionally reactive function in reactive context, because at least one reactivity condition is not met."
3451 (def_pos
, "This is the function declaration");
3454 let callsite_reactivity_mismatch
3455 f_pos def_pos callee_reactivity cause_pos_opt caller_reactivity
=
3457 (Typing.err_code
Typing.CallSiteReactivityMismatch
)
3460 "Reactivity mismatch: "
3462 ^
" function cannot call "
3465 (def_pos
, "This is declaration of the function being called.");
3467 @ Option.value_map cause_pos_opt ~default
:[] ~
f:(fun cause_pos
->
3470 "Reactivity of this argument was used as reactivity of the callee."
3474 let invalid_argument_of_rx_mutable_function pos =
3476 (Typing.err_code
Typing.InvalidArgumentOfRxMutableFunction
)
3478 "Single argument to \\HH\\Rx\\mutable should be an expression that yields new mutably-owned value, like 'new A()', Hack collection literal or 'f()' where f is function annotated with <<__MutableReturn>> attribute."
3480 let invalid_freeze_use pos1
=
3482 (Typing.err_code
Typing.InvalidFreezeUse
)
3484 "freeze takes a single mutably-owned local variable as an argument"
3486 let invalid_move_use pos1
=
3488 (Typing.err_code
Typing.InvalidMoveUse
)
3490 "move takes a single mutably-owned local variable as an argument"
3492 let require_args_reify def_pos arg_pos
=
3494 (Typing.err_code
Typing.RequireArgsReify
)
3497 "All type arguments must be specified because a type parameter is reified"
3499 (def_pos
, "Definition is here");
3502 let require_generic_explicit (def_pos
, def_name
) arg_pos
=
3504 (Typing.err_code
Typing.RequireGenericExplicit
)
3507 "Generic type parameter " ^ def_name ^
" must be specified explicitly"
3509 (def_pos
, "Definition is here");
3512 let invalid_reified_argument (def_pos
, def_name
) hint_pos arg_pos arg_kind
=
3514 (Typing.err_code
Typing.InvalidReifiedArgument
)
3516 (hint_pos
, "Invalid reified hint");
3518 "This is " ^ arg_kind ^
", it cannot be used as a reified type argument"
3520 (def_pos
, def_name ^
" is reified");
3523 let invalid_reified_argument_reifiable (def_pos
, def_name
) arg_pos ty_pos ty_msg
3526 (Typing.err_code
Typing.InvalidReifiedArgument
)
3528 (arg_pos
, "PHP arrays cannot be used as a reified type argument");
3529 (ty_pos
, String.capitalize ty_msg
);
3530 (def_pos
, def_name ^
" is reified");
3533 let new_static_class_reified pos =
3535 (Typing.err_code
Typing.NewStaticClassReified
)
3537 "Cannot call new static because the current class has reified generics"
3539 let class_get_reified pos =
3541 (Typing.err_code
Typing.ClassGetReified
)
3543 "Cannot access static properties on reified generics"
3545 let static_meth_with_class_reified_generic meth_pos generic_pos
=
3547 (Typing.err_code
Typing.StaticMethWithClassReifiedGeneric
)
3550 "Static methods cannot use generics reified at the class level. Try reifying them at the static method itself."
3552 (generic_pos
, "Class-level reified generic used here.");
3555 let consistent_construct_reified pos =
3557 (Typing.err_code
Typing.ConsistentConstructReified
)
3559 "This class or one of its ancestors is annotated with <<__ConsistentConstruct>>. It cannot have reified generics."
3561 let bad_function_pointer_construction pos =
3563 (Typing.err_code
Typing.BadFunctionPointerConstruction
)
3565 "Function pointers must be explicitly named"
3567 let reified_generics_not_allowed pos =
3569 (Typing.err_code
Typing.InvalidReifiedFunctionPointer
)
3571 "Creating function pointers with reified generics is not currently allowed"
3573 let new_without_newable pos name =
3575 (Typing.err_code
Typing.NewWithoutNewable
)
3578 ^
" cannot be used with `new` because it does not have the <<__Newable>> attribute"
3581 let invalid_freeze_target pos1 var_pos var_mutability_str
=
3583 (Typing.err_code
Typing.InvalidFreezeTarget
)
3585 (pos1
, "Invalid argument - freeze() takes a single mutable variable");
3586 (var_pos
, "This variable is " ^ var_mutability_str
);
3589 let invalid_move_target pos1 var_pos var_mutability_str
=
3591 (Typing.err_code
Typing.InvalidMoveTarget
)
3593 (pos1
, "Invalid argument - move() takes a single mutably-owned variable");
3594 (var_pos
, "This variable is " ^ var_mutability_str
);
3597 let discarded_awaitable pos1 pos2
=
3599 (Typing.err_code
Typing.DiscardedAwaitable
)
3602 "This expression is of type Awaitable, but it's "
3603 ^
"either being discarded or used in a dangerous way before "
3604 ^
"being awaited" );
3605 (pos2
, "This is why I think it is Awaitable");
3608 let unify_error ?code
errl =
3609 add_list
(Option.value code ~default
:(Typing.err_code
Typing.UnifyError
)) errl
3611 let unify_error_at pos ?code
errl =
3612 unify_error ?code
((pos, "Typing error") :: errl)
3614 let maybe_unify_error specific_code ?code
errl =
3615 add_list
(Option.value code ~default
:(Typing.err_code specific_code
)) errl
3617 let index_type_mismatch = maybe_unify_error Typing.IndexTypeMismatch
3619 let expected_stringlike = maybe_unify_error Typing.ExpectedStringlike
3621 let type_constant_mismatch (on_error
: typing_error_callback
) ?code
errl =
3623 Option.value code ~default
:(Typing.err_code
Typing.TypeConstantMismatch
)
3627 let class_constant_type_mismatch (on_error
: typing_error_callback
) ?
code errl =
3631 ~default
:(Typing.err_code
Typing.ClassConstantTypeMismatch
)
3635 let constant_does_not_match_enum_type =
3636 maybe_unify_error Typing.ConstantDoesNotMatchEnumType
3638 let enum_underlying_type_must_be_arraykey =
3639 maybe_unify_error Typing.EnumUnderlyingTypeMustBeArraykey
3641 let enum_constraint_must_be_arraykey =
3642 maybe_unify_error Typing.EnumConstraintMustBeArraykey
3644 let enum_subtype_must_have_compatible_constraint =
3645 maybe_unify_error Typing.EnumSubtypeMustHaveCompatibleConstraint
3647 let parameter_default_value_wrong_type =
3648 maybe_unify_error Typing.ParameterDefaultValueWrongType
3650 let newtype_alias_must_satisfy_constraint =
3651 maybe_unify_error Typing.NewtypeAliasMustSatisfyConstraint
3653 let bad_function_typevar = maybe_unify_error Typing.BadFunctionTypevar
3655 let bad_class_typevar = maybe_unify_error Typing.BadClassTypevar
3657 let bad_method_typevar = maybe_unify_error Typing.BadMethodTypevar
3659 let missing_return = maybe_unify_error Typing.MissingReturnInNonVoidFunction
3661 let inout_return_type_mismatch =
3662 maybe_unify_error Typing.InoutReturnTypeMismatch
3664 let class_constant_value_does_not_match_hint =
3665 maybe_unify_error Typing.ClassConstantValueDoesNotMatchHint
3667 let class_property_initializer_type_does_not_match_hint =
3668 maybe_unify_error Typing.ClassPropertyInitializerTypeDoesNotMatchHint
3670 let xhp_attribute_does_not_match_hint =
3671 maybe_unify_error Typing.XhpAttributeValueDoesNotMatchHint
3673 let pocket_universes_typing = maybe_unify_error Typing.PocketUniversesTyping
3675 let record_init_value_does_not_match_hint =
3676 maybe_unify_error Typing.RecordInitValueDoesNotMatchHint
3678 let elt_type_to_string = function
3679 | `Method
-> "method"
3680 | `Property
-> "property"
3682 let static_redeclared_as_dynamic
3683 dyn_position static_position member_name ~elt_type
=
3689 let elt_type = elt_type_to_string elt_type in
3696 ^
" is declared here as non-static"
3699 "But it conflicts with an inherited static declaration here"
3702 (Typing.err_code
Typing.StaticDynamic
)
3703 [(dyn_position
, msg_dynamic); (static_position
, msg_static)]
3705 let dynamic_redeclared_as_static
3706 static_position dyn_position member_name ~
elt_type =
3712 let elt_type = elt_type_to_string elt_type in
3719 ^
" is declared here as static"
3722 "But it conflicts with an inherited non-static declaration here"
3725 (Typing.err_code
Typing.StaticDynamic
)
3726 [(static_position
, msg_static); (dyn_position
, msg_dynamic)]
3728 let null_member code ~is_method
s pos r
=
3731 "You are trying to access the %s '%s' but this object can be null."
3738 add_list
(Typing.err_code
code) ([(pos, msg)] @ r
)
3740 let null_member_read = null_member Typing.NullMemberRead
3742 let null_member_write = null_member Typing.NullMemberWrite
3744 (* Trying to access a member on a mixed or nonnull value. *)
3745 let top_member null_code nonnull_code ~is_method ~is_nullable
s pos1 ty pos2
=
3748 "You are trying to access the %s '%s' but this is %s. Use a specific class or interface name."
3758 ( if is_nullable
then
3762 [(pos1
, msg); (pos2
, "Definition is here")]
3764 let top_member_read =
3765 top_member Typing.NullMemberRead
Typing.NonObjectMemberRead
3767 let top_member_write =
3768 top_member Typing.NullMemberWrite
Typing.NonObjectMemberWrite
3770 let non_object_member
3771 code ~is_method
s pos1 ty pos2
(on_error
: typing_error_callback
) =
3774 "You are trying to access the %s '%s' but this is %s"
3783 if String.equal ty
"a shape" then
3784 msg_start ^
". Did you mean $foo['" ^
s ^
"'] instead?"
3789 ~
code:(Typing.err_code
code)
3790 [(pos1
, msg); (pos2
, "Definition is here")]
3792 let non_object_member_read = non_object_member Typing.NonObjectMemberRead
3794 let non_object_member_write = non_object_member Typing.NonObjectMemberRead
3796 let unknown_object_member ~is_method
s pos r
=
3799 "You are trying to access the %s '%s' on a value whose class is unknown."
3806 add_list
(Typing.err_code
Typing.UnknownObjectMember
) ([(pos, msg)] @ r
)
3808 let non_class_member ~is_method
s pos1 ty pos2
=
3811 "You are trying to access the static %s '%s' but this is %s"
3820 (Typing.err_code
Typing.NonClassMember
)
3821 [(pos1
, msg); (pos2
, "Definition is here")]
3823 let ambiguous_member ~is_method
s pos1 ty pos2
=
3826 "You are trying to access the %s '%s' but there is more than one implementation on %s"
3835 (Typing.err_code
Typing.AmbiguousMember
)
3836 [(pos1
, msg); (pos2
, "Definition is here")]
3838 let null_container p null_witness
=
3840 (Typing.err_code
Typing.NullContainer
)
3843 "You are trying to access an element of this container"
3844 ^
" but the container could be null. " );
3848 let option_mixed pos =
3850 (Typing.err_code
Typing.OptionMixed
)
3852 "?mixed is a redundant typehint - just use mixed"
3854 let option_null pos =
3856 (Typing.err_code
Typing.OptionNull
)
3858 "?null is a redundant typehint - just use null"
3860 let declared_covariant pos1 pos2 emsg
=
3862 (Typing.err_code
Typing.DeclaredCovariant
)
3864 (pos2
, "Illegal usage of a covariant type parameter");
3865 (pos1
, "This is where the parameter was declared as covariant (+)");
3869 let declared_contravariant pos1 pos2 emsg
=
3871 (Typing.err_code
Typing.DeclaredContravariant
)
3873 (pos2
, "Illegal usage of a contravariant type parameter");
3874 (pos1
, "This is where the parameter was declared as contravariant (-)");
3878 let static_property_type_generic_param ~class_pos ~var_type_pos ~generic_pos
=
3880 (Typing.err_code
Typing.ClassVarTypeGenericParam
)
3883 "A generic parameter cannot be used in the type of a static property" );
3885 "This is where the type of the static property was declared" );
3886 (class_pos
, "This is the class containing the static property");
3889 let contravariant_this pos class_name tp
=
3891 (Typing.err_code
Typing.ContravariantThis
)
3893 ( "The \"this\" type cannot be used in this "
3894 ^
"contravariant position because its enclosing class \""
3897 ^
"is final and has a variant type parameter \""
3901 let cyclic_typeconst pos sl
=
3902 let sl = List.map
sl strip_ns in
3904 (Typing.err_code
Typing.CyclicTypeconst
)
3906 ("Cyclic type constant:\n " ^
String.concat ~sep
:" -> " sl)
3908 let abstract_concrete_override pos parent_pos
kind =
3911 | `method_
-> "method"
3912 | `typeconst
-> "type constant"
3913 | `constant
-> "constant"
3914 | `property
-> "property"
3917 (Typing.err_code
Typing.AbstractConcreteOverride
)
3919 (pos, "Cannot re-declare this " ^
kind_str ^
" as abstract");
3920 (parent_pos
, "Previously defined here");
3923 let required_field_is_optional pos1 pos2
name (on_error
: typing_error_callback
)
3926 ~
code:(Typing.err_code
Typing.RequiredFieldIsOptional
)
3928 (pos1
, "The field '" ^
name ^
"' is optional");
3929 (pos2
, "The field '" ^
name ^
"' is defined as required");
3932 let array_get_with_optional_field pos1 pos2
name =
3934 (Typing.err_code
Typing.ArrayGetWithOptionalField
)
3938 "The field `%s` may not be present in this shape. Use `Shapes::idx()` instead."
3940 (pos2
, "This is where the field was declared as optional.");
3943 let non_call_argument_in_suspend pos msgs =
3945 (Typing.err_code
Typing.NonCallArgumentInSuspend
)
3946 ( [(pos, "'suspend' operator expects call to a coroutine as an argument.")]
3949 let non_coroutine_call_in_suspend pos msgs =
3951 (Typing.err_code
Typing.NonCoroutineCallInSuspend
)
3954 "Only coroutine functions are allowed to be called in 'suspend' operator."
3959 let coroutine_call_outside_of_suspend pos =
3961 (Typing.err_code
Typing.CoroutineCallOutsideOfSuspend
)
3964 "Coroutine calls are only allowed when they are arguments to 'suspend' operator"
3968 let function_is_not_coroutine pos name =
3970 (Typing.err_code
Typing.FunctionIsNotCoroutine
)
3975 ^
"' is not a coroutine and cannot be used in as an argument of 'suspend' operator."
3979 let coroutinness_mismatch
3980 pos1_is_coroutine pos1 pos2
(on_error
: typing_error_callback
) =
3981 let m1 = "This is a coroutine." in
3982 let m2 = "This is not a coroutine." in
3984 ~
code:(Typing.err_code
Typing.CoroutinnessMismatch
)
3987 if pos1_is_coroutine
then
3992 if pos1_is_coroutine
then
3998 let invalid_ppl_call pos context
=
4000 "Cannot call a method on an object of a <<__PPL>> class " ^ context
4002 add
(Typing.err_code
Typing.InvalidPPLCall
) pos error_msg
4004 let invalid_ppl_static_call pos reason =
4006 "Cannot call a static method on a <<__PPL>> class " ^
reason
4008 add
(Typing.err_code
Typing.InvalidPPLStaticCall
) pos error_msg
4010 let ppl_meth_pointer pos func
=
4011 let error_msg = func ^
" cannot be used with a <<__PPL>> class" in
4012 add
(Typing.err_code
Typing.PPLMethPointer
) pos error_msg
4014 let coroutine_outside_experimental pos =
4016 (Typing.err_code
Typing.CoroutineOutsideExperimental
)
4018 Coroutine_errors.error_message
4020 let return_disposable_mismatch
4021 pos1_return_disposable pos1 pos2
(on_error
: typing_error_callback
) =
4022 let m1 = "This is marked <<__ReturnDisposable>>." in
4023 let m2 = "This is not marked <<__ReturnDisposable>>." in
4025 ~
code:(Typing.err_code
Typing.ReturnDisposableMismatch
)
4028 if pos1_return_disposable
then
4033 if pos1_return_disposable
then
4039 let return_void_to_rx_mismatch
4040 ~pos1_has_attribute pos1 pos2
(on_error
: typing_error_callback
) =
4041 let m1 = "This is marked <<__ReturnsVoidToRx>>." in
4042 let m2 = "This is not marked <<__ReturnsVoidToRx>>." in
4044 ~
code:(Typing.err_code
Typing.ReturnVoidToRxMismatch
)
4047 if pos1_has_attribute
then
4052 if pos1_has_attribute
then
4058 let this_as_lexical_variable pos =
4060 (Naming.err_code
Naming.ThisAsLexicalVariable
)
4062 "Cannot use $this as lexical variable"
4064 let dollardollar_lvalue pos =
4066 (Typing.err_code
Typing.DollardollarLvalue
)
4068 "Cannot assign a value to the special pipe variable ($$)"
4070 let mutating_const_property pos =
4072 (Typing.err_code
Typing.AssigningToConst
)
4074 "Cannot mutate a __Const property"
4076 let self_const_parent_not pos =
4078 (Typing.err_code
Typing.SelfConstParentNot
)
4080 "A __Const class may only extend other __Const classes"
4082 let overriding_prop_const_mismatch
4087 (on_error
: typing_error_callback
) =
4088 let m1 = "This property is __Const" in
4089 let m2 = "This property is not __Const" in
4091 ~
code:(Typing.err_code
Typing.OverridingPropConstMismatch
)
4099 if parent_const
then
4105 let mutable_return_result_mismatch
4106 pos1_has_mutable_return pos1 pos2
(on_error
: typing_error_callback
) =
4107 let m1 = "This is marked <<__MutableReturn>>." in
4108 let m2 = "This is not marked <<__MutableReturn>>." in
4110 ~
code:(Typing.err_code
Typing.MutableReturnResultMismatch
)
4113 if pos1_has_mutable_return
then
4118 if pos1_has_mutable_return
then
4124 let pu_expansion pos ty
name =
4125 let ty = strip_ns ty in
4127 (Typing.err_code
Typing.PocketUniversesExpansion
)
4129 (sprintf
"Cannot project type %s from %s." name ty)
4131 let pu_typing pos kind msg =
4133 (Typing.err_code
Typing.PocketUniversesTyping
)
4135 (sprintf
"Unexpected Pocket Universes %s %s during typing." kind msg)
4137 let pu_typing_not_supported pos =
4139 (Typing.err_code
Typing.PocketUniversesTyping
)
4141 "Unsupported Pocket Universes member."
4143 let pu_typing_invalid_upper_bounds pos =
4145 "There isn't enough information to infer what pocket universe this atom is from"
4147 add
(Typing.err_code
Typing.PocketUniversesInvalidUpperBounds
) pos msg
4149 let pu_typing_refinement pos =
4151 (Typing.err_code
Typing.PocketUniversesRefinement
)
4153 "Pocket Universes are not allowed on the right-hand side of is/as"
4155 let php_lambda_disallowed pos =
4157 (NastCheck.err_code
NastCheck.PhpLambdaDisallowed
)
4159 "PHP style anonymous functions are not allowed."
4161 (*****************************************************************************)
4162 (* Typing decl errors *)
4163 (*****************************************************************************)
4165 let wrong_extend_kind
4166 ~parent_pos ~parent_kind ~parent_name ~child_pos ~child_kind ~child_name
=
4167 let parent_kind_str = Ast_defs.string_of_class_kind parent_kind
in
4168 let parent_name = strip_ns parent_name in
4169 let child_name = strip_ns child_name in
4172 " Did you mean to add `use %s;` within the body of %s?"
4177 match child_kind
with
4178 | Ast_defs.Cabstract
4179 | Ast_defs.Cnormal
->
4180 let extends_msg = "Classes can only extend other classes." in
4182 if Ast_defs.is_c_interface parent_kind
then
4183 " Did you mean `implements " ^
parent_name ^
"`?"
4184 else if Ast_defs.is_c_trait parent_kind
then
4189 extends_msg ^
suggestion
4190 | Ast_defs.Cinterface
->
4191 let extends_msg = "Interfaces can only extend other interfaces." in
4193 if Ast_defs.is_c_trait parent_kind
then
4198 extends_msg ^
suggestion
4200 (* This case should never happen, as the type checker will have already caught
4201 it with EnumTypeBad. But just in case, report this error here too. *)
4202 "Enums can only extend int, string, or arraykey."
4203 | Ast_defs.Ctrait
->
4204 (* This case should never happen, as the parser will have caught it before
4206 "A trait cannot use `extends`. This is a parser error."
4208 let msg1 = (child_pos
, child_msg) in
4209 let msg2 = (parent_pos
, "This is " ^
parent_kind_str ^
".") in
4210 add_list
(Typing.err_code
Typing.WrongExtendKind
) [msg1; msg2]
4212 let unsatisfied_req parent_pos req_name req_pos
=
4213 let s1 = "Failure to satisfy requirement: " ^
strip_ns req_name
in
4214 let s2 = "Required here" in
4215 if Pos.equal req_pos parent_pos
then
4216 add
(Typing.err_code
Typing.UnsatisfiedReq
) parent_pos
s1
4219 (Typing.err_code
Typing.UnsatisfiedReq
)
4220 [(parent_pos
, s1); (req_pos
, s2)]
4222 let cyclic_class_def stack pos =
4223 let stack = SSet.fold ~
f:(fun x y -> strip_ns x ^
" " ^
y) stack ~init
:"" in
4225 (Typing.err_code
Typing.CyclicClassDef
)
4227 ("Cyclic class definition : " ^
stack)
4229 let cyclic_record_def names
pos =
4230 let names = List.map ~
f:strip_ns names in
4232 (Typing.err_code
Typing.CyclicRecordDef
)
4235 "Record inheritance cycle: %s"
4236 (String.concat ~sep
:" " names))
4238 let trait_reuse p_pos p_name
class_name trait
=
4239 let (c_pos
, c_name
) = class_name in
4240 let c_name = strip_ns c_name in
4241 let trait = strip_ns trait in
4243 "Class " ^
c_name ^
" reuses trait " ^
trait ^
" in its hierarchy"
4245 let err'
= "It is already used through " ^
strip_ns p_name
in
4246 add_list
(Typing.err_code
Typing.TraitReuse
) [(c_pos
, err); (p_pos
, err'
)]
4248 let trait_reuse_inside_class class_name trait occurrences
=
4249 let (c_pos
, c_name) = class_name in
4250 let c_name = strip_ns c_name in
4251 let trait = strip_ns trait in
4252 let err = "Class " ^
c_name ^
" uses trait " ^
trait ^
" multiple times" in
4254 (Typing.err_code
Typing.TraitReuseInsideClass
)
4255 ([(c_pos
, err)] @ List.map ~
f:(fun p -> (p, "used here")) occurrences
)
4257 let invalid_is_as_expression_hint op hint_pos ty_pos ty_str
=
4259 (Typing.err_code
Typing.InvalidIsAsExpressionHint
)
4261 (hint_pos
, "Invalid \"" ^ op ^
"\" expression hint");
4262 (ty_pos
, "The \"" ^ op ^
"\" operator cannot be used with " ^ ty_str
);
4265 let invalid_enforceable_type kind_str (tp_pos
, tp_name
) targ_pos ty_pos ty_str
=
4267 (Typing.err_code
Typing.InvalidEnforceableTypeArgument
)
4269 (targ_pos
, "Invalid type");
4271 "Type " ^
kind_str ^
" " ^ tp_name ^
" was declared __Enforceable here"
4273 (ty_pos
, "This type is not enforceable because it has " ^ ty_str
);
4276 let reifiable_attr attr_pos decl_kind decl_pos ty_pos ty_msg
=
4278 (Typing.err_code
Typing.DisallowPHPArraysAttr
)
4280 (decl_pos
, "Invalid " ^ decl_kind
);
4281 (attr_pos
, "This type constant has the __Reifiable attribute");
4282 (ty_pos
, "It cannot contain " ^ ty_msg
);
4285 let invalid_newable_type_argument (tp_pos
, tp_name
) ta_pos
=
4287 (Typing.err_code
Typing.InvalidNewableTypeArgument
)
4290 "A newable type argument must be a concrete class or a newable type parameter."
4292 (tp_pos
, "Type parameter " ^ tp_name ^
" was declared __Newable here");
4295 let invalid_newable_type_param_constraints
4296 (tparam_pos
, tparam_name
) constraint_list
=
4298 if List.is_empty constraint_list
then
4302 ^
String.concat ~sep
:", " (List.map ~
f:strip_ns constraint_list
)
4305 "The type parameter "
4307 ^
" has the <<__Newable>> attribute. Newable type parameters must be constrained with `as`, and exactly one of those constraints must be a valid newable class. The class must either be final, or it must have the <<__ConsistentConstruct>> attribute or extend a class that has it. "
4309 ^
" are valid newable classes"
4311 add
(Typing.err_code
Typing.InvalidNewableTypeParamConstraints
) tparam_pos
msg
4313 let override_final ~parent ~child ~
(on_error
: typing_error_callback
option) =
4314 let msg1 = (child
, "You cannot override this method") in
4315 let msg2 = (parent
, "It was declared as final") in
4316 on_error_or_add on_error
(Typing.err_code
Typing.OverrideFinal
) [msg1; msg2]
4318 let override_memoizelsb ~parent ~child
(on_error
: typing_error_callback
) =
4320 ~
code:(Typing.err_code
Typing.OverrideMemoizeLSB
)
4323 "__MemoizeLSB method may not be an override (temporary due to HHVM bug)"
4325 (parent
, "This method is being overridden");
4328 let override_lsb ~member_name ~parent ~child
(on_error
: typing_error_callback
)
4331 ~
code:(Typing.err_code
Typing.OverrideLSB
)
4334 "Member " ^ member_name ^
" may not override __LSB member of parent" );
4335 (parent
, "This is being overridden");
4338 let should_be_override pos class_id id
=
4340 (Typing.err_code
Typing.ShouldBeOverride
)
4343 "%s has no parent class with a method `%s` to override"
4347 let override_per_trait class_name id m_pos
=
4348 let (c_pos
, c_name) = class_name in
4354 ^
" should be an override per the declaring trait; no non-private parent definition found or overridden parent is defined in non-<?hh code"
4357 (Typing.err_code
Typing.OverridePerTrait
)
4358 [(c_pos
, err_msg); (m_pos
, "Declaration of " ^ id ^
"() is here")]
4360 let missing_assign pos =
4361 add
(Typing.err_code
Typing.MissingAssign
) pos "Please assign a value"
4363 let private_override pos class_id id
=
4365 (Typing.err_code
Typing.PrivateOverride
)
4370 ^
": combining private and override is nonsensical" )
4372 let invalid_memoized_param pos ty_reason_msg
=
4374 (Typing.err_code
Typing.InvalidMemoizedParam
)
4376 "Parameters to memoized function must be null, bool, int, float, string, an object deriving IMemoizeParam, or a Container thereof. See also http://docs.hhvm.com/hack/attributes/special#__memoize"
4380 let invalid_disposable_hint pos class_name =
4382 (Typing.err_code
Typing.InvalidDisposableHint
)
4384 ( "Parameter with type '"
4386 ^
"' must not implement IDisposable or IAsyncDisposable. Please use <<__AcceptDisposable>> attribute or create disposable object with 'using' statement instead."
4389 let invalid_disposable_return_hint pos class_name =
4391 (Typing.err_code
Typing.InvalidDisposableReturnHint
)
4395 ^
"' must not implement IDisposable or IAsyncDisposable. Please add <<__ReturnDisposable>> attribute."
4398 let xhp_required pos why_xhp ty_reason_msg
=
4399 let msg = "An XHP instance was expected" in
4401 (Typing.err_code
Typing.XhpRequired
)
4402 ((pos, msg) :: (pos, why_xhp
) :: ty_reason_msg
)
4404 let illegal_xhp_child pos ty_reason_msg
=
4405 let msg = "XHP children must be compatible with XHPChild" in
4406 add_list
(Typing.err_code
Typing.IllegalXhpChild
) ((pos, msg) :: ty_reason_msg
)
4408 let missing_xhp_required_attr pos attr ty_reason_msg
=
4409 let msg = "Required attribute " ^ attr ^
" is missing." in
4411 (Typing.err_code
Typing.MissingXhpRequiredAttr
)
4412 ((pos, msg) :: ty_reason_msg
)
4414 let nullsafe_not_needed p nonnull_witness
=
4416 (Typing.err_code
Typing.NullsafeNotNeeded
)
4417 ( [(p, "You are using the ?-> operator but this object cannot be null. ")]
4420 let generic_at_runtime p prefix
=
4422 (Typing.err_code
Typing.ErasedGenericAtRuntime
)
4425 ^
" generics can only be used in type hints because they do not exist at runtime."
4428 let generics_not_allowed p =
4430 (Typing.err_code
Typing.GenericsNotAllowed
)
4432 "Generics are not allowed in this position."
4434 let trivial_strict_eq p b left right left_trail right_trail
=
4435 let msg = "This expression is always " ^ b
in
4436 let left_trail = List.map
left_trail typedef_trail_entry in
4437 let right_trail = List.map
right_trail typedef_trail_entry in
4439 (Typing.err_code
Typing.TrivialStrictEq
)
4440 (((p, msg) :: left
) @ left_trail @ right
@ right_trail)
4442 let trivial_strict_not_nullable_compare_null p result type_reason
=
4443 let msg = "This expression is always " ^
result in
4445 (Typing.err_code
Typing.NotNullableCompareNullTrivial
)
4446 ((p, msg) :: type_reason
)
4448 let eq_incompatible_types p left right
=
4449 let msg = "This equality test has incompatible types" in
4451 (Typing.err_code
Typing.EqIncompatibleTypes
)
4452 (((p, msg) :: left
) @ right
)
4454 let comparison_invalid_types p left right
=
4456 "This comparison has invalid types. Only comparisons in which both arguments are strings, nums, DateTime, or DateTimeImmutable are allowed"
4459 (Typing.err_code
Typing.ComparisonInvalidTypes
)
4460 (((p, msg) :: left
) @ right
)
4462 let void_usage p void_witness
=
4463 let msg = "You are using the return value of a void function" in
4464 add_list
(Typing.err_code
Typing.VoidUsage
) ((p, msg) :: void_witness
)
4466 let noreturn_usage p noreturn_witness
=
4467 let msg = "You are using the return value of a noreturn function" in
4468 add_list
(Typing.err_code
Typing.NoreturnUsage
) ((p, msg) :: noreturn_witness
)
4470 let attribute_too_few_arguments pos x n =
4471 let n = string_of_int
n in
4473 (Typing.err_code
Typing.AttributeTooFewArguments
)
4475 ("The attribute " ^
x ^
" expects at least " ^
n ^
" arguments")
4477 let attribute_too_many_arguments pos x n =
4478 let n = string_of_int
n in
4480 (Typing.err_code
Typing.AttributeTooManyArguments
)
4482 ("The attribute " ^
x ^
" expects at most " ^
n ^
" arguments")
4484 let attribute_param_type pos x =
4486 (Typing.err_code
Typing.AttributeParamType
)
4488 ("This attribute parameter should be " ^
x)
4490 let deprecated_use pos pos_def
msg =
4492 (Typing.err_code
Typing.DeprecatedUse
)
4493 [(pos, msg); (pos_def
, "Definition is here")]
4495 let cannot_declare_constant kind pos (class_pos
, class_name) =
4498 | `enum
-> "an enum"
4499 | `
trait -> "a trait"
4500 | `record
-> "a record"
4503 (Typing.err_code
Typing.CannotDeclareConstant
)
4505 (pos, "Cannot declare a constant in " ^
kind_str);
4506 (class_pos
, strip_ns class_name ^
" was defined as " ^
kind_str ^
" here");
4509 let ambiguous_inheritance
4510 pos class_ origin
(error
: error
) (on_error
: typing_error_callback
) =
4511 let origin = strip_ns origin in
4512 let class_ = strip_ns class_ in
4514 "This declaration was inherited from an object of type "
4516 ^
". Redeclare this member in "
4518 ^
" with a compatible signature."
4520 let (code, msgl) = (get_code error
, to_list error
) in
4521 on_error ~
code (msgl @ [(pos, message)])
4523 let multiple_concrete_defs
4530 (on_error
: typing_error_callback
) =
4531 let child_origin = strip_ns child_origin in
4532 let parent_origin = strip_ns parent_origin in
4533 let class_ = strip_ns class_ in
4535 ~
code:(Typing.err_code
Typing.MultipleConcreteDefs
)
4541 ^
" both declare ambiguous implementations of "
4544 (child_pos
, child_origin ^
"'s definition is here.");
4545 (parent_pos
, parent_origin ^
"'s definition is here.");
4547 "Redeclare " ^
name ^
" in " ^
class_ ^
" with a compatible signature."
4551 let local_variable_modified_and_used pos_modified pos_used_l
=
4552 let used_msg p = (p, "And accessed here") in
4554 (Typing.err_code
Typing.LocalVariableModifedAndUsed
)
4556 "Unsequenced modification and access to local variable. Modified here"
4558 :: List.map pos_used_l
used_msg )
4560 let local_variable_modified_twice pos_modified pos_modified_l
=
4561 let modified_msg p = (p, "And also modified here") in
4563 (Typing.err_code
Typing.LocalVariableModifedTwice
)
4565 "Unsequenced modifications to local variable. Modified here" )
4566 :: List.map pos_modified_l
modified_msg )
4568 let assign_during_case p =
4570 (Typing.err_code
Typing.AssignDuringCase
)
4572 "Don't assign to variables inside of case labels"
4574 let cyclic_enum_constraint pos =
4575 add
(Typing.err_code
Typing.CyclicEnumConstraint
) pos "Cyclic enum constraint"
4577 let invalid_classname p =
4578 add
(Typing.err_code
Typing.InvalidClassname
) p "Not a valid class name"
4580 let illegal_type_structure pos errmsg
=
4582 "The two arguments to type_structure() must be:"
4583 ^
"\n - first: ValidClassname::class or an object of that class"
4584 ^
"\n - second: a single-quoted string literal containing the name"
4585 ^
" of a type constant of that class"
4589 add
(Typing.err_code
Typing.IllegalTypeStructure
) pos msg
4591 let illegal_typeconst_direct_access pos =
4593 "Type constants cannot be directly accessed. "
4594 ^
"Use type_structure(ValidClassname::class, 'TypeConstName') instead"
4596 add
(Typing.err_code
Typing.IllegalTypeStructure
) pos msg
4598 let override_no_default_typeconst pos_child pos_parent
=
4600 (Typing.err_code
Typing.OverrideNoDefaultTypeconst
)
4602 (pos_child
, "This abstract type constant does not have a default type");
4604 "It cannot override an abstract type constant that has a default type"
4608 let inout_annotation_missing pos1 pos2
=
4609 let msg1 = (pos1
, "This argument should be annotated with 'inout'") in
4610 let msg2 = (pos2
, "Because this is an inout parameter") in
4611 add_list
(Typing.err_code
Typing.InoutAnnotationMissing
) [msg1; msg2]
4613 let inout_annotation_unexpected pos1 pos2 pos2_is_variadic
=
4614 let msg1 = (pos1
, "Unexpected inout annotation for argument") in
4617 if pos2_is_variadic
then
4618 "A variadic parameter can never be inout"
4620 "This is a normal parameter (does not have 'inout')" )
4622 add_list
(Typing.err_code
Typing.InoutAnnotationUnexpected
) [msg1; msg2]
4624 let inoutness_mismatch pos1 pos2
(on_error
: typing_error_callback
) =
4625 let msg1 = (pos1
, "This is an inout parameter") in
4626 let msg2 = (pos2
, "It is incompatible with a normal parameter") in
4627 on_error ~
code:(Typing.err_code
Typing.InoutnessMismatch
) [msg1; msg2]
4629 let invalid_new_disposable pos =
4631 "Disposable objects may only be created in a 'using' statement or 'return' from function marked <<__ReturnDisposable>>"
4633 add
(Typing.err_code
Typing.InvalidNewDisposable
) pos msg
4635 let invalid_return_disposable pos =
4637 "Return expression must be new disposable in function marked <<__ReturnDisposable>>"
4639 add
(Typing.err_code
Typing.InvalidReturnDisposable
) pos msg
4641 let nonreactive_function_call pos decl_pos callee_reactivity cause_pos_opt
=
4643 (Typing.err_code
Typing.NonreactiveFunctionCall
)
4645 (pos, "Reactive functions can only call other reactive functions.");
4646 (decl_pos
, "This function is " ^ callee_reactivity ^
".");
4648 @ Option.value_map cause_pos_opt ~default
:[] ~
f:(fun cause_pos
->
4651 "This argument caused function to be " ^ callee_reactivity ^
"."
4655 let nonreactive_call_from_shallow pos decl_pos callee_reactivity cause_pos_opt
=
4657 (Typing.err_code
Typing.NonreactiveCallFromShallow
)
4659 (pos, "Shallow reactive functions cannot call non-reactive functions.");
4660 (decl_pos
, "This function is " ^ callee_reactivity ^
".");
4662 @ Option.value_map cause_pos_opt ~default
:[] ~
f:(fun cause_pos
->
4665 "This argument caused function to be " ^ callee_reactivity ^
"."
4669 let rx_enabled_in_non_rx_context pos =
4671 (Typing.err_code
Typing.RxEnabledInNonRxContext
)
4673 "\\HH\\Rx\\IS_ENABLED can only be used in reactive functions."
4675 let rx_parameter_condition_mismatch
4676 cond
pos def_pos
(on_error
: typing_error_callback
) =
4678 ~
code:(Typing.err_code
Typing.RxParameterConditionMismatch
)
4681 "This parameter does not satisfy "
4683 ^
" condition defined on matching parameter in function super type." );
4684 (def_pos
, "This is parameter declaration from the function super type.");
4687 let nonreactive_indexing is_append
pos =
4690 "Cannot append to a Hack Collection object in a reactive context. Instead, use the 'add' method."
4692 "Cannot assign to element of Hack Collection object via [] in a reactive context. Instead, use the 'set' method."
4694 add
(Typing.err_code
Typing.NonreactiveIndexing
) pos msg
4696 let obj_set_reactive pos =
4698 "This object's property is being mutated(used as an lvalue)"
4699 ^
"\nYou cannot set non-mutable object properties in reactive functions"
4701 add
(Typing.err_code
Typing.ObjSetReactive
) pos msg
4703 let invalid_unset_target_rx pos =
4705 (Typing.err_code
Typing.InvalidUnsetTargetInRx
)
4707 "Non-mutable argument for 'unset' is not allowed in reactive functions."
4709 let inout_argument_bad_type pos msgl =
4711 "Expected argument marked inout to be contained in a local or "
4712 ^
"a value-typed container (e.g. vec, dict, keyset, array). "
4713 ^
"To use inout here, assign to/from a temporary local variable."
4715 add_list
(Typing.err_code
Typing.InoutArgumentBadType
) ((pos, msg) :: msgl)
4717 let ambiguous_lambda pos uses
=
4719 "Lambda has parameter types that could not be determined at definition site."
4723 "%d distinct use types were determined: please add type hints to lambda parameters."
4727 (Typing.err_code
Typing.AmbiguousLambda
)
4728 ( [(pos, msg1); (pos, msg2)]
4729 @ List.map uses
(fun (pos, ty) -> (pos, "This use has type " ^
ty)) )
4731 let wrong_expression_kind_attribute
4732 expr_kind
pos attr attr_class_pos attr_class_name intf_name
=
4735 "The %s attribute cannot be used on %s."
4741 "The attribute's class is defined here. To be available for use on %s, the %s class must implement %s."
4743 (strip_ns attr_class_name
)
4744 (strip_ns intf_name
)
4747 (Typing.err_code
Typing.WrongExpressionKindAttribute
)
4748 [(pos, msg1); (attr_class_pos
, msg2)]
4750 let wrong_expression_kind_builtin_attribute expr_kind
pos attr
=
4753 "The %s attribute cannot be used on %s."
4757 add_list
(Typing.err_code
Typing.WrongExpressionKindAttribute
) [(pos, msg1)]
4759 let cannot_return_borrowed_value_as_immutable fun_pos value_pos
=
4761 (Typing.err_code
Typing.CannotReturnBorrowedValueAsImmutable
)
4764 "Values returned from reactive function by default are treated as immutable."
4767 "This value is mutably borrowed and cannot be returned as immutable" );
4770 let decl_override_missing_hint pos (on_error
: typing_error_callback
) =
4772 ~
code:(Typing.err_code
Typing.DeclOverrideMissingHint
)
4775 "When redeclaring class members, both declarations must have a typehint"
4779 let invalid_type_for_atmost_rx_as_rxfunc_parameter pos type_str
=
4781 (Typing.err_code
Typing.InvalidTypeForOnlyrxIfRxfuncParameter
)
4783 ( "Parameter annotated with <<__AtMostRxAsFunc>> attribute must be function, now '"
4787 let missing_annotation_for_atmost_rx_as_rxfunc_parameter pos =
4789 (Typing.err_code
Typing.MissingAnnotationForOnlyrxIfRxfuncParameter
)
4791 "Missing function type annotation on parameter marked with <<__AtMostRxAsFunc>> attribute."
4793 let superglobal_in_reactive_context pos name =
4795 (Typing.err_code
Typing.SuperglobalInReactiveContext
)
4797 ("Superglobal " ^
name ^
" cannot be used in a reactive context.")
4799 let static_property_in_reactive_context pos =
4801 (Typing.err_code
Typing.StaticPropertyInReactiveContext
)
4803 "Static property cannot be used in a reactive context."
4805 let returns_void_to_rx_function_as_non_expression_statement pos fpos
=
4807 (Typing.err_code
Typing.ReturnsVoidToRxAsNonExpressionStatement
)
4810 "Cannot use result of function annotated with <<__ReturnsVoidToRx>> in reactive context"
4812 (fpos
, "This is function declaration.");
4815 let non_awaited_awaitable_in_rx pos =
4817 (Typing.err_code
Typing.NonawaitedAwaitableInReactiveContext
)
4819 "This value has Awaitable type. Awaitable typed values in reactive code must be immediately await'ed."
4821 let shapes_key_exists_always_true pos1
name pos2
=
4823 (Typing.err_code
Typing.ShapesKeyExistsAlwaysTrue
)
4825 (pos1
, "This Shapes::keyExists() check is always true");
4826 (pos2
, "The field '" ^
name ^
"' exists because of this definition");
4829 let shape_field_non_existence_reason pos name = function
4831 [(pos, "The field '" ^
name ^
"' is not defined in this shape")]
4832 | `Nothing
reason ->
4834 "The type of the field '"
4836 ^
"' in this shape doesn't allow any values" )
4839 let shapes_key_exists_always_false pos1
name pos2
reason =
4840 add_list
(Typing.err_code
Typing.ShapesKeyExistsAlwaysFalse
)
4841 @@ (pos1
, "This Shapes::keyExists() check is always false")
4842 :: shape_field_non_existence_reason pos2
name reason
4844 let shapes_method_access_with_non_existent_field
4845 pos1
name pos2 method_name
reason =
4846 add_list
(Typing.err_code
Typing.ShapesMethodAccessWithNonExistentField
)
4848 "You are calling Shapes::"
4850 ^
"() on a field known to not exist" )
4851 :: shape_field_non_existence_reason pos2
name reason
4853 let shape_access_with_non_existent_field pos1
name pos2
reason =
4854 add_list
(Typing.err_code
Typing.ShapeAccessWithNonExistentField
)
4855 @@ (pos1
, "You are accessing a field known to not exist")
4856 :: shape_field_non_existence_reason pos2
name reason
4858 let ambiguous_object_access
4859 pos name self_pos vis subclass_pos class_self class_subclass
=
4860 let class_self = strip_ns class_self in
4861 let class_subclass = strip_ns class_subclass in
4863 (Typing.err_code
Typing.AmbiguousObjectAccess
)
4865 (pos, "This object access to " ^
name ^
" is ambiguous");
4867 "You will access the private instance declared in " ^
class_self );
4869 "Instead of the " ^ vis ^
" instance declared in " ^
class_subclass );
4872 let invalid_traversable_in_rx pos =
4874 (Typing.err_code
Typing.InvalidTraversableInRx
)
4876 "Cannot traverse over non-reactive traversable in reactive code."
4878 let lateinit_with_default pos =
4880 (Typing.err_code
Typing.LateInitWithDefault
)
4882 "A late-initialized property cannot have a default value"
4884 let bad_lateinit_override
4885 parent_is_lateinit parent_pos child_pos
(on_error
: typing_error_callback
) =
4887 if parent_is_lateinit
then
4893 ~
code:(Typing.err_code
Typing.BadLateInitOverride
)
4896 "Redeclared properties must be consistently declared __LateInit" );
4897 (parent_pos
, "The property " ^
verb ^
" declared __LateInit here");
4900 let bad_xhp_attr_required_override
4901 parent_tag child_tag parent_pos child_pos
(on_error
: typing_error_callback
)
4904 ~
code:(Typing.err_code
Typing.BadXhpAttrRequiredOverride
)
4906 (child_pos
, "Redeclared attribute must not be less strict");
4910 ^
", which is stricter than "
4914 let invalid_switch_case_value_type case_value_p case_value_ty scrutinee_ty
=
4915 add
(Typing.err_code
Typing.InvalidSwitchCaseValueType
) case_value_p
4917 "Switch statements use == equality, so comparing values of type %s with %s may not give the desired result."
4921 let unserializable_type pos message =
4923 (Typing.err_code
Typing.UnserializableType
)
4925 ( "Unserializable type (could not be converted to JSON and back again): "
4928 let redundant_rx_condition pos =
4930 (Typing.err_code
Typing.RedundantRxCondition
)
4932 "Reactivity condition for this method is always true, consider removing it."
4934 let invalid_arraykey code pos (cpos
, ctype
) (kpos
, ktype
) =
4936 (Typing.err_code
code)
4938 (pos, "This value is not a valid key type for this container");
4939 (cpos
, "This container is " ^ ctype
);
4940 (kpos
, String.capitalize ktype ^
" cannot be used as a key for " ^ ctype
);
4943 let invalid_arraykey_read = invalid_arraykey Typing.InvalidArrayKeyRead
4945 let invalid_arraykey_write = invalid_arraykey Typing.InvalidArrayKeyWrite
4947 let invalid_sub_string pos ty =
4948 add
(Typing.err_code
Typing.InvalidSubString
) pos
4949 @@ "Expected an object convertible to string but got "
4952 let typechecker_timeout (pos, fun_name
) seconds
=
4954 (Typing.err_code
Typing.TypecheckerTimeout
)
4957 "Type checker timed out after %d seconds whilst checking function %s"
4961 let unresolved_type_variable pos =
4963 (Typing.err_code
Typing.UnresolvedTypeVariable
)
4965 "The type of this expression contains an unresolved type variable"
4967 let invalid_arraykey_constraint pos t
=
4969 (Typing.err_code
Typing.InvalidArrayKeyConstraint
)
4973 ^
", which cannot be used as an arraykey (string | int)" )
4975 let exception_occurred pos e
=
4976 let pos_str = pos |> Pos.to_absolute |> Pos.string in
4977 HackEventLogger.type_check_exn_bug ~
path:(Pos.filename pos) ~
pos:pos_str ~e
;
4979 "Exception while typechecking at position %s\n%s"
4981 (Exception.to_string e
);
4983 (Typing.err_code
Typing.ExceptionOccurred
)
4986 "An exception occurred while typechecking this. %s"
4987 Error_message_sentinel.please_file_a_bug_message
)
4989 let redundant_covariant pos msg suggest
=
4991 (Typing.err_code
Typing.RedundantGeneric
)
4993 ( "This generic parameter is redundant because it only appears in a covariant (output) position"
4995 ^
". Consider replacing uses of generic parameter with `"
4997 ^
"` or specifying <<__Explicit>> on the generic parameter" )
4999 let meth_caller_trait pos trait_name
=
5001 (Typing.err_code
Typing.MethCallerTrait
)
5003 ( strip_ns trait_name
5004 ^
" is a trait which cannot be used with meth_caller. Use a class instead."
5007 let duplicate_interface pos name others
=
5009 (Typing.err_code
Typing.DuplicateInterface
)
5012 "Interface %s is used more than once in this declaration."
5014 :: List.map others
(fun pos -> (pos, "Here is another occurrence")) )
5016 (*****************************************************************************)
5018 (*****************************************************************************)
5020 let to_json (error
: Pos.absolute error_
) =
5021 let (error_code, msgl) = (get_code error
, to_list error
) in
5023 List.map
msgl (fun (p, w
) ->
5024 let (line
, scol
, ecol
) = Pos.info_pos
p in
5027 ("descr", Hh_json.JSON_String w
);
5028 ("path", Hh_json.JSON_String
(Pos.filename p));
5029 ("line", Hh_json.int_ line
);
5030 ("start", Hh_json.int_ scol
);
5031 ("end", Hh_json.int_ ecol
);
5032 ("code", Hh_json.int_
error_code);
5035 Hh_json.JSON_Object
[("message", Hh_json.JSON_Array
elts)]
5037 let convert_errors_to_string ?
(include_filename
= false) (errors
: error list
) :
5041 ~
f:(fun err acc_out
->
5044 ~
f:(fun (pos, msg) acc_in
->
5045 let result = Format.asprintf
"%a %s" Pos.pp
pos msg in
5046 if include_filename
then
5050 (Pos.to_absolute pos |> Pos.filename)
5053 full_result :: acc_in
5059 (*****************************************************************************)
5060 (* Try if errors. *)
5061 (*****************************************************************************)
5063 let try_ f1 f2
= try_with_result f1
(fun _
l -> f2
l)
5065 let try_with_error f1 f2
=
5067 let (error_code, l) = (get_code
err, to_list err) in
5068 add_list
error_code l;
5071 let has_no_errors f =
5078 (*****************************************************************************)
5080 (*****************************************************************************)
5083 let allow_errors_in_default_path_copy = !allow_errors_in_default_path in
5084 set_allow_errors_in_default_path true;
5085 let (_, result) = do_ f in
5086 set_allow_errors_in_default_path allow_errors_in_default_path_copy;
5089 let try_when f ~when_ ~
do_ =
5090 try_with_result f (fun result (error
: error
) ->