var auto_super_inits = new Array[CallSite]
# The look for new-style super constructors (called from a old style constructor)
- var the_root_init_mmethod = modelbuilder.the_root_init_mmethod
- if the_root_init_mmethod != null and auto_super_inits.is_empty then
- var candidatedefs = the_root_init_mmethod.lookup_definitions(mmodule, anchor)
- if candidatedefs.is_empty then
- # skip broken
+ var candidatedefs = get_super_candidatedefs(modelbuilder)
+
+ if not candidatedefs.is_empty and auto_super_inits.is_empty then
+
+ var candidatedef = candidatedefs.first
+ if candidatedefs.length > 1 then
+ var cd2 = candidatedefs[1]
+ modelbuilder.error(self, "Error: cannot do an implicit constructor call to conflicting inherited inits `{cd2}({cd2.initializers.join(", ")}`) and `{candidatedef}({candidatedef.initializers.join(", ")}`). NOTE: Do not mix old-style and new-style init!")
is_broken = true
return
end
- # Search the longest-one and checks for conflict
- var candidatedef = candidatedefs.first
- if candidatedefs.length > 1 then
- # Check for conflict in the order of initializers
- # Each initializer list must me a prefix of the longest list
- # part 1. find the longest list
- for spd in candidatedefs do
- if spd.initializers.length > candidatedef.initializers.length then candidatedef = spd
- end
- # compare
- for spd in candidatedefs do
- var i = 0
- for p in spd.initializers do
- if p != candidatedef.initializers[i] then
- modelbuilder.error(self, "Error: cannot do an implicit constructor call to conflicting inherited inits `{spd}({spd.initializers.join(", ")}`) and `{candidatedef}({candidatedef.initializers.join(", ")}`). NOTE: Do not mix old-style and new-style init!")
- return
- end
- i += 1
+ var msignature = candidatedef.msignature
+ msignature = msignature.resolve_for(recvtype, anchor, mmodule, true)
+
+ if msignature.arity > mpropdef.msignature.arity then
+ modelbuilder.error(self, "Error: cannot do an implicit constructor call to `{candidatedef}{msignature}`. Expected at least `{msignature.arity}` arguments.")
+ is_broken = true
+ return
+ end
+
+ if candidatedef.mproperty != mpropdef.mproperty then
+ var i = 0
+ for candidat_mparameter in msignature.mparameters do
+ var actual_mparameter = mpropdef.msignature.mparameters[i]
+ if not candidat_mparameter.mtype.is_subtype(mmodule, anchor, actual_mparameter.mtype) then
+ modelbuilder.error(self, "Type Error: expected argument #{i} of type `{candidat_mparameter.mtype}`, got implicit argument `{candidat_mparameter.name}` of type `{actual_mparameter.mtype}`. Signature is {msignature}")
+ return
end
+ i += 1
end
end
- var msignature = candidatedef.new_msignature or else candidatedef.msignature
- msignature = msignature.resolve_for(recvtype, anchor, mmodule, true)
-
- var callsite = new CallSite(hot_location, recvtype, mmodule, anchor, true, the_root_init_mmethod, candidatedef, msignature, false)
+ var callsite = new CallSite(hot_location, recvtype, mmodule, anchor, true, candidatedef.mproperty, candidatedef, msignature, false)
auto_super_inits.add(callsite)
- modelbuilder.toolcontext.info("Auto-super init for {mpropdef} to {the_root_init_mmethod.full_name}", 4)
+ modelbuilder.toolcontext.info("Auto-super init for {mpropdef} to {candidatedef.full_name}", 4)
+ else if candidatedefs.is_empty then
+ # skip broken
+ is_broken = true
+ return
end
if auto_super_inits.is_empty then
modelbuilder.error(self, "Error: no constructors to call implicitly in `{mpropdef}`. Call one explicitly.")
return
end
- # Can the super-constructors be called?
- for auto_super_init in auto_super_inits do
- var auto_super_init_def = auto_super_init.mpropdef
- var msig = mpropdef.msignature.as(not null)
- var supermsig = auto_super_init.msignature
- if supermsig.arity > msig.arity then
- modelbuilder.error(self, "Error: cannot do an implicit constructor call to `{auto_super_init_def}{supermsig}`. Expected at least `{supermsig.arity}` arguments, got `{msig.arity}`.")
- continue
- end
- var i = 0
- for sp in supermsig.mparameters do
- var p = msig.mparameters[i]
- var sub = p.mtype
- var sup = sp.mtype
- if not sub.is_subtype(mmodule, anchor, sup) then
- modelbuilder.error(self, "Error: cannot do an implicit constructor call to `{auto_super_init_def}{supermsig}`. Expected argument #{i} of type `{sp.mtype}`, got implicit argument `{p.name}` of type `{p.mtype}`.")
- break
- end
- i += 1
- end
- end
self.auto_super_inits = auto_super_inits
end
+ # This method returns the list of possible candidates for the current definition.
+ #
+ # Warning this method supports super call from old_style_init to default_inits without signature verification!!!
+ private fun get_super_candidatedefs(modelbuilder: ModelBuilder): Array[MMethodDef]
+ do
+ var candidatedefs = new Array[MMethodDef]
+
+ var mclassdef = self.parent.as(AClassdef).mclassdef
+ if mclassdef == null or mclassdef.is_broken then return candidatedefs # skip error
+ var mpropdef = self.mpropdef
+ if mpropdef == null or mpropdef.is_broken then return candidatedefs # skip error
+ var mmodule = mpropdef.mclassdef.mmodule
+ var anchor = mclassdef.bound_mtype
+ var mproperty = mpropdef.mproperty
+
+ # The look for new-style super constructors (called from a old style constructor)
+ var the_root_init_mmethod = modelbuilder.the_root_init_mmethod
+
+ if mpropdef.is_old_style_init then
+ var superprop: nullable MMethodDef = null
+ for mclass in mclassdef.mclass.in_hierarchy(mmodule).direct_greaters do
+ candidatedefs.add(mclass.intro.default_init.as(not null))
+ end
+ else
+ candidatedefs = the_root_init_mmethod.lookup_definitions(mmodule, anchor)
+ end
+ return candidatedefs
+ end
end
redef class ANode