#debug("recv: {recvtype} (aka {unsafe_type})")
if recvtype isa MNullType then
- self.error(node, "Error: Method '{name}' call on 'null'.")
- return null
+ # `null` only accepts some methods of object.
+ if name == "==" or name == "!=" or name == "is_same_instance" then
+ unsafe_type = mmodule.object_type.as_nullable
+ else
+ self.error(node, "Error: Method '{name}' call on 'null'.")
+ return null
+ end
end
var mproperty = self.try_get_mproperty_by_name2(node, unsafe_type, name)
redef class AAttrPropdef
redef fun do_typing(modelbuilder: ModelBuilder)
do
+ if not has_value then return
+
var mpropdef = self.mpropdef.as(not null)
var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef)
self.selfvariable = v.selfvariable
var nblock = self.n_block
if nblock != null then
v.visit_stmt(nblock)
+ if not nblock.after_flow_context.is_unreachable then
+ # We reach the end of the init without having a return, it is bad
+ v.error(self, "Control error: Reached end of block (a 'return' with a value was expected).")
+ end
end
end
end
#debug("var {variable}: {mtype}")
+ self.mtype = mtype
self.is_typed = true
end
end
self.read_type = readtype
- if readtype isa MNullType then
- v.error(self, "Error: Method '{reassign_name}' call on 'null'.")
- return null
- end
-
var callsite = v.get_method(self, readtype, reassign_name, false)
if callsite == null then return null # Skip error
self.reassign_callsite = callsite
is_col = true
end
- if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type, objcla.mclass_type.as_nullable])) then
+ if mapit_cla != null and v.is_subtype(ittype, mapit_cla.get_mtype([objcla.mclass_type.as_nullable, objcla.mclass_type.as_nullable])) then
# Map Iterator
var coltype = ittype.supertype_to(v.mmodule, v.anchor, mapit_cla)
var variables = self.variables
end
end
+redef class AWithExpr
+ var method_start: nullable CallSite
+ var method_finish: nullable CallSite
+
+ redef fun accept_typing(v: TypeVisitor)
+ do
+ var mtype = v.visit_expr(n_expr)
+ if mtype == null then return
+
+ method_start = v.get_method(self, mtype, "start", n_expr isa ASelfExpr)
+ method_finish = v.get_method(self, mtype, "finish", n_expr isa ASelfExpr)
+
+ v.visit_stmt(n_block)
+ self.mtype = n_block.mtype
+ self.is_typed = true
+ end
+end
+
redef class AAssertExpr
redef fun accept_typing(v)
do
var name = self.property_name
if recvtype == null then return # Forward error
- if recvtype isa MNullType then
- v.error(self, "Error: Method '{name}' call on 'null'.")
- return
- end
var callsite = v.get_method(self, recvtype, name, self.n_expr isa ASelfExpr)
if callsite == null then return
var name = self.property_name
if recvtype == null then return # Forward error
- if recvtype isa MNullType then
- v.error(self, "Error: Method '{name}' call on 'null'.")
- return
- end
var for_self = self.n_expr isa ASelfExpr
var callsite = v.get_method(self, recvtype, name, for_self)