X-Git-Url: http://nitlanguage.org diff --git a/src/typing.nit b/src/typing.nit index db7560f..a415667 100644 --- a/src/typing.nit +++ b/src/typing.nit @@ -34,7 +34,6 @@ end private class TypeVisitor var modelbuilder: ModelBuilder - var nclassdef: AClassdef # The module of the analysis # Used to correctly query the model @@ -44,26 +43,41 @@ private class TypeVisitor # Mainly used for type tests and type resolutions var anchor: nullable MClassType + # The analyzed mclassdef + var mclassdef: nullable MClassDef + # The analyzed property var mpropdef: nullable MPropDef var selfvariable: Variable = new Variable("self") - init(modelbuilder: ModelBuilder, nclassdef: AClassdef, mpropdef: MPropDef) + # Is `self` use restricted? + # * no explicit `self` + # * method called on the implicit self must be top-level + var is_toplevel_context = false + + init(modelbuilder: ModelBuilder, mmodule: MModule, mpropdef: nullable MPropDef) do self.modelbuilder = modelbuilder - self.nclassdef = nclassdef - self.mpropdef = mpropdef - var mclassdef = mpropdef.mclassdef + self.mmodule = mmodule + + if mpropdef != null then + self.mpropdef = mpropdef + var mclassdef = mpropdef.mclassdef + self.mclassdef = mclassdef + self.anchor = mclassdef.bound_mtype - self.mmodule = mclassdef.mmodule - self.anchor = mclassdef.bound_mtype + var mclass = mclassdef.mclass - var mclass = mclassdef.mclass + var selfvariable = new Variable("self") + self.selfvariable = selfvariable + selfvariable.declared_type = mclass.mclass_type - var selfvariable = new Variable("self") - self.selfvariable = selfvariable - selfvariable.declared_type = mclass.mclass_type + var mprop = mpropdef.mproperty + if mprop isa MMethod and mprop.is_toplevel then + is_toplevel_context = true + end + end end fun anchor_to(mtype: MType): MType @@ -177,7 +191,7 @@ private class TypeVisitor if sup == sub then self.modelbuilder.warning(node, "Warning: Expression is already a {sup}.") - else if self.is_subtype(sub, sup) and not sup.need_anchor then + else if self.is_subtype(sub, sup) then self.modelbuilder.warning(node, "Warning: Expression is already a {sup} since it is a {sub}.") end return sup @@ -190,7 +204,7 @@ private class TypeVisitor fun resolve_mtype(node: AType): nullable MType do - return self.modelbuilder.resolve_mtype(self.nclassdef, node) + return self.modelbuilder.resolve_mtype(mmodule, mclassdef, node) end fun try_get_mclass(node: ANode, name: String): nullable MClass @@ -237,6 +251,14 @@ private class TypeVisitor end assert mproperty isa MMethod + + if is_toplevel_context and recv_is_self and not mproperty.is_toplevel then + error(node, "Error: '{name}' is not a top-level method, thus need a receiver.") + end + if not recv_is_self and mproperty.is_toplevel then + error(node, "Error: cannot call '{name}', a top-level method, with a receiver.") + end + if mproperty.visibility == protected_visibility and not recv_is_self and self.mmodule.visibility_for(mproperty.intro_mclassdef.mmodule) < intrude_visibility and not modelbuilder.toolcontext.opt_ignore_visibility.value then self.modelbuilder.error(node, "Error: Method '{name}' is protected and can only acceded by self.") return null @@ -255,13 +277,13 @@ private class TypeVisitor end - var msignature = mpropdef.msignature.as(not null) + var msignature = mpropdef.new_msignature or else mpropdef.msignature.as(not null) msignature = resolve_for(msignature, recvtype, recv_is_self).as(MSignature) var erasure_cast = false var rettype = mpropdef.msignature.return_mtype if not recv_is_self and rettype != null then - if rettype isa MNullableType then rettype = rettype.mtype + rettype = rettype.as_notnullable if rettype isa MParameterType then var erased_rettype = msignature.return_mtype assert erased_rettype != null @@ -481,9 +503,8 @@ redef class AMethPropdef var nblock = self.n_block if nblock == null then return - var nclassdef = self.parent.as(AClassdef) var mpropdef = self.mpropdef.as(not null) - var v = new TypeVisitor(modelbuilder, nclassdef, mpropdef) + var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef) self.selfvariable = v.selfvariable var mmethoddef = self.mpropdef.as(not null) @@ -510,8 +531,8 @@ end redef class AAttrPropdef redef fun do_typing(modelbuilder: ModelBuilder) do - var nclassdef = self.parent.as(AClassdef) - var v = new TypeVisitor(modelbuilder, nclassdef, self.mpropdef.as(not null)) + var mpropdef = self.mpropdef.as(not null) + var v = new TypeVisitor(modelbuilder, mpropdef.mclassdef.mmodule, mpropdef) self.selfvariable = v.selfvariable var nexpr = self.n_expr @@ -830,7 +851,7 @@ redef class AForExpr if objcla == null then return # check iterator method - var itdef = v.get_method(self, mtype, "iterator", true) + var itdef = v.get_method(self, mtype, "iterator", n_expr isa ASelfExpr) if itdef == null then v.error(self, "Type Error: 'for' expects a type providing 'iterator' method, got '{mtype}'.") return @@ -883,7 +904,7 @@ redef class AForExpr # anchor formal and virtual types if mtype.need_anchor then mtype = v.anchor_to(mtype) - if mtype isa MNullableType then mtype = mtype.mtype + mtype = mtype.as_notnullable self.coltype = mtype.as(MClassType) # get methods is_ok, next, item @@ -986,9 +1007,7 @@ redef class AOrElseExpr return # Skip error end - if t1 isa MNullableType then - t1 = t1.mtype - end + t1 = t1.as_notnullable var t = v.merge_types(self, [t1, t2]) if t == null then @@ -1059,7 +1078,7 @@ redef class ASuperstringExpr if mclass == null then return # Forward error self.mtype = mclass.mclass_type for nexpr in self.n_exprs do - var t = v.visit_expr(nexpr) + v.visit_expr_subtype(nexpr, v.mmodule.object_type) end end end @@ -1172,6 +1191,8 @@ redef class AAsNotnullExpr redef fun accept_typing(v) do var mtype = v.visit_expr(self.n_expr) + if mtype == null then return # Forward error + if mtype isa MNullType then v.error(self, "Type error: as(not null) on null") return @@ -1180,8 +1201,18 @@ redef class AAsNotnullExpr self.mtype = mtype.mtype return end - # TODO: warn on useless as not null self.mtype = mtype + + if mtype isa MClassType then + v.modelbuilder.warning(self, "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, "Warning: expression is already not null, since it is a `{mtype}: {u}`.") + return + end end end @@ -1196,6 +1227,9 @@ redef class ASelfExpr redef var its_variable: nullable Variable redef fun accept_typing(v) do + if v.is_toplevel_context and not self isa AImplicitSelfExpr then + v.error(self, "Error: self cannot be used in top-level method.") + end var variable = v.selfvariable self.its_variable = variable self.mtype = v.get_variable(self, variable) @@ -1233,6 +1267,9 @@ redef class ASendExpr if not (vmpropdef isa MMethodDef and vmpropdef.mproperty.is_init) then v.error(self, "Can call a init only in another init") end + if vmpropdef isa MMethodDef and vmpropdef.mproperty.is_root_init and not callsite.mproperty.is_root_init then + v.error(self, "Error: {vmpropdef} cannot call a factory {callsite.mproperty}") + end end var ret = msignature.return_mtype @@ -1488,12 +1525,15 @@ redef class ASuperExpr if v.modelbuilder.toolcontext.error_count > errcount then return # Forard error continue # Try next super-class end - if superprop != null and superprop.mproperty != candidate then + if superprop != null and candidate.is_root_init then + continue + end + if superprop != null and superprop.mproperty != candidate and not superprop.mproperty.is_root_init then v.error(self, "Error: conflicting super constructor to call for {mproperty}: {candidate.full_name}, {superprop.mproperty.full_name}") return end var candidatedefs = candidate.lookup_definitions(v.mmodule, recvtype) - if superprop != null then + if superprop != null and superprop.mproperty == candidate then if superprop == candidatedefs.first then continue candidatedefs.add(superprop) end @@ -1508,7 +1548,7 @@ redef class ASuperExpr return end - var msignature = superprop.msignature.as(not null) + var msignature = superprop.new_msignature or else superprop.msignature.as(not null) msignature = v.resolve_for(msignature, recvtype, true).as(MSignature) var callsite = new CallSite(self, recvtype, v.mmodule, v.anchor, true, superprop.mproperty, superprop, msignature, false)