Skip to content

Commit

Permalink
Run toString(null) for explicit nullable abstract
Browse files Browse the repository at this point in the history
If the abstract is declared over Null<T>, then null is part of the type
so the user should be able to handle the null case within the toString
method. It is also useful to be able to have custom empty values for
an abstract that wraps a nullable type.

This is also in-line what null safety has to say, as it forces the user
to add a null check to toString when the concrete type is Null<T>.
  • Loading branch information
tobil4sk committed Feb 18, 2025
1 parent 1249ed9 commit fefe7c1
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/typing/calls.ml
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ let rec needs_temp_var e =
| TField (e, _) | TParenthesis e -> needs_temp_var e
| _ -> true

let call_to_string ctx ?(resume=false) e =
let call_to_string ctx ?(resume=false) ?(no_null_check=false) e =
if not ctx.allow_transform then
{ e with etype = ctx.t.tstring }
else
Expand All @@ -333,7 +333,7 @@ let call_to_string ctx ?(resume=false) e =
ctx.f.meta <- List.tl ctx.f.meta;
build_call ctx acc [] (WithType.with_type ctx.t.tstring) e.epos
in
if ctx.com.config.pf_static && not (is_nullable e.etype) then
if no_null_check || (ctx.com.config.pf_static && not (is_nullable e.etype)) then
gen_to_string e
else begin (* generate `if(e == null) 'null' else e.toString()` *)
let string_null = mk (TConst (TString "null")) ctx.t.tstring e.epos in
Expand Down
4 changes: 2 additions & 2 deletions src/typing/operators.ml
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ let make_binop ctx op e1 e2 is_assign_op p =
let tstring = ctx.t.tstring in
let to_string e =
let rec loop t = match classify t with
| KAbstract ({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics ->
call_to_string ctx e
| KAbstract ({a_impl = Some c; a_this},_) when PMap.mem "toString" c.cl_statics ->
call_to_string ~no_null_check:(is_explicit_null a_this) ctx e
| KInt | KFloat | KString -> e
| KUnk | KDyn | KNumParam _ | KStrParam _ | KOther ->
Texpr.Builder.resolve_and_make_static_call ctx.com.std "string" [e] e.epos
Expand Down
7 changes: 4 additions & 3 deletions src/typing/typer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1603,7 +1603,8 @@ and type_meta ?(mode=MGet) ctx m e1 with_type p =
| (Meta.ToString,_,_) ->
let e = e() in
(match follow e.etype with
| TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics -> call_to_string ctx e
| TAbstract({a_impl = Some c; a_this},_) when PMap.mem "toString" c.cl_statics ->
call_to_string ~no_null_check:(is_explicit_null a_this) ctx e
| _ -> e)
| (Meta.Markup,_,_) ->
raise_typing_error "Markup literals must be processed by a macro" p
Expand Down Expand Up @@ -1725,8 +1726,8 @@ and type_call_builtin ctx e el mode with_type p =
let e = type_expr ctx e WithType.value in
let infos = type_expr ctx infos WithType.value in
let e = match follow e.etype with
| TAbstract({a_impl = Some c},_) when PMap.mem "toString" c.cl_statics ->
call_to_string ctx e
| TAbstract({a_impl = Some c; a_this},_) when PMap.mem "toString" c.cl_statics ->
call_to_string ~no_null_check:(is_explicit_null a_this) ctx e
| _ ->
e
in
Expand Down

0 comments on commit fefe7c1

Please sign in to comment.