@@ -711,10 +711,6 @@ struct referencer {
711711 next: &referencer // Next referencer.
712712}
713713
714- enum recheckableType: type {
715- &StructIns,
716- }
717-
718714// Cycle state flags.
719715const (
720716 cycleErrDisable = 1 << iota // Disable error logging for cycle analysis.
@@ -764,7 +760,7 @@ struct typeChecker {
764760 ignoredGenerics: *[]&Type
765761
766762 // See developer reference (15).
767- recheckNeed: *[]recheckableType
763+ recheckNeed: *[]&Type
768764
769765 // This generics used as type alias for real kind.
770766 useGenerics: []&TypeAlias
@@ -1187,7 +1183,7 @@ impl typeChecker {
11871183
11881184 // Builds generic types and associates with struct s.
11891185 // Returns struct s if no error occurred, otherwise returns nil.
1190- fn getStructInsWithGenerics(mut self, mut s: &StructIns, mut indx: &ast::IndexExpr): &StructIns {
1186+ fn getStructInsWithGenerics(mut self, mut s: &StructIns, mut indx: &ast::IndexExpr): ( &StructIns, recheckNeeded: bool) {
11911187 inscatch, letGenerics := self.inscatchNeeded(s.Decl)
11921188
11931189 // Save configuration.
@@ -1207,8 +1203,7 @@ impl typeChecker {
12071203 defer { self.lookup = lookup }
12081204
12091205 // Whether the instance pushed to recheck stack.
1210- mut recheck := false
1211- mut &_recheck := recheck // For closure.
1206+ mut &_recheck := recheckNeeded // For closure.
12121207
12131208 pushGenericToIns := fn(mut typDecl: &ast::Expr): bool {
12141209 mut typ := unsafe { self.checkDecl(typDecl) }
@@ -1242,7 +1237,6 @@ impl typeChecker {
12421237 prim := typ.Prim()
12431238 if prim != nil && unsafe { self.isIgnoredGeneric(prim.Kind) } {
12441239 unsafe { _recheck = true }
1245- unsafe { *self.recheckNeed = append(*self.recheckNeed, s) }
12461240 }
12471241 }
12481242 s.Generics = append(s.Generics, &InsGeneric{Type: typ})
@@ -1257,28 +1251,54 @@ impl typeChecker {
12571251 for (_, mut typDecl) in tup.X {
12581252 ok := pushGenericToIns(typDecl)
12591253 if !ok {
1260- ret nil
1254+ ret nil, false
12611255 }
12621256 }
12631257 |:
12641258 ok := pushGenericToIns(indx.Index)
12651259 if !ok {
1266- ret nil
1260+ ret nil, false
12671261 }
12681262 }
1269- ret s
1263+ ret s, recheckNeeded
12701264 }
12711265
1272- fn buildStructInsWithGenerics(mut self, mut s: &StructIns, mut indx: &ast::IndexExpr): &StructIns {
1273- s = self.getStructInsWithGenerics(s, indx)
1266+ fn buildStructInsWithGenerics(mut self, mut s: &StructIns, mut indx: &ast::IndexExpr): ( &StructIns, recheckNeeded: bool) {
1267+ s, recheckNeeded = self.getStructInsWithGenerics(s, indx)
12741268 if s == nil {
1275- ret nil
1269+ ret nil, false
12761270 }
12771271 mut ok := self.s.checkGenericQuantity(len(s.Decl.Generics), len(s.Generics), indx.X.Token)
12781272 if !ok {
1279- ret nil
1273+ ret nil, false
1274+ }
1275+ // If recheck needed for the structure, do not build instance.
1276+ // Avoid appending to collection, otherwise we may have duplicate instances.
1277+ // For example:
1278+ //
1279+ // consider this function:
1280+ // fn Foo(): Bar[T]
1281+ //
1282+ // consider this code:
1283+ // x := int(10)
1284+ // Foo(x)
1285+ // Foo(x)
1286+ //
1287+ // In this case, Foo called with type inferred generics.
1288+ // We build for the non-generic types first.
1289+ // If we append instance for Bar[T], we will have duplicate instances.
1290+ // Because Bar[T] will resolved as Bar[int] in the first call.
1291+ // The second will append Bar[T] to collection again, because there is no Bar[T].
1292+ // Then the new Bar[T] will resolved as Bar[int], as a result we have two Bar[int].
1293+ // This may also cause some conflicts, since lookup returns the first match.
1294+ //
1295+ // As explained above, we should not append instances into collection here.
1296+ // Return with s directly, and report recheck needed.
1297+ // Append instance into collection when analysis sent type to recheck.
1298+ if recheckNeeded {
1299+ ret s, recheckNeeded
12801300 }
1281- ret self.buildStructIns(s, indx.X.Token)
1301+ ret self.buildStructIns(s, indx.X.Token), false
12821302 }
12831303
12841304 fn buildStructIns(mut self, mut s: &StructIns, mut errToken: &token::Token): &StructIns {
@@ -1751,25 +1771,26 @@ impl typeChecker {
17511771 ret kind
17521772 }
17531773
1754- fn buildIndex(mut self, mut indx: &ast::IndexExpr): Kind {
1774+ fn buildIndex(mut self, mut indx: &ast::IndexExpr): ( Kind, recheckNeeded: bool) {
17551775 mut typ := self.build(indx.X.Data)
17561776 if typ == nil {
1757- ret nil
1777+ ret nil, false
17581778 }
17591779 mut s := typ.SoftStruct()
17601780 if self.selection {
17611781 self.pushErr(indx.X.Token, log::GenericsNotAllowed)
1762- ret nil
1782+ ret nil, false
17631783 }
17641784 if s == nil || s.Source != nil || len(s.Generics) > 0 {
17651785 self.pushErr(indx.X.Token, log::TypeNotSupportsGenerics, typ.Str())
1766- ret nil
1786+ ret nil, false
17671787 }
17681788 ret self.buildStructInsWithGenerics(s, indx)
17691789 }
17701790
17711791 fn build(mut self, mut declKind: ast::ExprData): &Type {
17721792 let mut kind: Kind = nil
1793+ let mut recheckNeeded: bool = false
17731794 match type declKind {
17741795 | &ast::RangeExpr:
17751796 mut r := declKind.(&ast::RangeExpr)
@@ -1833,7 +1854,7 @@ impl typeChecker {
18331854 kind = t
18341855 }
18351856 | &ast::IndexExpr:
1836- mut t := self.buildIndex(declKind.(&ast::IndexExpr))
1857+ mut t, (recheckNeeded) := self.buildIndex(declKind.(&ast::IndexExpr))
18371858 if t != nil {
18381859 kind = t
18391860 }
@@ -1844,19 +1865,24 @@ impl typeChecker {
18441865 if kind == nil {
18451866 ret nil
18461867 }
1868+ mut typ := (&Type)(nil)
18471869 match type kind {
18481870 | &Type:
1849- ret kind.(&Type)
1871+ typ = kind.(&Type)
18501872 |:
1851- mut tk : = &Type{Kind: kind}
1873+ typ = &Type{Kind: kind}
18521874 if self.ignoredGenerics != nil {
18531875 _, prim := kind.(&Prim)
18541876 if prim {
1855- unsafe { *self.ignoredGenerics = append(*self.ignoredGenerics, tk ) }
1877+ unsafe { *self.ignoredGenerics = append(*self.ignoredGenerics, typ ) }
18561878 }
18571879 }
1858- ret tk
18591880 }
1881+ // Recheck needed, append type into collection.
1882+ if recheckNeeded {
1883+ unsafe { *self.recheckNeed = append(*self.recheckNeed, typ) }
1884+ }
1885+ ret typ
18601886 }
18611887
18621888 fn checkDecl(mut self, mut &decl: &ast::Expr): &Type {
@@ -1900,10 +1926,10 @@ impl typeChecker {
19001926
19011927 // Rechecks the recheckable type.
19021928 // See developer reference (15).
1903- fn recheck(mut self, mut &t: recheckableType , mut &errorToken: &token::Token): (ok: bool) {
1904- match type t {
1905- | &StructIns :
1906- mut s := t.(&StructIns )
1929+ fn recheck(mut self, mut &t: &Type , mut &errorToken: &token::Token): (ok: bool) {
1930+ match {
1931+ | t.SoftStruct() != nil :
1932+ mut s := t.SoftStruct( )
19071933 s.checked = false
19081934
19091935 // We need to hard-check methods, if it have any method.
@@ -1920,7 +1946,22 @@ impl typeChecker {
19201946 }
19211947 }
19221948
1923- ok = self._fromStructIns(s, errorToken)
1949+ // Recheck needed types will not be appended.
1950+ // So append instance to the collection. The buildStructIns will do it.
1951+ // Now, the instance s have resolved types completely.
1952+ // There is no risk for duplicated instances. Time to append.
1953+ //
1954+ // The buildStructIns returns common instance to avoid using duplicated instances.
1955+ // So the returned instance may be already existing or the same instance we pass.
1956+ // In both cases, use the result to make sure we have common instance.
1957+ s = self.buildStructIns(s, errorToken)
1958+ // The result instance is not nil, so analysis were successful.
1959+ // Update t.Kind with the instance s to make sure using common instance.
1960+ // Because all types must be point to the same common instance.
1961+ if s != nil {
1962+ ok = true
1963+ t.Kind = s
1964+ }
19241965 }
19251966 ret
19261967 }
0 commit comments