fun split_once_on(p: Pattern): Array[SELFTYPE]
do
var m = p.search_in(self, 0)
- if m == null then return [self]
- return new Array[SELFTYPE].with_items(substring(0, m.from), substring_from(m.after))
+ var res = new Array[SELFTYPE]
+ if m == null then
+ res.add self
+ else
+ res.add substring(0, m.from)
+ res.add substring_from(m.after)
+ end
+ return res
end
# Replace all occurences of a pattern with a string
return sub
end
- redef fun check_subtype(node: ANode, sub, sup: MType): nullable MType
+ redef fun check_subtype(node: ANode, sub, sup: MType, autocast: Bool): nullable MType
do
var res = super
if node isa AAsCastExpr then
return res
end
+ if not autocast then
+ return res
+ end
sup = supx.resolve_for(anchor.mclass.mclass_type, anchor, mmodule, true)
if self.is_subtype(sub, sup) then
dcp.cpt_autocast.inc("vt")
mtype = v.cleanup_type(mtype).as(not null)
var prop = v.get_method(mtype, "with_native")
v.add_monomorphic_send(mtype, prop)
+ v.add_callsite(with_capacity_callsite)
+ v.add_callsite(push_callsite)
end
end
# If `sub` is a safe subtype of `sup` then return `sub`.
# If `sub` is an unsafe subtype (ie an implicit cast is required), then return `sup`.
#
- # The point of the return type is to determinate the usable type on an expression:
+ # The point of the return type is to determinate the usable type on an expression when `autocast` is true:
# If the suptype is safe, then the return type is the one on the expression typed by `sub`.
# Is the subtype is unsafe, then the return type is the one of an implicit cast on `sup`.
- fun check_subtype(node: ANode, sub, sup: MType): nullable MType
+ fun check_subtype(node: ANode, sub, sup: MType, autocast: Bool): nullable MType
do
if self.is_subtype(sub, sup) then return sub
- if self.is_subtype(sub, self.anchor_to(sup)) then
+ if autocast and self.is_subtype(sub, self.anchor_to(sup)) then
# FIXME workaround to the current unsafe typing policy. To remove once fixed virtual types exists.
#node.debug("Unsafe typing: expected {sup}, got {sub}")
return sup
if sup == null then return null # Forward error
- var res = check_subtype(nexpr, sub, sup)
+ var res = check_subtype(nexpr, sub, sup, true)
if res != sub then
nexpr.implicit_cast_to = res
end
var value_type = v.visit_expr_subtype(self.n_value, msignature.mparameters.first.mtype)
if value_type == null then return null # Skip error
- v.check_subtype(self, rettype, writetype)
+ v.check_subtype(self, rettype, writetype, false)
return rettype
end
end
end
set_comprehension(e)
if mtype != null then
- if v.check_subtype(e, t, mtype) == null then return # Skip error
+ if v.check_subtype(e, t, mtype, false) == null then return # Forward error
if t == mtype then useless = true
else
mtypes.add(t)
import astvalidation
import semantize
intrude import semantize::scope
+intrude import semantize::typing
redef class ToolContext
var transform_phase: Phase = new TransformPhase(self, [typing_phase, auto_super_init_phase])
end
super
end
+
+ redef fun replace_with(other)
+ do
+ super
+ if other isa AExpr then
+ if other.implicit_cast_to == null then other.implicit_cast_to = implicit_cast_to
+ end
+ end
end
redef class AVardeclExpr
--- /dev/null
+# 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.
+
+import standard::collection::array
+
+class A
+ type V: nullable Object
+ var v: V
+
+ fun test_array: Array[V]
+ do
+ #alt3#v = 10
+ return [v] #alt1-2#
+ #alt1#return [10:V]
+ #alt2#return [10]
+ end
+end
+
+class B
+ super A
+ redef type V: Bool
+end
+
+var a = new A(1)
+
+a.test_array.first.output
+
+var ab = new A(true)
+
+ab.test_array.first.output
+
+var b = new B(true)
+
+b.test_array.first.output
--- /dev/null
+1
+true
+true
--- /dev/null
+alt/base_autocast_array_alt1.nit:25,11--12: Type Error: expected `V`, got `Int`.
--- /dev/null
+Runtime error: Cast failed. Expected `Array[V]`, got `Array[Int]` (alt/base_autocast_array_alt2.nit:26)
+10
+10
--- /dev/null
+Runtime error: Cast failed. Expected `V`, got `Int` (alt/base_autocast_array_alt3.nit:23)
+10
+10
--- /dev/null
+Runtime error: Cast failed (alt/base_autocast_array_alt2.nit:45)
+10
+10