nitc: remove a warning on casts on MMTypeFormal
[nit.git] / src / syntax / typing.nit
index ff50f0f..c3ef59c 100644 (file)
@@ -289,6 +289,15 @@ redef class AExternInitPropdef
        end
 end
 
+redef class ASignature
+       redef fun after_typing(v)
+       do
+               if self.n_opar != null and self.n_params.is_empty then
+                       v.warning(self, "Warning: superfluous parentheses.")
+               end
+       end
+end
+
 redef class AParam
        redef fun after_typing(v)
        do
@@ -389,6 +398,27 @@ redef class AExpr
 
        # The control flow information if current boolean expression is false
        readable private var _if_false_flow_ctx: nullable FlowContext
+
+       # Wharn in case of superfluous parentheses
+       private fun warn_parentheses(v: AbsSyntaxVisitor)
+       do
+       end
+end
+
+redef class AParExpr
+       redef fun warn_parentheses(v)
+       do
+               v.warning(self, "Warning: superfluous parentheses.")
+       end
+end
+
+redef class AParExprs
+       redef fun after_typing(v)
+       do
+               if n_exprs.is_empty then
+                       v.warning(self, "Warning: superfluous parentheses.")
+               end
+       end
 end
 
 redef class AVardeclExpr
@@ -454,6 +484,9 @@ redef class AReturnExpr
                else if e != null and t != null then
                        v.check_conform_expr(e, t)
                end
+               if e != null then
+                       e.warn_parentheses(v)
+               end
                _is_typed = true
        end
 end
@@ -471,12 +504,16 @@ redef class AContinueExpr
                end
 
                var t = esc.continue_stype
-               if n_expr == null and t != null then
+               var e = n_expr
+               if e == null and t != null then
                        v.error(self, "Error: continue with a value required in this block.")
-               else if n_expr != null and t == null then
+               else if e != null and t == null then
                        v.error(self, "Error: continue without value required in this block.")
-               else if n_expr != null and t != null then
-                       v.check_conform_expr(n_expr.as(not null), t)
+               else if e != null and t != null then
+                       v.check_conform_expr(e, t)
+               end
+               if e != null then
+                       e.warn_parentheses(v)
                end
                _is_typed = true
        end
@@ -493,13 +530,17 @@ redef class ABreakExpr
                esc.break_flow_contexts.add(old_flow_ctx)
 
                var bl = esc.break_list
-               if n_expr == null and bl != null then
+               var e = n_expr
+               if e == null and bl != null then
                        v.error(self, "Error: break with a value required in this block.")
-               else if n_expr != null and bl == null then
+               else if e != null and bl == null then
                        v.error(self, "Error: break without value required in this block.")
-               else if n_expr != null and bl != null then
+               else if e != null and bl != null then
                        # Typing check can only be done later
-                       bl.add(n_expr.as(not null))
+                       bl.add(e)
+               end
+               if e != null then
+                       e.warn_parentheses(v)
                end
                _is_typed = true
        end
@@ -514,7 +555,7 @@ redef class AAbortExpr
 end
 
 # An abstract control structure with feature escapable block
-class AAbsControl
+abstract class AAbsControl
        super AExpr
        # The corresponding escapable block
        readable var _escapable: nullable EscapableBlock
@@ -575,6 +616,8 @@ redef class AIfExpr
                v.enter_visit(n_expr)
                v.check_conform_expr(n_expr, v.type_bool)
 
+               n_expr.warn_parentheses(v)
+
                # Prepare 'then' context
                var old_flow_ctx = v.flow_ctx
                v.use_if_true_flow_ctx(n_expr)
@@ -615,6 +658,8 @@ redef class AWhileExpr
 
                if n_expr isa ATrueExpr then
                        v.warning(self, "Warning: use 'loop' instead of 'while true do'.")
+               else
+                       n_expr.warn_parentheses(v)
                end
 
                # Prepare inside context (assert cond)
@@ -692,6 +737,7 @@ redef class AForExpr
                        v.error(n_expr, "Type error: 'for' on a nullable expression.")
                        return
                end
+               n_expr.warn_parentheses(v)
 
                # Get iterate
                var iterate_name = once "iterate".to_symbol
@@ -737,6 +783,7 @@ redef class AAssertExpr
                # Process condition
                v.enter_visit(n_expr)
                v.check_conform_expr(n_expr, v.type_bool)
+               n_expr.warn_parentheses(v)
 
                # Process optional 'else' part
                if n_else != null then
@@ -996,7 +1043,7 @@ redef class AOrElseExpr
                # Consider the type of the left operand
                var t = n_expr.stype
                if not t.is_nullable then
-                       v.warning(n_expr, "Warning: left operant of a 'or else' is not a nullable type.")
+                       v.warning(n_expr, "Warning: left operand of a 'or else' is not a nullable type.")
                else
                        t = t.as_notnull
                end
@@ -1081,7 +1128,7 @@ end
 redef class AArrayExpr
        redef fun after_typing(v)
        do
-               var stype = v.check_conform_multiexpr(null, n_exprs)
+               var stype = v.check_conform_multiexpr(null, n_exprs.n_exprs)
                if stype != null then do_typing(v, stype)
        end
 
@@ -1139,7 +1186,7 @@ redef class ASuperExpr
                        assert p isa MMMethod
                        _init_in_superclass = p
                        register_super_init_call(v, p)
-                       if n_args.length > 0 then
+                       if n_args.n_exprs.length > 0 then
                                var signature = get_signature(v, v.self_var.stype.as(not null), p, true)
                                process_signature(v, signature, p.name, compute_raw_arguments)
                        end
@@ -1575,9 +1622,6 @@ redef class ASuperInitCall
                                if c == prev_class then
                                        prev_class = null
                                else if c == cla then
-                                       if prev_class != null then
-                                               v.error(self, "Error: Constructor of {c} must be invoked before constructor of {prev_class}")
-                                       end
                                        esic.add(property)
                                        break
                                end
@@ -1597,6 +1641,9 @@ redef class ANewExpr
                        v.error(self, "Error: try to instantiate abstract class {t.local_class}.")
                        return
                end
+               if t.is_nullable then
+                       v.error(self, "Type error: cannot instantiate the nullable type {t}.")
+               end
                var name: Symbol
                if n_id == null then
                        name = once "init".to_symbol
@@ -1708,7 +1755,7 @@ redef class AEqExpr
 
                if n_expr.stype isa MMTypeNone then
                        if n_expr2.stype isa MMTypeNone then
-                               v.warning(self, "Warning: comparaison between 2 null values.")
+                               v.warning(self, "Warning: comparaison between two null values.")
                        else
                                try_to_isa(v, n_expr2)
                        end
@@ -1739,7 +1786,7 @@ redef class ANeExpr
 
                if n_expr.stype isa MMTypeNone then
                        if n_expr2.stype isa MMTypeNone then
-                               v.warning(self, "Warning: comparaison between 2 null values.")
+                               v.warning(self, "Warning: comparaison between two null values.")
                        else
                                try_to_isa(v, n_expr2)
                        end
@@ -1811,7 +1858,7 @@ redef class ACallFormExpr
                                        n = new AClosureCallExpr.init_aclosurecallexpr(n_id, n_args, n_closure_defs)
                                        n._variable = variable
                                else
-                                       if not n_args.is_empty then
+                                       if not n_args.n_exprs.is_empty or n_args isa AParExprs then
                                                v.error(self, "Error: {name} is variable, not a function.")
                                                return
                                        end
@@ -1991,7 +2038,7 @@ redef class AClosureDef
        end
 end
 
-class ATypeCheckExpr
+abstract class ATypeCheckExpr
        super AExpr
        private fun check_expr_cast(v: TypingVisitor, n_expr: AExpr, n_type: AType)
        do
@@ -2002,7 +2049,10 @@ class ATypeCheckExpr
                if etype == ttype then
                        v.warning(self, "Warning: Expression is already a {ttype}.")
                else if etype < ttype then
-                       v.warning(self, "Warning: Expression is already a {ttype} since it is a {etype}.")
+                       if not ttype isa MMTypeFormal then
+                               # the old metamodel is not that great with formal types
+                               v.warning(self, "Warning: Expression is already a {ttype} since it is a {etype}.")
+                       end
                else if etype isa MMTypeNone then
                        # ttype is not nullable because of prevous test
                        v.warning(self, "Warning: Expression is null therefore cannot be a {ttype}.")
@@ -2094,3 +2144,15 @@ redef class AOnceExpr
        end
 end
 
+redef class ADebugTypeExpr
+       redef fun after_typing(v)
+       do
+               if not v.check_expr(n_expr) then return
+               if not n_type.is_typed then return
+               var etype = n_expr.stype
+               var ttype = n_type.stype
+               if etype != ttype then
+                       v.warning(self, "Warning: Expression is a {etype}, expected {ttype}.")
+               end
+       end
+end