end
end
+redef class AIssetAttrExpr
+ redef meth after_typing(v)
+ do
+ do_typing(v)
+ if prop == null then return
+ if attr_type.is_nullable then
+ v.error(self, "Error: isset on a nullable attribute.")
+ end
+ _stype = v.type_bool
+ _is_typed = true
+ end
+end
+
class AAbsAbsSendExpr
special PExpr
# The signature of the called property
n_expr2.stype isa MMTypeNone and not n_expr.stype.is_nullable then
v.warning(self, "Warning: comparaison between null and a non nullable value.")
end
+
+ if n_expr.stype isa MMTypeNone then
+ try_to_isa(v, n_expr2)
+ else if n_expr2.stype isa MMTypeNone then
+ try_to_isa(v, n_expr)
+ end
+ end
+
+ private meth try_to_isa(v: TypingVisitor, n: PExpr)
+ do
+ var variable = n.its_variable
+ if variable != null then
+ _if_false_variable_ctx = v.variable_ctx.sub_with(self, variable, n.stype.as_notnull)
+ end
end
end
redef class ANeExpr
n_expr2.stype isa MMTypeNone and not n_expr.stype.is_nullable then
v.warning(self, "Warning: comparaison between null and a non nullable value.")
end
+
+ if n_expr.stype isa MMTypeNone then
+ try_to_isa(v, n_expr2)
+ else if n_expr2.stype isa MMTypeNone then
+ try_to_isa(v, n_expr)
+ end
+ end
+
+ private meth try_to_isa(v: TypingVisitor, n: PExpr)
+ do
+ var variable = n.its_variable
+ if variable != null then
+ _if_true_variable_ctx = v.variable_ctx.sub_with(self, variable, n.stype.as_notnull)
+ end
end
end
redef class ALtExpr
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}.")
+ else if etype.is_nullable and etype.as_notnull == ttype then
+ if ttype isa MMTypeFormal and ttype.bound.is_nullable then
+ # No warning in this case since with
+ # type T: nullable A
+ # var x: nullable T
+ # 'x.as(not null)' != 'x.as(T)'
+ # 'x != null' != 'x isa T'
+ else if self isa AIsaExpr then
+ v.warning(self, "Warning: Prefer '!= null'.")
+ else
+ v.warning(self, "Warning: Prefer '.as(not null)'.")
+ end
end
end
end