Merge: typing: add services for intersecting and subtracting types
authorJean Privat <jean@pryen.org>
Mon, 20 Mar 2017 20:09:01 +0000 (16:09 -0400)
committerJean Privat <jean@pryen.org>
Mon, 20 Mar 2017 20:09:01 +0000 (16:09 -0400)
Nit does not have intersection nor union types, however, the intersection and the difference operations on types are needed for a better behavior of the adaptive typing system.

Currently, the only need of type intersection and type difference is with `isa`. The previous implementation did not really implement them and only did the following:

~~~nit
var x: X
...
if x isa Y then
   # if X<:Y then x is still a X (and you get a warning) else x is now a Y
   ...
else
   # nothing never change here. x is a X
   ...
end
~~~

Now, the `then` branch, handle the merge of nullable types and the `else` branch might also be adapted.

~~~nit
var x: nullable X # where Y <: X
...
if x isa Object then
   # x is a X (instead of Object as before)
else
  #  x is null (instead of nullable X as before)
end

if x isa nullable Object then # warning, useless isa
   # x is a nullable X (as before)
else
   # x is dead (instead of nullable X as before)
end

if x isa Y then
   # x is a Y (same as before)
else
   # x is a nullable X (same as before)
end

if x isa nullable Y then
   # x is a nullable Y (as before)
else
   # x is a X without nullable (instead of nullable X as before)
end
~~~

I do not expect that these change improve that much the expressiveness of the language. However, it makes the type system a little more consistent and a little less hackish.

Pull-Request: #2385
Reviewed-by: Jean-Christophe Beaupré <jcbrinfo.public@gmail.com>

src/semantize/typing.nit
tests/base_adaptive_full.nit [new file with mode: 0644]
tests/sav/base_adaptive_full.res [new file with mode: 0644]
tests/sav/base_adaptive_full_alt1.res [new file with mode: 0644]
tests/sav/base_adaptive_full_alt2.res [new file with mode: 0644]
tests/sav/base_adaptive_loop_array_1alt2_alt1.res
tests/sav/base_adaptive_loop_array_alt1.res
tests/sav/base_adaptive_loop_call_alt1.res
tests/sav/base_isa_nil.res
tests/sav/base_var_untyped_alt4.res
tests/sav/base_var_untyped_alt5.res

index 50ba70e..0bbe61b 100644 (file)
@@ -580,7 +580,16 @@ private class TypeVisitor
                                return mtypes.first
                        else
                                var res = merge_types(node,mtypes)
-                               if res == null then res = variable.declared_type
+                               if res == null then
+                                       res = variable.declared_type
+                                       # Try to fallback to a non-null version
+                                       if res != null and can_be_null(res) then do
+                                               for t in mtypes do
+                                                       if t != null and can_be_null(t) then break label
+                                               end
+                                               res = res.as_notnull
+                                       end label
+                               end
                                return res
                        end
                end
@@ -600,6 +609,29 @@ private class TypeVisitor
                flow.set_var(self, variable, mtype)
        end
 
+       # Find the exact representable most specific common super-type in `col`.
+       #
+       # Try to find the most specific common type that is a super-type of each types
+       # in `col`.
+       # In most cases, the result is simply the most general type in `col`.
+       # If nullables types are involved, then the nullable information is correctly preserved.
+       # If incomparable super-types exists in `col`, them no solution is given and the `null`
+       # value is returned (since union types are non representable in Nit)
+       #
+       # The `null` values in `col` are ignored, nulltypes (MNullType) are considered.
+       #
+       # Returns the `null` value if:
+       #
+       # * `col` is empty
+       # * `col` only have null values
+       # * there is a conflict
+       #
+       # Example (with a diamond A,B,C,D):
+       #
+       # * merge(A,B,C) -> A, because A is the most general type in {A,B,C}
+       # * merge(C,B) -> null, there is conflict, because `B or C` cannot be represented
+       # * merge(A,nullable B) -> nullable A, because A is the most general type and
+       #   the nullable information is preserved
        fun merge_types(node: ANode, col: Array[nullable MType]): nullable MType
        do
                if col.length == 1 then return col.first
@@ -621,6 +653,82 @@ private class TypeVisitor
                #self.modelbuilder.warning(node, "Type Error: {col.length} conflicting types: <{col.join(", ")}>")
                return null
        end
+
+       # Find a most general common subtype between `type1` and `type2`.
+       #
+       # Find the most general type that is a subtype of `type2` and, if possible, a subtype of `type1`.
+       # Basically, this return the most specific type between `type1` and `type2`.
+       # If nullable types are involved, the information is correctly preserved.
+       # If `type1` and `type2` are incomparable then `type2` is preferred (since intersection types
+       # are not representable in Nit).
+       #
+       # The `null` value is returned if both `type1` and `type2` are null.
+       #
+       # Examples (with diamond A,B,C,D):
+       #
+       # * intersect_types(A,B) -> B, because B is a subtype of A
+       # * intersect_types(B,A) -> B, because B is a subtype of A
+       # * intersect_types(B,C) -> C, B and C are incomparable,
+       #   `type2` is then preferred (`B and C` cannot be represented)
+       # * intersect_types(nullable B,A) -> B, because B<:A and the non-null information is preserved
+       # * intersect_types(B,nullable C) -> C, `type2` is preferred and the non-null information is preserved
+       fun intersect_types(node: ANode, type1, type2: nullable MType): nullable MType
+       do
+               if type1 == null then return type2
+               if type2 == null then return type1
+
+               if not can_be_null(type2) or not can_be_null(type1) then
+                       type1 = type1.as_notnull
+                       type2 = type2.as_notnull
+               end
+
+               var res
+               if is_subtype(type1, type2) then
+                       res = type1
+               else
+                       res = type2
+               end
+               return res
+       end
+
+       # Find a most general type that is a subtype of `type1` but not one of `type2`.
+       #
+       # Basically, this returns `type1`-`type2` but since there is no substraction type
+       # in Nit this just returns `type1` most of the case.
+       #
+       # The few other cases are if `type2` is a super-type and if some nullable information
+       # is present.
+       #
+       # The `null` value is returned if `type1` is null.
+       #
+       # Examples (with diamond A,B,C,D):
+       #
+       # * diff_types(A,B) -> A, because the notB cannot be represented
+       # * diff_types(B,A) -> None (absurd type), because B<:A
+       # * diff_types(nullable A, nullable B) -> A, because null is removed
+       # * diff_types(nullable B, A) -> Null, because anything but null is removed
+       fun diff_types(node: ANode, type1, type2: nullable MType): nullable MType
+       do
+               if type1 == null then return null
+               if type2 == null then return type1
+
+               # if t1 <: t2 then t1-t2 = bottom
+               if is_subtype(type1, type2) then
+                       return modelbuilder.model.null_type.as_notnull
+               end
+
+               # else if t1 <: nullable t2 then t1-t2 = nulltype
+               if is_subtype(type1, type2.as_nullable) then
+                       return modelbuilder.model.null_type
+               end
+
+               # else t2 can be null and type2 must accept null then null is excluded in t1
+               if can_be_null(type1) and (type2 isa MNullableType or type2 isa MNullType) then
+                       return type1.as_notnull
+               end
+
+               return type1
+       end
 end
 
 # Mapping between parameters and arguments in a call.
@@ -1689,9 +1797,16 @@ redef class AIsaExpr
                        #var to = if mtype != null then mtype.to_s else "invalid"
                        #debug("adapt {variable}: {from} -> {to}")
 
-                       # Do not adapt if there is no information gain (i.e. adapt to a supertype)
-                       if mtype == null or orig == null or not v.is_subtype(orig, mtype) then
-                               self.after_flow_context.when_true.set_var(v, variable, mtype)
+                       var thentype = v.intersect_types(self, orig, mtype)
+                       if thentype != orig then
+                               self.after_flow_context.when_true.set_var(v, variable, thentype)
+                               #debug "{variable}:{orig or else "?"} isa {mtype or else "?"} -> then {thentype or else "?"}"
+                       end
+
+                       var elsetype = v.diff_types(self, orig, mtype)
+                       if elsetype != orig then
+                               self.after_flow_context.when_false.set_var(v, variable, elsetype)
+                               #debug "{variable}:{orig or else "?"} isa {mtype or else "?"} -> else {elsetype or else "?"}"
                        end
                end
 
diff --git a/tests/base_adaptive_full.nit b/tests/base_adaptive_full.nit
new file mode 100644 (file)
index 0000000..00745e6
--- /dev/null
@@ -0,0 +1,360 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# A comprehensive test to check most cast of adaptive typing with merge, union and intersections.
+#
+# alt1 is for necessary static errors
+# alt2 is for errors due to the lack of union&intersection types
+
+import core::kernel
+
+# Base diamond hierarchy to have types
+
+class A
+end
+class B
+       super A
+end
+class C
+       super A
+end
+class D
+       super B
+       super C
+end
+
+class N
+end
+
+# Base methods to statically check the adapted types.
+
+fun test_a(x:A) do end
+fun test_b(x:B) do end
+fun test_nb(x:nullable B) do end
+fun test_c(x:C) do end
+fun test_nn(x:nullable N) do end
+fun test_o(x:Object) do end
+
+## Intersections and substractions
+
+# Intersection B and C (from B)
+fun inter1(x: B) do
+       if x isa C then
+               test_a(x)
+               #alt2#test_b(x)
+               test_c(x)
+       else
+               test_a(x)
+               test_b(x)
+               #alt1#test_c(x)
+       end
+       test_a(x)
+       test_b(x)
+       #alt1#test_c(x)
+end
+
+# Intersection B and C (from Object)
+fun inter2(x: nullable Object) do
+       if x isa B and x isa C then
+               test_a(x)
+               #alt2#test_b(x)
+               test_c(x)
+       end
+end
+
+# Intersection B and then C (from Object)
+fun inter3(x: nullable Object) do
+       if x isa B then
+               test_a(x)
+               test_b(x)
+               #alt1#test_c(x)
+               if x isa C then
+                       test_a(x)
+                       #alt2#test_b(x)
+                       test_c(x)
+               else
+                       test_a(x)
+                       test_b(x)
+                       #alt1#test_c(x)
+               end
+               #alt2#test_a(x)
+               # The previous one need an explanation: merge(inter(B,C),sub(B,C)) = merge(C,B) = null (because conflict).
+               # Unfortunately the fallback is on Object (instead of B) because the B information in the then branch
+               # is lost and for the typer, `x isa C` is indistinguishable with `x=new C`.
+               #alt2#test_b(x)
+               #alt1#test_c(x)
+               test_o(x)
+       else
+               #alt1#test_a(x)
+               #alt1#test_b(x)
+               #alt1#test_c(x)
+               if x isa C then
+                       test_a(x)
+                       #alt1#test_b(x)
+                       test_c(x)
+               else
+                       #alt1#test_a(x)
+                       #alt1#test_b(x)
+                       #alt1#test_c(x)
+               end
+               #alt1#test_a(x)
+               #alt1#test_b(x)
+               #alt1#test_c(x)
+       end
+       #alt1#test_a(x)
+       #alt1#test_b(x)
+       #alt1#test_c(x)
+end
+
+# Intersection nB and notnull (from nb)
+fun null_inter1n(x: nullable B) do
+       if x != null then
+               test_b(x)
+       else
+               test_nn(x)
+       end
+       test_nb(x)
+       #alt1#test_b(x)
+       #alt1#test_nn(x)
+end
+
+# Intersection nB and notnull (from nObject)
+fun null_inter2n(b: nullable B) do
+       var x
+       x = b
+       if x != null then
+               test_b(x)
+       else
+               test_nb(x)
+               test_nn(x)
+       end
+       test_nb(x)
+       #alt1#test_b(x)
+       #alt1#test_nn(x)
+end
+
+# Intersection nB and Object (from nb)
+fun null_inter1o(x: nullable B) do
+       if x isa A then
+               test_b(x)
+       else
+               test_nb(x)
+               test_nn(x)
+       end
+       test_nb(x)
+       #alt1#test_b(x)
+       #alt1#test_nn(x)
+end
+
+# Intersection nB and Object (from nObject)
+fun null_inter2o(b: nullable B) do
+       var x
+       x = b
+       if x isa A then
+               test_b(x)
+       else
+               test_nb(x)
+               test_nn(x)
+       end
+       test_nb(x)
+       #alt1#test_b(x)
+       #alt1#test_nn(x)
+end
+
+# Intersection Object and nB
+fun null_inter3(x: A) do
+       if x isa nullable B then
+               test_b(x)
+       else
+               test_a(x)
+       end
+       test_a(x)
+end
+
+## Unions
+
+# Union between B and C (with assigment)
+fun union1(b:B, c:C, m: Bool) do
+       var x
+       x = b
+       if m then x = c
+       #alt2#test_a(x)
+       #alt1#test_b(x)
+       #alt1#test_c(x)
+       test_o(x)
+end
+
+# Union between B and C (with isa or isa)
+fun union2(x: nullable Object) do
+       if x isa B or x isa C then
+               #alt2#test_a(x)
+               #alt1#test_b(x)
+               #alt1#test_c(x)
+               test_o(x)
+       end
+end
+
+# Union between B and null (from nullable Object)
+fun null_union(b: B) do
+       var x
+       x = b
+       test_nb(x)
+       test_b(x)
+       if true then x = null
+       test_nb(x)
+       #alt1#test_b(x)
+end
+
+## Loops
+
+# Type adaptation in a loop
+fun loop1(b:B, c:C, m: Bool) do
+       var x
+       x = b
+       while m do
+               #alt2#test_a(x)
+               #alt1#test_b(x)
+               #alt1#test_c(x)
+               test_o(x)
+               x = c
+               test_a(x)
+               #alt1#test_b(x)
+               test_c(x)
+       end
+       #alt2#test_a(x)
+       #alt1#test_b(x)
+       #alt1#test_c(x)
+       test_o(x)
+end
+
+# Union in a loop
+fun loop_union(b:B, c:C, m: Bool) do
+       var x
+       x = b
+       while m do
+               test_o(x)
+               #alt2#test_a(x)
+               #alt1#test_b(x)
+               #alt1#test_c(x)
+               if m then x = c
+               #alt2#test_a(x)
+               #alt1#test_b(x)
+               #alt1#test_c(x)
+               test_o(x)
+       end
+       #alt2#test_a(x)
+       #alt1#test_b(x)
+       #alt1#test_c(x)
+       test_o(x)
+end
+
+# Loop while not null
+fun null_loop_1(b: nullable B) do
+       var x
+       x = b
+       while x != null do
+               test_b(x)
+               test_nb(x)
+               if true then x = null
+               #alt1#test_b(x)
+               test_nb(x)
+       end
+       #alt1#test_b(x)
+       test_nb(x)
+end
+
+# Loop while null
+fun null_loop_2(b: nullable B) do
+       var x
+       x = b
+       while x == null do
+               #alt1#test_b(x)
+               test_nb(x)
+               if true then x = b
+               #alt1#test_b(x)
+               test_nb(x)
+       end
+       test_b(x)
+       test_nb(x)
+end
+
+# Loop while isa (from B)
+fun loop_inter1a(b: B) do
+       var x = b
+       while x isa C do
+               test_a(x)
+               #alt2#test_b(x)
+               test_c(x)
+               x = b
+               test_a(x)
+               test_b(x)
+               #alt1#test_c(x)
+       end
+       test_a(x)
+       test_b(x)
+       #alt1#test_c(x)
+end
+
+# Loop while not isa (from B)
+fun loop_inter2a(b: B) do
+       var x = b
+       while not x isa C do
+               test_a(x)
+               test_b(x)
+               #alt1#test_c(x)
+               x = b
+               test_a(x)
+               test_b(x)
+               #alt1#test_c(x)
+       end
+       test_a(x)
+       #alt2#test_b(x)
+       test_c(x)
+end
+
+# loop while isa (from Object)
+fun loop_inter1b(b: B) do
+       var x
+       x = b
+       while x isa C do
+               test_a(x)
+               #alt2#test_b(x)
+               test_c(x)
+               x = b
+               test_a(x)
+               test_b(x)
+               #alt1#test_c(x)
+       end
+       test_a(x)
+       test_b(x)
+       #alt1#test_c(x)
+end
+
+# loop while not isa (from Object)
+fun loop_inter2b(b: B) do
+       var x
+       x = b
+       while not x isa C do
+               test_a(x)
+               test_b(x)
+               #alt1#test_c(x)
+               x = b
+               test_a(x)
+               test_b(x)
+               #alt1#test_c(x)
+       end
+       test_a(x)
+       #alt2#test_b(x)
+       test_c(x)
+end
diff --git a/tests/sav/base_adaptive_full.res b/tests/sav/base_adaptive_full.res
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/sav/base_adaptive_full_alt1.res b/tests/sav/base_adaptive_full_alt1.res
new file mode 100644 (file)
index 0000000..926e7a0
--- /dev/null
@@ -0,0 +1,56 @@
+alt/base_adaptive_full_alt1.nit:60,10: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:64,9: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:81,10: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:89,11: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:96,10: Type Error: expected `C`, got `Object`.
+alt/base_adaptive_full_alt1.nit:99,10: Type Error: expected `A`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:100,10: Type Error: expected `B`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:101,10: Type Error: expected `C`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:104,11: Type Error: expected `B`, got `C`.
+alt/base_adaptive_full_alt1.nit:107,11: Type Error: expected `A`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:108,11: Type Error: expected `B`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:109,11: Type Error: expected `C`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:111,10: Type Error: expected `A`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:112,10: Type Error: expected `B`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:113,10: Type Error: expected `C`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:115,9: Type Error: expected `A`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:116,9: Type Error: expected `B`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:117,9: Type Error: expected `C`, got `nullable Object`.
+alt/base_adaptive_full_alt1.nit:128,9: Type Error: expected `B`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:129,10: Type Error: expected `nullable N`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:143,9: Type Error: expected `B`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:144,10: Type Error: expected `nullable N`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:156,9: Type Error: expected `B`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:157,10: Type Error: expected `nullable N`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:171,9: Type Error: expected `B`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:172,10: Type Error: expected `nullable N`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:193,9: Type Error: expected `B`, got `Object`.
+alt/base_adaptive_full_alt1.nit:194,9: Type Error: expected `C`, got `Object`.
+alt/base_adaptive_full_alt1.nit:202,10: Type Error: expected `B`, got `Object`.
+alt/base_adaptive_full_alt1.nit:203,10: Type Error: expected `C`, got `Object`.
+alt/base_adaptive_full_alt1.nit:216,9: Type Error: expected `B`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:227,10: Type Error: expected `B`, got `Object`.
+alt/base_adaptive_full_alt1.nit:228,10: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:228,10: Type Error: expected `C`, got `Object`.
+alt/base_adaptive_full_alt1.nit:232,10: Type Error: expected `B`, got `C`.
+alt/base_adaptive_full_alt1.nit:236,9: Type Error: expected `B`, got `Object`.
+alt/base_adaptive_full_alt1.nit:237,9: Type Error: expected `C`, got `Object`.
+alt/base_adaptive_full_alt1.nit:248,10: Type Error: expected `B`, got `Object`.
+alt/base_adaptive_full_alt1.nit:249,10: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:249,10: Type Error: expected `C`, got `Object`.
+alt/base_adaptive_full_alt1.nit:252,10: Type Error: expected `B`, got `Object`.
+alt/base_adaptive_full_alt1.nit:253,10: Type Error: expected `C`, got `Object`.
+alt/base_adaptive_full_alt1.nit:257,9: Type Error: expected `B`, got `Object`.
+alt/base_adaptive_full_alt1.nit:258,9: Type Error: expected `C`, got `Object`.
+alt/base_adaptive_full_alt1.nit:270,10: Type Error: expected `B`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:273,9: Type Error: expected `B`, got `null`.
+alt/base_adaptive_full_alt1.nit:282,10: Type Error: expected `B`, got `null`.
+alt/base_adaptive_full_alt1.nit:285,10: Type Error: expected `B`, got `nullable B`.
+alt/base_adaptive_full_alt1.nit:302,10: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:306,9: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:315,10: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:319,10: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:337,10: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:341,9: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:351,10: Type Error: expected `C`, got `B`.
+alt/base_adaptive_full_alt1.nit:355,10: Type Error: expected `C`, got `B`.
diff --git a/tests/sav/base_adaptive_full_alt2.res b/tests/sav/base_adaptive_full_alt2.res
new file mode 100644 (file)
index 0000000..117b18b
--- /dev/null
@@ -0,0 +1,16 @@
+alt/base_adaptive_full_alt2.nit:55,10: Type Error: expected `B`, got `C`.
+alt/base_adaptive_full_alt2.nit:71,10: Type Error: expected `B`, got `C`.
+alt/base_adaptive_full_alt2.nit:84,11: Type Error: expected `B`, got `C`.
+alt/base_adaptive_full_alt2.nit:91,10: Type Error: expected `A`, got `Object`.
+alt/base_adaptive_full_alt2.nit:95,10: Type Error: expected `B`, got `Object`.
+alt/base_adaptive_full_alt2.nit:192,9: Type Error: expected `A`, got `Object`.
+alt/base_adaptive_full_alt2.nit:201,10: Type Error: expected `A`, got `Object`.
+alt/base_adaptive_full_alt2.nit:226,10: Type Error: expected `A`, got `Object`.
+alt/base_adaptive_full_alt2.nit:235,9: Type Error: expected `A`, got `Object`.
+alt/base_adaptive_full_alt2.nit:247,10: Type Error: expected `A`, got `Object`.
+alt/base_adaptive_full_alt2.nit:251,10: Type Error: expected `A`, got `Object`.
+alt/base_adaptive_full_alt2.nit:256,9: Type Error: expected `A`, got `Object`.
+alt/base_adaptive_full_alt2.nit:297,10: Type Error: expected `B`, got `C`.
+alt/base_adaptive_full_alt2.nit:322,9: Type Error: expected `B`, got `C`.
+alt/base_adaptive_full_alt2.nit:332,10: Type Error: expected `B`, got `C`.
+alt/base_adaptive_full_alt2.nit:358,9: Type Error: expected `B`, got `C`.
index 4c5dbc5..90799da 100644 (file)
@@ -1,3 +1,3 @@
 alt/base_adaptive_loop_array_1alt2_alt1.nit:26,10--15: Error: method `length` does not exists in `Int`.
-alt/base_adaptive_loop_array_1alt2_alt1.nit:26,10--15: Error: method `length` does not exists in `nullable Object`.
-alt/base_adaptive_loop_array_1alt2_alt1.nit:28,3--8: Error: method `length` does not exists in `nullable Object`.
+alt/base_adaptive_loop_array_1alt2_alt1.nit:26,10--15: Error: method `length` does not exists in `Object`.
+alt/base_adaptive_loop_array_1alt2_alt1.nit:28,3--8: Error: method `length` does not exists in `Object`.
index 58c7b04..c861a32 100644 (file)
@@ -1,2 +1,2 @@
-alt/base_adaptive_loop_array_alt1.nit:26,10--15: Error: method `length` does not exists in `nullable Object`.
-alt/base_adaptive_loop_array_alt1.nit:28,3--8: Error: method `length` does not exists in `nullable Object`.
+alt/base_adaptive_loop_array_alt1.nit:26,10--15: Error: method `length` does not exists in `Object`.
+alt/base_adaptive_loop_array_alt1.nit:28,3--8: Error: method `length` does not exists in `Object`.
index 661cf83..153c634 100644 (file)
@@ -1 +1 @@
-alt/base_adaptive_loop_call_alt1.nit:57,8--10: Error: method `foo` does not exists in `nullable Object`.
+alt/base_adaptive_loop_call_alt1.nit:57,8--10: Error: method `foo` does not exists in `Object`.
index fe426c4..2394059 100644 (file)
@@ -1,5 +1,5 @@
 base_isa_nil.nit:33,2--13: Warning: expression is already a `Object`.
-base_isa_nil.nit:36,2--22: Warning: expression is already a `nullable Object`.
+base_isa_nil.nit:36,2--22: Warning: expression is already a `nullable Object` since it is a `Object`.
 base_isa_nil.nit:43,2--22: Warning: expression is already a `nullable Object`.
 true
 true
index cc41e02..60a0b47 100644 (file)
@@ -1 +1 @@
-alt/base_var_untyped_alt4.nit:44,4--5: Error: method `+` does not exists in `nullable Object`.
+alt/base_var_untyped_alt4.nit:44,4--5: Error: method `+` does not exists in `Object`.
index e644c3d..22f2cd0 100644 (file)
@@ -1 +1 @@
-alt/base_var_untyped_alt5.nit:51,4: Error: method `*` does not exists in `nullable Object`.
+alt/base_var_untyped_alt5.nit:51,4: Error: method `*` does not exists in `Object`.