Merge: nitvm: Basic blocks generation and SSA-algorithm
[nit.git] / src / semantize / typing.nit
index 8a4e13f..31cc4b0 100644 (file)
@@ -301,15 +301,9 @@ private class TypeVisitor
 
                #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 @@ private class TypeVisitor
 
                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
@@ -958,7 +960,7 @@ redef class AVarReassignExpr
 
                v.set_variable(self, variable, rettype)
 
-               self.is_typed = true
+               self.is_typed = rettype != null
        end
 end
 
@@ -1004,9 +1006,11 @@ redef class AReturnExpr
                        else
                                v.visit_expr(nexpr)
                                v.error(nexpr, "Error: `return` with value in a procedure.")
+                               return
                        end
                else if ret_type != null then
                        v.error(self, "Error: `return` without value in a function.")
+                       return
                end
                self.is_typed = true
        end
@@ -1342,6 +1346,15 @@ redef class AIntExpr
        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
@@ -2050,7 +2063,7 @@ redef class AAttrAssignExpr
                var mtype = self.attr_type
 
                v.visit_expr_subtype(self.n_value, mtype)
-               self.is_typed = true
+               self.is_typed = mtype != null
        end
 end
 
@@ -2061,9 +2074,9 @@ redef class AAttrReassignExpr
                var mtype = self.attr_type
                if mtype == null then return # Skip error
 
-               self.resolve_reassignment(v, mtype, mtype)
+               var rettype = self.resolve_reassignment(v, mtype, mtype)
 
-               self.is_typed = true
+               self.is_typed = rettype != null
        end
 end