Merge: New syntax for typed literal arrays
authorJean Privat <jean@pryen.org>
Thu, 25 Sep 2014 21:41:09 +0000 (17:41 -0400)
committerJean Privat <jean@pryen.org>
Thu, 25 Sep 2014 21:41:09 +0000 (17:41 -0400)
Currenlty there is only
~~~.nit
var a = [1, 2] # a isa Array[Int]
var b = [1, true] # Type Error: ambiguous array type Int Bool
var c = new Array[Object].with_items(1, true) # c isa Array[Object]
~~~

Now, there is also
~~~.nit
var d = [1, true: Object] # d isa Array[Object]
var e = [1, 2: Numeric] # e isa Array[Numeric]
var f = [1, 2: Int] # f isa Array[Int] but with a warning for the useless `:Int`
~~~

Pull-Request: #772
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

1  2 
src/semantize/typing.nit

diff --combined src/semantize/typing.nit
@@@ -1097,19 -1097,37 +1097,37 @@@ redef class AArrayExp
  
        redef fun accept_typing(v)
        do
+               var mtype: nullable MType = null
+               var ntype = self.n_type
+               if ntype != null then
+                       mtype = v.resolve_mtype(ntype)
+                       if mtype == null then return # Skip error
+               end
                var mtypes = new Array[nullable MType]
+               var useless = false
                for e in self.n_exprs.n_exprs do
                        var t = v.visit_expr(e)
                        if t == null then
                                return # Skip error
                        end
-                       mtypes.add(t)
+                       if mtype != null then
+                               if v.check_subtype(e, t, mtype) == null then return # Skip error
+                               if t == mtype then useless = true
+                       else
+                               mtypes.add(t)
+                       end
+               end
+               if mtype == null then
+                       mtype = v.merge_types(self, mtypes)
                end
-               var mtype = v.merge_types(self, mtypes)
                if mtype == null then
                        v.error(self, "Type Error: ambiguous array type {mtypes.join(" ")}")
                        return
                end
+               if useless then
+                       assert ntype != null
+                       v.modelbuilder.warning(ntype, "useless-type", "Warning: useless type declaration `{mtype}` in literal Array since it can be inferred from the elements type.")
+               end
                var mclass = v.get_mclass(self, "Array")
                if mclass == null then return # Forward error
                var array_mtype = mclass.get_mtype([mtype])
@@@ -1489,16 -1507,14 +1507,16 @@@ redef class ASuperExp
  
        redef fun accept_typing(v)
        do
 -              var recvtype = v.anchor
 +              var anchor = v.anchor
 +              assert anchor != null
 +              var recvtype = v.get_variable(self, v.selfvariable)
                assert recvtype != null
                var mproperty = v.mpropdef.mproperty
                if not mproperty isa MMethod then
                        v.error(self, "Error: super only usable in a method")
                        return
                end
 -              var superprops = mproperty.lookup_super_definitions(v.mmodule, recvtype)
 +              var superprops = mproperty.lookup_super_definitions(v.mmodule, anchor)
                if superprops.length == 0 then
                        if mproperty.is_init and v.mpropdef.is_intro then
                                process_superinit(v)
  
        private fun process_superinit(v: TypeVisitor)
        do
 -              var recvtype = v.anchor
 +              var anchor = v.anchor
 +              assert anchor != null
 +              var recvtype = v.get_variable(self, v.selfvariable)
                assert recvtype != null
                var mpropdef = v.mpropdef
                assert mpropdef isa MMethodDef
                var mproperty = mpropdef.mproperty
                var superprop: nullable MMethodDef = null
                for msupertype in mpropdef.mclassdef.supertypes do
 -                      msupertype = msupertype.anchor_to(v.mmodule, recvtype)
 +                      msupertype = msupertype.anchor_to(v.mmodule, anchor)
                        var errcount = v.modelbuilder.toolcontext.error_count
                        var candidate = v.try_get_mproperty_by_name2(self, msupertype, mproperty.name).as(nullable MMethod)
                        if candidate == null then
                                v.error(self, "Error: conflicting super constructor to call for {mproperty}: {candidate.full_name}, {superprop.mproperty.full_name}")
                                return
                        end
 -                      var candidatedefs = candidate.lookup_definitions(v.mmodule, recvtype)
 +                      var candidatedefs = candidate.lookup_definitions(v.mmodule, anchor)
                        if superprop != null and superprop.mproperty == candidate then
                                if superprop == candidatedefs.first then continue
                                candidatedefs.add(superprop)