From: Jean Privat Date: Fri, 19 Jun 2009 15:56:45 +0000 (-0400) Subject: syntax: var assignment can bypass casted type X-Git-Tag: v0.3~243 X-Git-Url: http://nitlanguage.org syntax: var assignment can bypass casted type If rvalue is conform with casted type then variable remains casted else if rvalue is conform with base type then # It is the novelty variable is (up)casted to its base type else error Example: var x: T x.u_only_method # error assert x isa U x.u_only_method # ok x = a_t # ok x.u_only_method # error Signed-off-by: Jean Privat --- diff --git a/src/syntax/typing.nit b/src/syntax/typing.nit index 4300a8f..679b88e 100644 --- a/src/syntax/typing.nit +++ b/src/syntax/typing.nit @@ -544,7 +544,12 @@ redef class AVarAssignExpr do v.variable_ctx.mark_is_set(variable) var t = v.variable_ctx.stype(variable) - v.check_conform_expr(n_value, t) + if v.check_conform_expr(n_value, variable.stype) then + # Fall back to base type if current type does not match + if not n_value.stype < t then + v.variable_ctx.stype(variable) = variable.stype + end + end _is_typed = true end end @@ -584,7 +589,12 @@ redef class AVarReassignExpr var t = v.variable_ctx.stype(variable) var t2 = do_rvalue_typing(v, t) if t2 == null then return - v.check_conform(self, t2, n_value.stype) + if v.check_conform(self, t2, variable.stype) then + # Fall back to base type if current type does not match + if not t2 < t then + v.variable_ctx.stype(variable) = variable.stype + end + end _is_typed = true end end diff --git a/tests/base_isa_cast2.nit b/tests/base_isa_cast2.nit new file mode 100644 index 0000000..4bccc58 --- /dev/null +++ b/tests/base_isa_cast2.nit @@ -0,0 +1,62 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2009 Jean Privat +# +# 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. + +import kernel + +class A + init do end +end + +class B +special A + meth foo(i: Int) do i.output + init do end +end + +var a: A = new B +if a isa B then + a.foo(1) + a = new B + a.foo(2) + a = new A + #alt1#a.foo(-1) +else +#alt2#a.foo(-2) +end +#alt3#a.foo(-3) + +if not a isa B then + #alt4#a.foo(-4) + a = new B + assert a isa B + a.foo(3) +end +#alt8#a.foo(4) + +while a isa B do + #alt8#a.foo(5) + a = new A + #alt5#a.foo(-5) +end +#alt6#a.foo(-6) + +while not a isa B do + #alt7#a.foo(-7) + a = new B + assert a isa B + a.foo(6) +end +#alt8#a.foo(7) diff --git a/tests/sav/base_isa_cast2.sav b/tests/sav/base_isa_cast2.sav new file mode 100644 index 0000000..c65db77 --- /dev/null +++ b/tests/sav/base_isa_cast2.sav @@ -0,0 +1,4 @@ +1 +2 +3 +6 diff --git a/tests/sav/base_isa_cast2_alt1.sav b/tests/sav/base_isa_cast2_alt1.sav new file mode 100644 index 0000000..148bc33 --- /dev/null +++ b/tests/sav/base_isa_cast2_alt1.sav @@ -0,0 +1 @@ +alt/base_isa_cast2_alt1.nit:35,2--9: Error: Method 'foo' doesn't exists in A. diff --git a/tests/sav/base_isa_cast2_alt2.sav b/tests/sav/base_isa_cast2_alt2.sav new file mode 100644 index 0000000..9e5a166 --- /dev/null +++ b/tests/sav/base_isa_cast2_alt2.sav @@ -0,0 +1 @@ +alt/base_isa_cast2_alt2.nit:37,1--8: Error: Method 'foo' doesn't exists in A. diff --git a/tests/sav/base_isa_cast2_alt3.sav b/tests/sav/base_isa_cast2_alt3.sav new file mode 100644 index 0000000..65186d9 --- /dev/null +++ b/tests/sav/base_isa_cast2_alt3.sav @@ -0,0 +1 @@ +alt/base_isa_cast2_alt3.nit:39,1--8: Error: Method 'foo' doesn't exists in A. diff --git a/tests/sav/base_isa_cast2_alt4.sav b/tests/sav/base_isa_cast2_alt4.sav new file mode 100644 index 0000000..3d2c680 --- /dev/null +++ b/tests/sav/base_isa_cast2_alt4.sav @@ -0,0 +1 @@ +alt/base_isa_cast2_alt4.nit:42,2--9: Error: Method 'foo' doesn't exists in A. diff --git a/tests/sav/base_isa_cast2_alt5.sav b/tests/sav/base_isa_cast2_alt5.sav new file mode 100644 index 0000000..0b93912 --- /dev/null +++ b/tests/sav/base_isa_cast2_alt5.sav @@ -0,0 +1 @@ +alt/base_isa_cast2_alt5.nit:52,2--9: Error: Method 'foo' doesn't exists in A. diff --git a/tests/sav/base_isa_cast2_alt6.sav b/tests/sav/base_isa_cast2_alt6.sav new file mode 100644 index 0000000..21595bf --- /dev/null +++ b/tests/sav/base_isa_cast2_alt6.sav @@ -0,0 +1 @@ +alt/base_isa_cast2_alt6.nit:54,1--8: Error: Method 'foo' doesn't exists in A. diff --git a/tests/sav/base_isa_cast2_alt7.sav b/tests/sav/base_isa_cast2_alt7.sav new file mode 100644 index 0000000..33bd723 --- /dev/null +++ b/tests/sav/base_isa_cast2_alt7.sav @@ -0,0 +1 @@ +alt/base_isa_cast2_alt7.nit:57,2--9: Error: Method 'foo' doesn't exists in A. diff --git a/tests/sav/base_isa_cast2_alt8.sav b/tests/sav/base_isa_cast2_alt8.sav new file mode 100644 index 0000000..c378c50 --- /dev/null +++ b/tests/sav/base_isa_cast2_alt8.sav @@ -0,0 +1,3 @@ +alt/base_isa_cast2_alt8.nit:47,1--7: Error: Method 'foo' doesn't exists in A. +alt/base_isa_cast2_alt8.nit:50,2--8: Error: Method 'foo' doesn't exists in A. +alt/base_isa_cast2_alt8.nit:62,1--7: Error: Method 'foo' doesn't exists in A.