In order to fix #86 and #1238 some preliminary work to solve remaining issues with the type system is needed. This PR is a step toward this goal.
This introduce not-null types, that is a modifier to indicate that a type cannot contain null.
Basically, this new modifier is almost useless because it is the semantic of all the types (except obviously null and nullable things). Except in one case: when one adapts a formal type whose bound is nullable.
Before the PR, the semantic was the following
~~~nit
class A[E: nullable Object]
fun foo(e: E, o: nullable Object) do
var o2 = o.as(not null) # the static type of o2 is `Object`
print o2 # OK
var e2 = e.as(not null) # the static type of e2 is still `E` because there is no `nullable` to remove
print e2 # Error: expected Object, got E
end
end
~~~
Obviously, the issue was not that important because people managed to program complex things in Nit and I do not remember getting some complain about that particular issue. For the rare cases of this unexpected behavior, a workaround was possible: to cast on the non-nullable bound
~~~nit
var e2 = e.as(Object)
print e2 # OK
~~~
Nevertheless, the behavior was still buggy since type information was lost and not POLA. Moreover, `!= null` and `or else` did not have a workaround.
So, this PR introduces a special new type-modifier for this case so that everything become sensible.
~~~nit
var e2 = e.as(not null) # the static type of e2 is now `not null E`
print e2 # OK
~~~
Moreover, a lot of local refactorisation was done in model.nit and typing.nit to clean and harmonize the code. So that independently of the new notnull modifier, the code is cleaner, some bugs where removed and some small features added, especially the detection of useless `or else`.
Last, but not least, the `not null` thing is only an internal modifier and is not usable as a syntactic type construction (the grammar and the AST is unchanged); `not null` can however be shown to the programmer in messages.
~~~nit
var e2 = e.as(not null) # the static type of e2 is now `not null E`
var e3 = e2.as(not null) # << Warning: expression is not null, since it is a `not null E` >>
~~~
I could easily add `not null` as a specific syntactic construction since everything internally is ready. but 1. does this worth it?. 2. I do not want to conflict with #1243 that also change the grammar.
As an example, is it useful to write the following? (currently refused but very easy to add after this PR)
~~~nit
class A[E: nullable Object]
fun foo(e: not null E): not null E do
var x = e.to_s # no null pointer exception
# ...
return e
end
end
var a = new A[nullable Int]
var i = a.foo(5)
~~~
Pull-Request: #1244
Reviewed-by: Etienne M. Gagnon <egagnon@j-meg.com>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
end
var ben = new Benitlux("sherbrooke")
-ben.run(opts.send_emails.value or else false)
+ben.run(opts.send_emails.value)
# The parsing logic for the wellington locaiton is active (to gather data)
# but the web interface do not allow to subscribe to its mailing list.
#
# TODO revamp mailing list Web interface
ben = new Benitlux("wellington")
-ben.run(opts.send_emails.value or else false)
+ben.run(opts.send_emails.value)
end
if current_in != null then
- in_set(block) = current_in.as(not null)
+ in_set(block) = current_in
else
continue
end
var old_out = out_set(block)
for line in block.lines do
- self.current_in = current_in.as(not null)
+ self.current_in = current_in
self.current_out = empty_set
pre_line_visit(line)
enter_visit(line)
print "result:{state}"
for n in path do
var a = n.action
- if a != null then print " + {a or else ""}"
+ if a != null then print " + {a}"
print " {n.steps}: {n.state} ({n.cost}$)"
end
end
if obj isa JsonObject then
if obj.keys.has("message") then
var title = "GithubAPIError"
- var msg = obj["message"].to_s or else ""
+ var msg = obj["message"].to_s
var err = new GithubError(msg, title)
err.json["requested_uri"] = uri
err.json["status_code"] = response.status_code
# This module introduces the standard array structure.
# It also implements two other abstract collections : ArrayMap and ArraySet
-module array
+module array is
+ no_warning "useless-type-test" # to avoid warning with nitc while compiling with c_src
+end
import abstract_collection
var oldnode = v.current_node
v.current_node = self
var old_frame = v.frame
- var frame = new StaticFrame(v, self.mpropdef.as(not null), recv.mcasttype.as_notnullable.as(MClassType), [recv])
+ var frame = new StaticFrame(v, self.mpropdef.as(not null), recv.mcasttype.undecorate.as(MClassType), [recv])
v.frame = frame
var value
var mtypes_by_class = new MultiHashMap[MClass, MType]
for e in mtypes do
- var c = e.as_notnullable.as(MClassType).mclass
+ var c = e.undecorate.as(MClassType).mclass
mtypes_by_class[c].add(e)
poset.add_node(e)
end
var casttypes_by_class = new MultiHashMap[MClass, MType]
for e in cast_types do
- var c = e.as_notnullable.as(MClassType).mclass
+ var c = e.undecorate.as(MClassType).mclass
casttypes_by_class[c].add(e)
poset.add_node(e)
end
# Group cast_type by their classes
var bucklets = new HashMap[MClass, Set[MType]]
for e in cast_types do
- var c = e.as_notnullable.as(MClassType).mclass
+ var c = e.undecorate.as(MClassType).mclass
if not bucklets.has_key(c) then
bucklets[c] = new HashSet[MType]
end
# resolution table (for receiver)
if is_live then
- var mclass_type = mtype.as_notnullable
+ var mclass_type = mtype.undecorate
assert mclass_type isa MClassType
if resolution_tables[mclass_type].is_empty then
v.add_decl("NULL, /*NO RESOLUTIONS*/")
fun compile_type_resolution_table(mtype: MType) do
- var mclass_type = mtype.as_notnullable.as(MClassType)
+ var mclass_type = mtype.undecorate.as(MClassType)
# extern const struct resolution_table_X resolution_table_X
self.provide_declaration("resolution_table_{mtype.c_name}", "extern const struct types resolution_table_{mtype.c_name};")
fun can_be_primitive(value: RuntimeVariable): Bool
do
- var t = value.mcasttype.as_notnullable
+ var t = value.mcasttype.undecorate
if not t isa MClassType then return false
var k = t.mclass.kind
return k == interface_kind or t.is_c_primitive
end
end
+redef class MNotNullType
+ redef fun infobox(v)
+ do
+ return mtype.infobox(v)
+ end
+ redef fun linkto
+ do
+ var res = new HTMLTag("span")
+ res.append("not null ").add(mtype.linkto)
+ return res
+ end
+end
+
+redef class MNullType
+ redef fun infobox(v)
+ do
+ var res = new HInfoBox(v, to_s)
+ return res
+ end
+ redef fun linkto
+ do
+ var res = new HTMLTag("span")
+ res.append("null")
+ return res
+ end
+end
+
redef class MSignature
redef fun linkto
do
do
var mt = mtype
if mt == null then return null
- mt = mt.as_notnullable
- if mt isa MVirtualType or mt isa MParameterType then
+ mt = mt.undecorate
+ if mt isa MFormalType then
res.add_class("nc_vt")
end
return mt.infobox(v)
# Returns true if the test concern real generic covariance
fun count_types(node, elem: ANode, sub, sup: MType, mmodule: MModule, anchor: nullable MClassType): Bool
do
- sub = sub.as_notnullable
- sup = sup.as_notnullable
+ sub = sub.undecorate
+ sup = sup.undecorate
# Category of the target type
if sub isa MGenericType then
fun count_cast(node: ANode, sub, sup: MType, mmodule: MModule, anchor: nullable MClassType)
do
var nsup = sup
- sup = sup.as_notnullable
- sub = sub.as_notnullable
+ sup = sup.undecorate
+ sub = sub.undecorate
if sub == nsup then
cpt_cast_pattern.inc("monomorphic cast!?!")
# Now the case of direct null and nullable is over.
# If `sub` is a formal type, then it is accepted if its bound is accepted
- while sub isa MParameterType or sub isa MVirtualType do
+ while sub isa MFormalType do
#print "3.is {sub} a {sup}?"
# A unfixed formal type can only accept itself
assert sub isa MClassType # It is the only remaining type
# A unfixed formal type can only accept itself
- if sup isa MParameterType or sup isa MVirtualType then
+ if sup isa MFormalType then
return false
end
if pd isa MMethodDef then
# Parameters (contravariant)
for p in pd.msignature.mparameters do
- var t = p.mtype.as_notnullable
+ var t = p.mtype.undecorate
if not t.need_anchor then
# OK
else if t isa MParameterType then
# Return (covariant)
var t = pd.msignature.return_mtype
if t != null and t.need_anchor then
- t = t.as_notnullable
+ t = t.undecorate
if t isa MParameterType then
covar_pt.add(t)
else if t isa MVirtualType then
# Attribute (invariant)
var t = pd.static_mtype
if t != null and t.need_anchor then
- t = t.as_notnullable
+ t = t.undecorate
if t isa MParameterType then
covar_pt.add t
contravar_pt.add t
# Virtual type bound (covariant)
var t = pd.bound
if t != null and t.need_anchor then
- t = t.as_notnullable
+ t = t.undecorate
if t isa MParameterType then
covar_pt.add t
else if t isa MVirtualType then
# Process the generic types in a covariant position
for c in covar_classes do for i in [0..c.mclass.arity[ do
# The type used in the argument
- var ta = c.arguments[i].as_notnullable
+ var ta = c.arguments[i].undecorate
# The associated formal parameter
var tp = c.mclass.mparameters[i]
# Process the generic types in a contravariant position
for c in contravar_classes do for i in [0..c.mclass.arity[ do
# The type used in the argument
- var ta = c.arguments[i].as_notnullable
+ var ta = c.arguments[i].undecorate
# The associated formal parameter
var tp = c.mclass.mparameters[i]
super
tnlc.values.inc(mtype)
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
if mtype isa MClassType then
cnlc.values.inc(mtype.mclass)
end
redef class MType
private fun signature_depth: Int do
- var mtype = self.as_notnullable
+ var mtype = self.undecorate
if not mtype isa MGenericType then return 0
var depth = 0
if sup isa MNullableType then
sup_accept_null = true
sup = sup.mtype
+ else if sup isa MNotNullType then
+ sup = sup.mtype
else if sup isa MNullType then
sup_accept_null = true
end
# Can `sub` provide null or not?
# Thus we can match with `sup_accept_null`
# Also discard the nullable marker if it exists
+ var sub_reject_null = false
if sub isa MNullableType then
if not sup_accept_null then return false
sub = sub.mtype
+ else if sub isa MNotNullType then
+ sub_reject_null = true
+ sub = sub.mtype
else if sub isa MNullType then
return sup_accept_null
end
# Now the case of direct null and nullable is over.
# If `sub` is a formal type, then it is accepted if its bound is accepted
- while sub isa MParameterType or sub isa MVirtualType do
+ while sub isa MFormalType do
#print "3.is {sub} a {sup}?"
# A unfixed formal type can only accept itself
assert anchor != null
sub = sub.lookup_bound(mmodule, anchor)
+ if sub_reject_null then sub = sub.as_notnull
#print "3.is {sub} a {sup}?"
# Manage the second layer of null/nullable
if sub isa MNullableType then
- if not sup_accept_null then return false
+ if not sup_accept_null and not sub_reject_null then return false
+ sub = sub.mtype
+ else if sub isa MNotNullType then
+ sub_reject_null = true
sub = sub.mtype
else if sub isa MNullType then
return sup_accept_null
end
#print "4.is {sub} a {sup}? <- no more resolution"
- assert sub isa MClassType # It is the only remaining type
+ assert sub isa MClassType else print "{sub} <? {sub}" # It is the only remaining type
# A unfixed formal type can only accept itself
- if sup isa MParameterType or sup isa MVirtualType then
+ if sup isa MFormalType then
return false
end
return res
end
- # Return the not nullable version of the type
- # Is the type is already not nullable, then self is returned.
+ # Remove the base type of a decorated (proxy) type.
+ # Is the type is not decorated, then self is returned.
#
- # Note: this just remove the `nullable` notation, but the result can still contains null.
+ # Most of the time it is used to return the not nullable version of a nullable type.
+ # In this case, this just remove the `nullable` notation, but the result can still contains null.
# For instance if `self isa MNullType` or self is a formal type bounded by a nullable type.
- fun as_notnullable: MType
+ # If you really want to exclude the `null` value, then use `as_notnull`
+ fun undecorate: MType
do
return self
end
+ # Returns the not null version of the type.
+ # That is `self` minus the `null` value.
+ #
+ # For most types, this return `self`.
+ # For formal types, this returns a special `MNotNullType`
+ fun as_notnull: MType do return self
+
private var as_nullable_cache: nullable MType = null
end
end
+# A formal type (either virtual of parametric).
+#
+# The main issue with formal types is that they offer very little information on their own
+# and need a context (anchor and mmodule) to be useful.
+abstract class MFormalType
+ super MType
+
+ redef var as_notnull = new MNotNullType(self) is lazy
+end
+
# A virtual formal type.
class MVirtualType
- super MType
+ super MFormalType
# The property associated with the type.
# Its the definitions of this property that determine the bound or the virtual type.
redef fun lookup_fixed(mmodule: MModule, resolved_receiver: MType): MType
do
assert not resolved_receiver.need_anchor
- resolved_receiver = resolved_receiver.as_notnullable
+ resolved_receiver = resolved_receiver.undecorate
assert resolved_receiver isa MClassType # It is the only remaining type
var prop = lookup_single_definition(mmodule, resolved_receiver)
# Note that parameter types are shared among class refinements.
# Therefore parameter only have an internal name (see `to_s` for details).
class MParameterType
- super MType
+ super MFormalType
# The generic class where the parameter belong
var mclass: MClass
redef fun lookup_bound(mmodule: MModule, resolved_receiver: MType): MType
do
assert not resolved_receiver.need_anchor
- resolved_receiver = resolved_receiver.as_notnullable
+ resolved_receiver = resolved_receiver.undecorate
assert resolved_receiver isa MClassType # It is the only remaining type
var goalclass = self.mclass
if resolved_receiver.mclass == goalclass then
redef fun lookup_fixed(mmodule: MModule, resolved_receiver: MType): MType
do
assert not resolved_receiver.need_anchor
- resolved_receiver = resolved_receiver.as_notnullable
+ resolved_receiver = resolved_receiver.undecorate
assert resolved_receiver isa MClassType # It is the only remaining type
var res = self.resolve_for(resolved_receiver.mclass.mclass_type, resolved_receiver, mmodule, false)
return res
end
end
-# A type prefixed with "nullable"
-class MNullableType
+# A type that decorates another type.
+#
+# The point of this class is to provide a common implementation of sevices that just forward to the original type.
+# Specific decorator are expected to redefine (or to extend) the default implementation as this suit them.
+abstract class MProxyType
super MType
-
- # The base type of the nullable type
+ # The base type
var mtype: MType
redef fun model do return self.mtype.model
-
- init
- do
- self.to_s = "nullable {mtype}"
- end
-
- redef var to_s: String is noinit
-
- redef var full_name is lazy do return "nullable {mtype.full_name}"
-
- redef var c_name is lazy do return "nullable__{mtype.c_name}"
-
redef fun need_anchor do return mtype.need_anchor
- redef fun as_nullable do return self
- redef fun as_notnullable do return mtype
+ redef fun as_nullable do return mtype.as_nullable
+ redef fun as_notnull do return mtype.as_notnull
+ redef fun undecorate do return mtype.undecorate
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
do
var res = self.mtype.resolve_for(mtype, anchor, mmodule, cleanup_virtual)
- return res.as_nullable
+ return res
end
redef fun can_resolve_for(mtype, anchor, mmodule)
return self.mtype.can_resolve_for(mtype, anchor, mmodule)
end
- # Efficiently returns `mtype.lookup_fixed(mmodule, resolved_receiver).as_nullable`
redef fun lookup_fixed(mmodule, resolved_receiver)
do
var t = mtype.lookup_fixed(mmodule, resolved_receiver)
- if t == mtype then return self
- return t.as_nullable
+ return t
end
redef fun depth do return self.mtype.depth
end
end
+# A type prefixed with "nullable"
+class MNullableType
+ super MProxyType
+
+ init
+ do
+ self.to_s = "nullable {mtype}"
+ end
+
+ redef var to_s: String is noinit
+
+ redef var full_name is lazy do return "nullable {mtype.full_name}"
+
+ redef var c_name is lazy do return "nullable__{mtype.c_name}"
+
+ redef fun as_nullable do return self
+ redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
+ do
+ var res = super
+ return res.as_nullable
+ end
+
+ # Efficiently returns `mtype.lookup_fixed(mmodule, resolved_receiver).as_nullable`
+ redef fun lookup_fixed(mmodule, resolved_receiver)
+ do
+ var t = super
+ if t == mtype then return self
+ return t.as_nullable
+ end
+end
+
+# A non-null version of a formal type.
+#
+# When a formal type in bounded to a nullable type, this is the type of the not null version of it.
+class MNotNullType
+ super MProxyType
+
+ redef fun to_s do return "not null {mtype}"
+ redef var full_name is lazy do return "not null {mtype.full_name}"
+ redef var c_name is lazy do return "notnull__{mtype.c_name}"
+
+ redef fun as_notnull do return self
+
+ redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual)
+ do
+ var res = super
+ return res.as_notnull
+ end
+
+ # Efficiently returns `mtype.lookup_fixed(mmodule, resolved_receiver).as_notnull`
+ redef fun lookup_fixed(mmodule, resolved_receiver)
+ do
+ var t = super
+ if t == mtype then return self
+ return t.as_notnull
+ end
+end
+
# The type of the only value null
#
# The is only one null type per model, see `MModel::null_type`.
redef fun full_name do return "null"
redef fun c_name do return "null"
redef fun as_nullable do return self
+
+ # Aborts on `null`
+ redef fun as_notnull do abort # sorry...
redef fun need_anchor do return false
redef fun resolve_for(mtype, anchor, mmodule, cleanup_virtual) do return self
redef fun can_resolve_for(mtype, anchor, mmodule) do return true
fun lookup_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
do
assert not mtype.need_anchor
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
var cache = self.lookup_definitions_cache[mmodule, mtype]
if cache != null then return cache
fun lookup_super_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
do
assert not mtype.need_anchor
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
# First, select all candidates
var candidates = new Array[MPROPDEF]
# REQUIRE: `mtype.has_mproperty(mmodule, self)`
fun lookup_all_definitions(mmodule: MModule, mtype: MType): Array[MPROPDEF]
do
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
var cache = self.lookup_all_definitions_cache[mmodule, mtype]
if cache != null then return cache
# It is a case-by case
var vis_type: nullable MVisibility = null # The own visibility of the type
var mmodule_type: nullable MModule = null # The original module of the type
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
if mtype isa MClassType then
vis_type = mtype.mclass.visibility
mmodule_type = mtype.mclass.intro.mmodule
end
print "[HOST ADDRESS] : {debug.address}"
-print "[HOST] : {debug.host or else "unamed"}"
+print "[HOST] : {debug.host}"
print "[PORT] : {debug.port}"
print "Connecting ... {debug.connected}"
# return type
var rmt = mpropdef.msignature.return_mtype
if rmt != null then
- if rmt isa MParameterType or rmt isa MVirtualType then
+ if rmt isa MFormalType then
var mclass_type = mpropdef.mclassdef.bound_mtype
rmt = rmt.anchor_to(mmodule, mclass_type)
end
# params
for p in mpropdef.msignature.mparameters do
var mtype = p.mtype.resolve_for(recv_type, recv_type, mmodule, true)
- if mtype isa MParameterType or mtype isa MVirtualType then
+ if mtype isa MFormalType then
var mclass_type = mpropdef.mclassdef.bound_mtype
mtype = mtype.anchor_to(mmodule, mclass_type)
end
if mtype == null then return
- if mtype isa MParameterType or mtype isa MVirtualType then
+ if mtype isa MFormalType then
mtype = mtype.anchor_to(mmodule, mclass_type)
end
redef fun from_mtype do return n_type.mtype.as_nullable
redef fun to_mtype do
var mtype = n_type.mtype.as(not null)
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
return mtype
end
end
redef fun to_s do return """
-name: {{{name or else "null"}}}
-namespace: {{{namespace or else "null"}}}
-version: {{{version or else "null"}}}"""
+name: {{{name}}}
+namespace: {{{namespace}}}
+version: {{{version}}}"""
end
redef class AAnnotation
var mtype = callsite.recv
var anchor = callsite.anchor
if anchor != null then mtype = mtype.anchor_to(callsite.mmodule, anchor)
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
if mtype isa MClassType then mtype = mtype.mclass.intro.bound_mtype
var mproperty = callsite.mproperty
var res = live_targets_cache[mtype, mproperty]
do
mtype = mtype.anchor_to(self.analysis.mainmodule, self.receiver)
if mtype isa MNullType then return null
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
assert mtype isa MClassType
assert not mtype.need_anchor
return mtype
#node.debug("Unsafe typing: expected {sup}, got {sub}")
return sup
end
- self.modelbuilder.error(node, "Type error: expected {sup}, got {sub}")
+ if sub.need_anchor then
+ var u = anchor_to(sub)
+ self.modelbuilder.error(node, "Type error: expected {sup}, got {sub}: {u}")
+ else
+ self.modelbuilder.error(node, "Type error: expected {sup}, got {sub}")
+ end
return null
end
return sup
end
+ # Can `mtype` be null (up to the current knowledge)?
+ fun can_be_null(mtype: MType): Bool
+ do
+ if mtype isa MNullableType or mtype isa MNullType then return true
+ if mtype isa MFormalType then
+ var x = anchor_to(mtype)
+ if x isa MNullableType or x isa MNullType then return true
+ end
+ return false
+ end
+
+ # Check that `mtype` can be null (up to the current knowledge).
+ #
+ # If not then display a `useless-null-test` warning on node and return false.
+ # Else return true.
+ fun check_can_be_null(anode: ANode, mtype: MType): Bool
+ do
+ if can_be_null(mtype) then return true
+
+ if mtype isa MFormalType then
+ var res = anchor_to(mtype)
+ modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}: {res}`.")
+ else
+ modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}`.")
+ end
+ return false
+ end
+
# Special verification on != and == for null
# Return true
fun null_test(anode: ABinopExpr)
if not mtype2 isa MNullType then return
+ if mtype isa MNullType then return
+
# Check of useless null
- if not mtype isa MNullableType then
- if not anchor_to(mtype) isa MNullableType then
- modelbuilder.warning(anode, "useless-null-test", "Warning: expression is not null, since it is a `{mtype}`.")
- end
- return
- end
+ if not check_can_be_null(anode.n_expr, mtype) then return
+
+ mtype = mtype.as_notnull
# Check for type adaptation
var variable = anode.n_expr.its_variable
if variable == null then return
+ # One is null (mtype2 see above) the other is not null
if anode isa AEqExpr then
anode.after_flow_context.when_true.set_var(variable, mtype2)
- anode.after_flow_context.when_false.set_var(variable, mtype.mtype)
+ anode.after_flow_context.when_false.set_var(variable, mtype)
else if anode isa ANeExpr then
anode.after_flow_context.when_false.set_var(variable, mtype2)
- anode.after_flow_context.when_true.set_var(variable, mtype.mtype)
+ anode.after_flow_context.when_true.set_var(variable, mtype)
else
abort
end
var erasure_cast = false
var rettype = mpropdef.msignature.return_mtype
if not recv_is_self and rettype != null then
- rettype = rettype.as_notnullable
+ rettype = rettype.undecorate
if rettype isa MParameterType then
var erased_rettype = msignature.return_mtype
assert erased_rettype != null
var found = true
for t2 in col do
if t2 == null then continue # return null
- if t2 isa MNullableType or t2 isa MNullType then
+ if can_be_null(t2) and not can_be_null(t1) then
t1 = t1.as_nullable
end
if not is_subtype(t2, t1) then found = false
# anchor formal and virtual types
if mtype.need_anchor then mtype = v.anchor_to(mtype)
- mtype = mtype.as_notnullable
+ mtype = mtype.undecorate
self.coltype = mtype.as(MClassType)
# get methods is_ok, next, item
return # Skip error
end
- t1 = t1.as_notnullable
+ if t1 isa MNullType then
+ v.error(n_expr, "Type error: or else on null")
+ else if v.check_can_be_null(n_expr, t1) then
+ t1 = t1.as_notnull
+ end
var t = v.merge_types(self, [t1, t2])
if t == null then
var c = v.get_mclass(self, "Object")
if c == null then return # forward error
t = c.mclass_type
- if t2 isa MNullableType then
+ if v.can_be_null(t2) then
t = t.as_nullable
end
#v.error(self, "Type Error: ambiguous type {t1} vs {t2}")
v.error(self, "Type error: as(not null) on null")
return
end
- if mtype isa MNullableType then
- self.mtype = mtype.mtype
- return
- end
- self.mtype = mtype
- if mtype isa MClassType then
- v.modelbuilder.warning(self, "useless-type-test", "Warning: expression is already not null, since it is a `{mtype}`.")
- return
- end
- assert mtype.need_anchor
- var u = v.anchor_to(mtype)
- if not u isa MNullableType then
- v.modelbuilder.warning(self, "useless-type-test", "Warning: expression is already not null, since it is a `{mtype}: {u}`.")
- return
+ if v.check_can_be_null(n_expr, mtype) then
+ mtype = mtype.as_notnull
end
+
+ self.mtype = mtype
end
end
var anchor = self.frame.arguments.first.mtype.as(MClassType)
# `sub` or `sup` are formal or virtual types, resolve them to concrete types
- if sub isa MParameterType or sub isa MVirtualType then
+ if sub isa MFormalType then
sub = sub.resolve_for(anchor.mclass.mclass_type, anchor, mainmodule, false)
end
- if sup isa MParameterType or sup isa MVirtualType then
+ if sup isa MFormalType then
sup = sup.resolve_for(anchor.mclass.mclass_type, anchor, mainmodule, false)
end
end
# Now the case of direct null and nullable is over
- if sub isa MParameterType or sub isa MVirtualType then
+ if sub isa MFormalType then
sub = sub.anchor_to(mainmodule, anchor)
# Manage the second layer of null/nullable
if sub isa MNullableType then
--- /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::kernel
+
+class A[E] #alt2# class A[E: Object]
+ type V: nullable Object #alt2# type V: Object
+
+ fun foo(e: E, v: E) do #1alt1# fun foo(e: nullable E, v: nullable E) do
+ assert e != null#alt1# #alt3# assert e == null #alt4# if false then e = null
+ assert v != null#alt1# #alt3# assert v == null #alt4# if false then e = null
+ bar(e)
+ bar(v)
+ if e != null then
+ bar(e)
+ else bar(e)
+ if v != null then
+ bar(v)
+ else bar(v)
+ bar(e.as(not null))
+ bar(v.as(not null))
+ bar(e or else 0)
+ bar(v or else 0)
+ bar(e or else v)
+ bar(v or else e)
+ end
+
+ fun bar(o: Object) do o.output
+end
+
+var a = new A[Object]
+a.foo (1, 2)
--- /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.
+
+class A[E: nullable Discrete]
+ fun array(e, f: E): Object
+ do
+ assert e != null
+ assert f != null #alt1# #alt2# assert f == null
+ return [e, f]
+ end
+
+ fun range(e, f: E): Object
+ do
+ assert e != null
+ assert f != null #alt1#
+ return [e..f]
+ end
+end
+
+var a = new A[nullable Int]
+
+var ar = a.array(1, 5)
+ar.output_class_name
+ar.as(Array[Int]).add 6
+print ar
+
+var ra = a.range(1, 5)
+ra.output_class_name
+print ra
-base_as_notnull.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-base_as_notnull.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-base_as_notnull.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-base_as_notnull.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+base_as_notnull.nit:41,6: Warning: expression is not null, since it is a `A`.
+base_as_notnull.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+base_as_notnull.nit:43,6: Warning: expression is not null, since it is a `B`.
+base_as_notnull.nit:52,6: Warning: expression is not null, since it is a `B`.
1
2
3
-base_as_notnull2.nit:30,12--25: Warning: expression is already not null, since it is a `Object`.
-base_as_notnull2.nit:50,12--25: Warning: expression is already not null, since it is a `F: Object`.
+base_as_notnull2.nit:30,12: Warning: expression is not null, since it is a `Object`.
+base_as_notnull2.nit:50,12: Warning: expression is not null, since it is a `F: Object`.
1
1
2
-alt/base_as_notnull2_alt1.nit:30,12--25: Warning: expression is already not null, since it is a `Object`.
-alt/base_as_notnull2_alt1.nit:50,12--25: Warning: expression is already not null, since it is a `F: Object`.
+alt/base_as_notnull2_alt1.nit:30,12: Warning: expression is not null, since it is a `Object`.
+alt/base_as_notnull2_alt1.nit:50,12: Warning: expression is not null, since it is a `F: Object`.
alt/base_as_notnull2_alt1.nit:58,7--10: Type error: expected Object, got null
-alt/base_as_notnull2_alt2.nit:30,12--25: Warning: expression is already not null, since it is a `Object`.
-alt/base_as_notnull2_alt2.nit:50,12--25: Warning: expression is already not null, since it is a `F: Object`.
+alt/base_as_notnull2_alt2.nit:30,12: Warning: expression is not null, since it is a `Object`.
+alt/base_as_notnull2_alt2.nit:50,12: Warning: expression is not null, since it is a `F: Object`.
Runtime error: Cast failed (alt/base_as_notnull2_alt2.nit:40)
1
1
-alt/base_as_notnull2_alt3.nit:30,12--25: Warning: expression is already not null, since it is a `Object`.
-alt/base_as_notnull2_alt3.nit:50,12--25: Warning: expression is already not null, since it is a `F: Object`.
+alt/base_as_notnull2_alt3.nit:30,12: Warning: expression is not null, since it is a `Object`.
+alt/base_as_notnull2_alt3.nit:50,12: Warning: expression is not null, since it is a `F: Object`.
alt/base_as_notnull2_alt3.nit:64,7--10: Type error: expected Int, got null
-alt/base_as_notnull_alt1.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt1.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt1.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt1.nit:50,6--19: Warning: expression is already not null, since it is a `A`.
+alt/base_as_notnull_alt1.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt1.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt1.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt1.nit:50,6: Warning: expression is not null, since it is a `A`.
alt/base_as_notnull_alt1.nit:50,6--19: Type error: expected B, got A
-alt/base_as_notnull_alt1.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt1.nit:52,6: Warning: expression is not null, since it is a `B`.
-alt/base_as_notnull_alt2.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt2.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt2.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt2.nit:51,6--20: Warning: expression is already not null, since it is a `A`.
+alt/base_as_notnull_alt2.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt2.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt2.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt2.nit:51,6--7: Warning: expression is not null, since it is a `A`.
alt/base_as_notnull_alt2.nit:51,6--20: Type error: expected B, got A
-alt/base_as_notnull_alt2.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt2.nit:52,6: Warning: expression is not null, since it is a `B`.
-alt/base_as_notnull_alt3.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt3.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt3.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt3.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt3.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt3.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt3.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt3.nit:52,6: Warning: expression is not null, since it is a `B`.
alt/base_as_notnull_alt3.nit:53,6--20: Type error: expected B, got A
-alt/base_as_notnull_alt4.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt4.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt4.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt4.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt4.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt4.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt4.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt4.nit:52,6: Warning: expression is not null, since it is a `B`.
alt/base_as_notnull_alt4.nit:54,6--21: Type error: expected B, got A
-alt/base_as_notnull_alt5.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt5.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt5.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt5.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt5.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt5.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt5.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt5.nit:52,6: Warning: expression is not null, since it is a `B`.
Runtime error: Cast failed (alt/base_as_notnull_alt5.nit:59)
1
2
-alt/base_as_notnull_alt6.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt6.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt6.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt6.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt6.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt6.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt6.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt6.nit:52,6: Warning: expression is not null, since it is a `B`.
Runtime error: Cast failed (alt/base_as_notnull_alt6.nit:60)
1
2
-alt/base_as_notnull_alt7.nit:41,6--19: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt7.nit:42,6--20: Warning: expression is already not null, since it is a `A`.
-alt/base_as_notnull_alt7.nit:43,6--19: Warning: expression is already not null, since it is a `B`.
-alt/base_as_notnull_alt7.nit:52,6--19: Warning: expression is already not null, since it is a `B`.
+alt/base_as_notnull_alt7.nit:41,6: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt7.nit:42,6--7: Warning: expression is not null, since it is a `A`.
+alt/base_as_notnull_alt7.nit:43,6: Warning: expression is not null, since it is a `B`.
+alt/base_as_notnull_alt7.nit:52,6: Warning: expression is not null, since it is a `B`.
alt/base_as_notnull_alt7.nit:61,1--17: Type error: as(not null) on null
-base_as_notnull_int.nit:18,1--14: Warning: expression is already not null, since it is a `Int`.
-base_as_notnull_int.nit:20,1--15: Warning: expression is already not null, since it is a `Object`.
+base_as_notnull_int.nit:18,1: Warning: expression is not null, since it is a `Int`.
+base_as_notnull_int.nit:20,1--2: Warning: expression is not null, since it is a `Object`.
1
1
1
-base_eq_null_notnull.nit:36,6--14: Warning: expression is not null, since it is a `A`.
-base_eq_null_notnull.nit:43,2--10: Warning: expression is not null, since it is a `A`.
+base_eq_null_notnull.nit:36,6: Warning: expression is not null, since it is a `A`.
+base_eq_null_notnull.nit:43,2: Warning: expression is not null, since it is a `A`.
true
true
true
--- /dev/null
+base_notnull.nit:25,6: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:28,6: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:31,7: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:32,7: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:33,7: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:34,7: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:35,7: Warning: expression is not null, since it is a `not null E`.
+base_notnull.nit:36,7: Warning: expression is not null, since it is a `not null E`.
+1
+2
+1
+2
+1
+2
+1
+2
+1
+2
--- /dev/null
+alt/base_notnull_1alt1.nit:25,6: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:28,6: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:31,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:32,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:33,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:34,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:35,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1.nit:36,7: Warning: expression is not null, since it is a `not null E`.
+1
+2
+1
+2
+1
+2
+1
+2
+1
+2
--- /dev/null
+alt/base_notnull_1alt1_alt1.nit:23,7: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt1.nit:24,7: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt1.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt1.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt1.nit:35,7--17: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt1.nit:36,7--17: Type error: expected Object, got nullable E: nullable Object
--- /dev/null
+alt/base_notnull_1alt1_alt2.nit:25,6: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:28,6: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:31,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:32,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:33,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:34,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:35,7: Warning: expression is not null, since it is a `not null E`.
+alt/base_notnull_1alt1_alt2.nit:36,7: Warning: expression is not null, since it is a `not null E`.
+1
+2
+1
+2
+1
+2
+1
+2
+1
+2
--- /dev/null
+alt/base_notnull_1alt1_alt3.nit:23,7: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:24,7: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:26,8: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:29,8: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:31,7--20: Type error: as(not null) on null
+alt/base_notnull_1alt1_alt3.nit:32,7--20: Type error: as(not null) on null
+alt/base_notnull_1alt1_alt3.nit:33,7: Type error: or else on null
+alt/base_notnull_1alt1_alt3.nit:33,7--17: Type error: expected Object, got nullable Int
+alt/base_notnull_1alt1_alt3.nit:34,7: Type error: or else on null
+alt/base_notnull_1alt1_alt3.nit:34,7--17: Type error: expected Object, got nullable Int
+alt/base_notnull_1alt1_alt3.nit:35,7: Type error: or else on null
+alt/base_notnull_1alt1_alt3.nit:35,7--17: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt3.nit:36,7: Type error: or else on null
+alt/base_notnull_1alt1_alt3.nit:36,7--17: Type error: expected Object, got null
--- /dev/null
+alt/base_notnull_1alt1_alt4.nit:23,7: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt4.nit:24,7: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt4.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt4.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_1alt1_alt4.nit:35,7--17: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_1alt1_alt4.nit:36,7--17: Type error: expected Object, got nullable E: nullable Object
--- /dev/null
+alt/base_notnull_alt1.nit:23,7: Type error: expected Object, got E: nullable Object
+alt/base_notnull_alt1.nit:24,7: Type error: expected Object, got E: nullable Object
+alt/base_notnull_alt1.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_alt1.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_alt1.nit:35,7--17: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_alt1.nit:36,7--17: Type error: expected Object, got nullable E: nullable Object
--- /dev/null
+alt/base_notnull_alt2.nit:21,10: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:22,10: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:25,6: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:28,6: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:31,7: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:32,7: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:33,7: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:34,7: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:35,7: Warning: expression is not null, since it is a `E: Object`.
+alt/base_notnull_alt2.nit:36,7: Warning: expression is not null, since it is a `E: Object`.
+1
+2
+1
+2
+1
+2
+1
+2
+1
+2
--- /dev/null
+alt/base_notnull_alt3.nit:23,7: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:24,7: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:26,8: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:29,8: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:31,7--20: Type error: as(not null) on null
+alt/base_notnull_alt3.nit:32,7--20: Type error: as(not null) on null
+alt/base_notnull_alt3.nit:33,7: Type error: or else on null
+alt/base_notnull_alt3.nit:33,7--17: Type error: expected Object, got nullable Int
+alt/base_notnull_alt3.nit:34,7: Type error: or else on null
+alt/base_notnull_alt3.nit:34,7--17: Type error: expected Object, got nullable Int
+alt/base_notnull_alt3.nit:35,7: Type error: or else on null
+alt/base_notnull_alt3.nit:35,7--17: Type error: expected Object, got null
+alt/base_notnull_alt3.nit:36,7: Type error: or else on null
+alt/base_notnull_alt3.nit:36,7--17: Type error: expected Object, got null
--- /dev/null
+alt/base_notnull_alt4.nit:23,7: Type error: expected Object, got E: nullable Object
+alt/base_notnull_alt4.nit:24,7: Type error: expected Object, got E: nullable Object
+alt/base_notnull_alt4.nit:27,12: Type error: expected Object, got null
+alt/base_notnull_alt4.nit:30,12: Type error: expected Object, got null
+alt/base_notnull_alt4.nit:35,7--17: Type error: expected Object, got nullable E: nullable Object
+alt/base_notnull_alt4.nit:36,7--17: Type error: expected Object, got nullable E: nullable Object
--- /dev/null
+Array[Int]
+156
+Range[Int]
+12345
--- /dev/null
+alt/base_notnull_lit_alt1.nit:27,14: Type error: expected Discrete, got E: nullable Discrete
--- /dev/null
+Runtime error: Assert failed (alt/base_notnull_lit_alt2.nit:19)
-base_null.nit:28,2--13: Warning: expression is not null, since it is a `null`.
-base_null.nit:42,2--13: Warning: expression is not null, since it is a `null`.
false
false
true
-alt/base_upcast2_1alt1_alt10.nit:36,21: Type error: expected C, got T
+alt/base_upcast2_1alt1_alt10.nit:36,21: Type error: expected C, got T: A[Int]
-alt/base_upcast2_1alt1_alt7.nit:33,22: Type error: expected A[Bool], got T
+alt/base_upcast2_1alt1_alt7.nit:33,22: Type error: expected A[Bool], got T: A[Int]
-alt/base_upcast2_1alt1_alt8.nit:34,22: Type error: expected B[Int], got T
+alt/base_upcast2_1alt1_alt8.nit:34,22: Type error: expected B[Int], got T: A[Int]
-alt/base_upcast2_1alt1_alt9.nit:35,22: Type error: expected B[Bool], got T
+alt/base_upcast2_1alt1_alt9.nit:35,22: Type error: expected B[Bool], got T: A[Int]
-alt/base_upcast2_1alt2_alt10.nit:36,21: Type error: expected C, got T
+alt/base_upcast2_1alt2_alt10.nit:36,21: Type error: expected C, got T: A[Bool]
-alt/base_upcast2_1alt2_alt6.nit:32,22: Type error: expected A[Int], got T
+alt/base_upcast2_1alt2_alt6.nit:32,22: Type error: expected A[Int], got T: A[Bool]
-alt/base_upcast2_1alt2_alt8.nit:34,22: Type error: expected B[Int], got T
+alt/base_upcast2_1alt2_alt8.nit:34,22: Type error: expected B[Int], got T: A[Bool]
-alt/base_upcast2_1alt2_alt9.nit:35,22: Type error: expected B[Bool], got T
+alt/base_upcast2_1alt2_alt9.nit:35,22: Type error: expected B[Bool], got T: A[Bool]
-alt/base_upcast2_1alt3_alt10.nit:36,21: Type error: expected C, got T
+alt/base_upcast2_1alt3_alt10.nit:36,21: Type error: expected C, got T: B[Int]
-alt/base_upcast2_1alt3_alt7.nit:33,22: Type error: expected A[Bool], got T
+alt/base_upcast2_1alt3_alt7.nit:33,22: Type error: expected A[Bool], got T: B[Int]
-alt/base_upcast2_1alt3_alt9.nit:35,22: Type error: expected B[Bool], got T
+alt/base_upcast2_1alt3_alt9.nit:35,22: Type error: expected B[Bool], got T: B[Int]
-alt/base_upcast2_1alt4_alt10.nit:36,21: Type error: expected C, got T
+alt/base_upcast2_1alt4_alt10.nit:36,21: Type error: expected C, got T: B[Bool]
-alt/base_upcast2_1alt4_alt7.nit:33,22: Type error: expected A[Bool], got T
+alt/base_upcast2_1alt4_alt7.nit:33,22: Type error: expected A[Bool], got T: B[Bool]
-alt/base_upcast2_1alt4_alt8.nit:34,22: Type error: expected B[Int], got T
+alt/base_upcast2_1alt4_alt8.nit:34,22: Type error: expected B[Int], got T: B[Bool]
-alt/base_upcast2_1alt5_alt7.nit:33,22: Type error: expected A[Bool], got T
+alt/base_upcast2_1alt5_alt7.nit:33,22: Type error: expected A[Bool], got T: C
-alt/base_upcast2_1alt5_alt8.nit:34,22: Type error: expected B[Int], got T
+alt/base_upcast2_1alt5_alt8.nit:34,22: Type error: expected B[Int], got T: C
-base_var_type_evolution_null3.nit:52,5--13: Warning: expression is not null, since it is a `Object`.
+base_var_type_evolution_null3.nit:52,5: Warning: expression is not null, since it is a `Object`.
1
1
5
-alt/base_var_type_evolution_null3_alt1.nit:52,5--13: Warning: expression is not null, since it is a `Object`.
+alt/base_var_type_evolution_null3_alt1.nit:52,5: Warning: expression is not null, since it is a `Object`.
1
1
5
alt/base_virtual_type_self_alt5.nit:44,9: Type error: expected A[U], got Float
-alt/base_virtual_type_self_alt5.nit:45,7--12: Type error: expected Float, got A[U]
-alt/base_virtual_type_self_alt5.nit:47,7--12: Type error: expected Float, got A[A[U]]
+alt/base_virtual_type_self_alt5.nit:45,7--12: Type error: expected Float, got A[U]: A[Int]
+alt/base_virtual_type_self_alt5.nit:47,7--12: Type error: expected Float, got A[A[U]]: A[A[Int]]
alt/error_expr_not_ok_alt4.nit:149,7--24: Type error: expected A, got String
alt/error_expr_not_ok_alt4.nit:150,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt4.nit:150,7--18: Type error: expected A, got Int
-alt/error_expr_not_ok_alt4.nit:151,7--23: Warning: expression is already not null, since it is a `Int`.
+alt/error_expr_not_ok_alt4.nit:151,7--10: Warning: expression is not null, since it is a `Int`.
alt/error_expr_not_ok_alt4.nit:151,7--23: Type error: expected A, got Int
alt/error_expr_not_ok_alt4.nit:152,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt4.nit:152,7--18: Type error: expected A, got Bool
alt/error_expr_not_ok_alt5.nit:149,7--24: Type error: expected A, got String
alt/error_expr_not_ok_alt5.nit:150,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt5.nit:150,7--18: Type error: expected A, got Int
-alt/error_expr_not_ok_alt5.nit:151,7--23: Warning: expression is already not null, since it is a `Int`.
+alt/error_expr_not_ok_alt5.nit:151,7--10: Warning: expression is not null, since it is a `Int`.
alt/error_expr_not_ok_alt5.nit:151,7--23: Type error: expected A, got Int
alt/error_expr_not_ok_alt5.nit:152,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt5.nit:152,7--18: Type error: expected A, got Bool
alt/error_expr_not_ok_alt6.nit:149,7--24: Type error: expected A, got String
alt/error_expr_not_ok_alt6.nit:150,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt6.nit:150,7--18: Type error: expected A, got Int
-alt/error_expr_not_ok_alt6.nit:151,7--23: Warning: expression is already not null, since it is a `Int`.
+alt/error_expr_not_ok_alt6.nit:151,7--10: Warning: expression is not null, since it is a `Int`.
alt/error_expr_not_ok_alt6.nit:151,7--23: Type error: expected A, got Int
alt/error_expr_not_ok_alt6.nit:152,7--18: Warning: Expression is already a Int.
alt/error_expr_not_ok_alt6.nit:152,7--18: Type error: expected A, got Bool
--- /dev/null
+Array
+156
+Range
+12345
-Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:909)
+Runtime error: Cast failed. Expected `E`, got `Bool` (../lib/standard/collection/array.nit:911)
NativeString
N
Nit