From: Jean Privat Date: Sat, 30 May 2015 00:37:22 +0000 (-0400) Subject: Merge: Warn call on nullable receiver X-Git-Tag: v0.7.5~4 X-Git-Url: http://nitlanguage.org?hp=-c Merge: Warn call on nullable receiver Followup of #1375 and #394 This introduce an advice on calls on a nullable receiver. Since the conversion could be complex, I propose a light approach with advices (quiet warnings) instead of hard errors, so that: 1. jenkins can track them 2. nitpick (thus vim) can show them 3. mirgration can be done in an incremental and iterative way 4. issues with a strict call-on-nullable policy can be identified without breaking things 5. @Morriar can bank nitcoins in future PR If (when?) all call on nullable can be removed, then the advice will become an error. Pull-Request: #1414 Reviewed-by: Alexis Laferrière Reviewed-by: Romain Chanoir --- dff7da4e0a4783718f9409ee27dc072f84e24b82 diff --combined src/model/model.nit index 908cb60,e4b881f..4e9be82 --- a/src/model/model.nit +++ b/src/model/model.nit @@@ -206,9 -206,6 +206,9 @@@ redef class MModul # The primitive type `Int` var int_type: MClassType = self.get_primitive_class("Int").mclass_type is lazy + # The primitive type `Byte` + var byte_type: MClassType = self.get_primitive_class("Byte").mclass_type is lazy + # The primitive type `Char` var char_type: MClassType = self.get_primitive_class("Char").mclass_type is lazy @@@ -2156,6 -2153,10 +2156,10 @@@ class MMetho 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 diff --combined src/semantize/typing.nit index 3c7c9b1,10edaf1..44ed320 --- a/src/semantize/typing.nit +++ b/src/semantize/typing.nit @@@ -301,15 -301,9 +301,9 @@@ private class TypeVisito #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) @@@ -331,6 -325,14 +325,14 @@@ 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 @@@ -1342,15 -1344,6 +1344,15 @@@ redef class AIntExp end end +redef class AByteExpr + redef fun accept_typing(v) + do + var mclass = v.get_mclass(self, "Byte") + if mclass == null then return # Forward error + self.mtype = mclass.mclass_type + end +end + redef class AFloatExpr redef fun accept_typing(v) do