end
t = t.anchor_to(self.nclassdef.mclassdef.mmodule, self.nclassdef.mclassdef.bound_mtype)
if t isa MNullableType then
- var name = n.callsite.mproperty.name
- if name == "==" or name == "!=" or name == "is_same_instance" then
+ var p = n.callsite.mproperty
+ if p.is_null_safe then
self.nullable_eq_sends += 1
else
self.nullable_sends += 1
do
return self.is_init
end
+
+ # A specific method that is safe to call on null.
+ # Currently, only `==`, `!=` and `is_same_instance` are safe
+ fun is_null_safe: Bool do return name == "==" or name == "!=" or name == "is_same_instance"
end
# A global attribute
#debug("recv: {recvtype} (aka {unsafe_type})")
if recvtype isa MNullType then
- # `null` only accepts some methods of object.
- if name == "==" or name == "!=" or name == "is_same_instance" then
- var objclass = get_mclass(node, "Object")
- if objclass == null then return null # Forward error
- unsafe_type = objclass.mclass_type
- else
- self.error(node, "Error: method `{name}` called on `null`.")
- return null
- end
+ var objclass = get_mclass(node, "Object")
+ if objclass == null then return null # Forward error
+ unsafe_type = objclass.mclass_type
end
var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
assert mproperty isa MMethod
+ # `null` only accepts some methods of object.
+ if recvtype isa MNullType and not mproperty.is_null_safe then
+ self.error(node, "Error: method `{name}` called on `null`.")
+ return null
+ else if unsafe_type isa MNullableType and not mproperty.is_null_safe then
+ modelbuilder.advice(node, "call-on-nullable", "Warning: method call on a nullable receiver `{recvtype}`.")
+ end
+
if is_toplevel_context and recv_is_self and not mproperty.is_toplevel then
error(node, "Error: `{name}` is not a top-level method, thus need a receiver.")
end
-alt/base_adaptive_loop3_alt3.nit:29,10--13: Error: method `next` called on `null`.
+alt/base_adaptive_loop3_alt3.nit:29,10--13: Error: method `next` does not exists in `null`.
-alt/base_var_null_alt12.nit:45,3--4: Error: method `+` called on `null`.
+alt/base_var_null_alt12.nit:45,3--4: Error: method `+` does not exists in `null`.
-alt/base_var_null_alt4.nit:31,3--4: Error: method `+` called on `null`.
+alt/base_var_null_alt4.nit:31,3--4: Error: method `+` does not exists in `null`.
-alt/base_var_null_alt8.nit:38,3--4: Error: method `+` called on `null`.
+alt/base_var_null_alt8.nit:38,3--4: Error: method `+` does not exists in `null`.
alt/error_expr_not_ok_alt6.nit:42,7--9: Type Error: expected `A`, got `Int`.
alt/error_expr_not_ok_alt6.nit:43,5--8: Error: method `fail` does not exists in `Int`.
alt/error_expr_not_ok_alt6.nit:45,7--10: Type Error: expected `A`, got `null`.
-alt/error_expr_not_ok_alt6.nit:46,6--9: Error: method `fail` called on `null`.
+alt/error_expr_not_ok_alt6.nit:46,6--9: Error: method `fail` does not exists in `null`.
alt/error_expr_not_ok_alt6.nit:49,7--10: Type Error: expected `A`, got `null`.
-alt/error_expr_not_ok_alt6.nit:50,6--10: Error: method `trash` called on `null`.
+alt/error_expr_not_ok_alt6.nit:50,6--10: Error: method `trash` does not exists in `null`.
alt/error_expr_not_ok_alt6.nit:60,4--7: Type Error: expected `Bool`, got `Int`.
alt/error_expr_not_ok_alt6.nit:60,20: Type Error: expected `A`, got `Int`.
alt/error_expr_not_ok_alt6.nit:62,10--13: Type Error: expected `Bool`, got `Int`.