@@ -822,8 +822,11 @@ class Namer { typer: Typer =>
822
822
if (sym.is(Module )) moduleValSig(sym)
823
823
else valOrDefDefSig(original, sym, Nil , identity)(using localContext(sym).setNewScope)
824
824
case original : DefDef =>
825
- val typer1 = ctx.typer.newLikeThis(ctx.nestingLevel + 1 )
826
- nestedTyper(sym) = typer1
825
+ // For the primary constructor DefDef, it is:
826
+ // * indexed as a part of completing the class, with indexConstructor; and
827
+ // * typed ahead when completing the constructor
828
+ // So we need to make sure to reuse the same local/nested typer.
829
+ val typer1 = nestedTyper.getOrElseUpdate(sym, ctx.typer.newLikeThis(ctx.nestingLevel + 1 ))
827
830
typer1.defDefSig(original, sym, this )(using localContext(sym).setTyper(typer1))
828
831
case imp : Import =>
829
832
try
@@ -833,6 +836,12 @@ class Namer { typer: Typer =>
833
836
typr.println(s " error while completing ${imp.expr}" )
834
837
throw ex
835
838
839
+ /** Context setup for indexing the constructor. */
840
+ def indexConstructor (constr : DefDef , sym : Symbol ): Unit =
841
+ val typer1 = ctx.typer.newLikeThis(ctx.nestingLevel + 1 )
842
+ nestedTyper(sym) = typer1
843
+ typer1.indexConstructor(constr, sym)(using localContext(sym).setTyper(typer1))
844
+
836
845
final override def complete (denot : SymDenotation )(using Context ): Unit = {
837
846
if (Config .showCompletions && ctx.typerState != creationContext.typerState) {
838
847
def levels (c : Context ): Int =
@@ -988,15 +997,19 @@ class Namer { typer: Typer =>
988
997
989
998
/** If completion of the owner of the to be completed symbol has not yet started,
990
999
* complete the owner first and check again. This prevents cyclic references
991
- * where we need to copmplete a type parameter that has an owner that is not
1000
+ * where we need to complete a type parameter that has an owner that is not
992
1001
* yet completed. Test case is pos/i10967.scala.
993
1002
*/
994
1003
override def needsCompletion (symd : SymDenotation )(using Context ): Boolean =
995
1004
val owner = symd.owner
996
1005
! owner.exists
997
1006
|| owner.is(Touched )
998
1007
|| {
999
- owner.ensureCompleted()
1008
+ // Only complete the owner if it's a type (eg. the class that owns a type parameter)
1009
+ // This avoids completing primary constructor methods while completing the type of one of its type parameters
1010
+ // See i15177.scala.
1011
+ if owner.isType then
1012
+ owner.ensureCompleted()
1000
1013
! symd.isCompleted
1001
1014
}
1002
1015
@@ -1521,7 +1534,10 @@ class Namer { typer: Typer =>
1521
1534
index(constr)
1522
1535
index(rest)(using localCtx)
1523
1536
1524
- checkCaseClassParamDependencies(symbolOfTree(constr).info, cls) // Completes constr symbol as a side effect
1537
+ val constrSym = symbolOfTree(constr)
1538
+ constrSym.infoOrCompleter match
1539
+ case completer : Completer => completer.indexConstructor(constr, constrSym)
1540
+ case _ =>
1525
1541
1526
1542
tempInfo = denot.asClass.classInfo.integrateOpaqueMembers.asInstanceOf [TempClassInfo ]
1527
1543
denot.info = savedInfo
@@ -1751,6 +1767,17 @@ class Namer { typer: Typer =>
1751
1767
val sym = tree.symbol
1752
1768
if sym.isConstructor then sym.owner else sym
1753
1769
1770
+ /** Index the primary constructor of a class, as a part of completing that class.
1771
+ * This allows the rest of the constructor completion to be deferred,
1772
+ * which avoids non-cyclic classes failing, e.g. pos/i15177.
1773
+ */
1774
+ def indexConstructor (constr : DefDef , sym : Symbol )(using Context ): Unit =
1775
+ index(constr.leadingTypeParams)
1776
+ sym.owner.typeParams.foreach(_.ensureCompleted())
1777
+ completeTrailingParamss(constr, sym, indexingCtor = true )
1778
+ if Feature .enabled(modularity) then
1779
+ constr.termParamss.foreach(_.foreach(setTracked))
1780
+
1754
1781
/** The signature of a module valdef.
1755
1782
* This will compute the corresponding module class TypeRef immediately
1756
1783
* without going through the defined type of the ValDef. This is necessary
@@ -1872,13 +1899,13 @@ class Namer { typer: Typer =>
1872
1899
// 3. Info of CP is computed (to be copied to DP).
1873
1900
// 4. CP is completed.
1874
1901
// 5. Info of CP is copied to DP and DP is completed.
1875
- index(ddef.leadingTypeParams)
1876
- if (isConstructor) sym.owner.typeParams.foreach(_.ensureCompleted() )
1902
+ if ! sym.isPrimaryConstructor then
1903
+ index(ddef.leadingTypeParams )
1877
1904
val completedTypeParams =
1878
1905
for tparam <- ddef.leadingTypeParams yield typedAheadExpr(tparam).symbol
1879
1906
if completedTypeParams.forall(_.isType) then
1880
1907
completer.setCompletedTypeParams(completedTypeParams.asInstanceOf [List [TypeSymbol ]])
1881
- completeTrailingParamss(ddef, sym)
1908
+ completeTrailingParamss(ddef, sym, indexingCtor = false )
1882
1909
val paramSymss = normalizeIfConstructor(ddef.paramss.nestedMap(symbolOfTree), isConstructor)
1883
1910
sym.setParamss(paramSymss)
1884
1911
@@ -1890,11 +1917,11 @@ class Namer { typer: Typer =>
1890
1917
wrapMethType(addParamRefinements(restpe, paramSymss))
1891
1918
1892
1919
if isConstructor then
1893
- if sym.isPrimaryConstructor && Feature .enabled(modularity) then
1894
- ddef.termParamss.foreach(_.foreach(setTracked))
1895
1920
// set result type tree to unit, but take the current class as result type of the symbol
1896
1921
typedAheadType(ddef.tpt, defn.UnitType )
1897
- wrapMethType(effectiveResultType(sym, paramSymss))
1922
+ val mt = wrapMethType(effectiveResultType(sym, paramSymss))
1923
+ if sym.isPrimaryConstructor then checkCaseClassParamDependencies(mt, sym.owner)
1924
+ mt
1898
1925
else if sym.isAllOf(Given | Method ) && Feature .enabled(modularity) then
1899
1926
// set every context bound evidence parameter of a given companion method
1900
1927
// to be tracked, provided it has a type that has an abstract type member.
@@ -1907,30 +1934,37 @@ class Namer { typer: Typer =>
1907
1934
valOrDefDefSig(ddef, sym, paramSymss, wrapMethType)
1908
1935
end defDefSig
1909
1936
1910
- def completeTrailingParamss (ddef : DefDef , sym : Symbol )(using Context ): Unit =
1937
+ /** Complete the trailing parameters of a DefDef,
1938
+ * as a part of indexing the primary constructor or
1939
+ * as a part of completing a DefDef, including the primary constructor.
1940
+ */
1941
+ def completeTrailingParamss (ddef : DefDef , sym : Symbol , indexingCtor : Boolean )(using Context ): Unit =
1911
1942
// A map from context-bounded type parameters to associated evidence parameter names
1912
1943
val witnessNamesOfParam = mutable.Map [TypeDef , List [TermName ]]()
1913
- if ! ddef.name.is(DefaultGetterName ) && ! sym.is(Synthetic ) then
1944
+ if ! ddef.name.is(DefaultGetterName ) && ! sym.is(Synthetic ) && (indexingCtor || ! sym.isPrimaryConstructor) then
1914
1945
for params <- ddef.paramss; case tdef : TypeDef <- params do
1915
1946
for case WitnessNamesAnnot (ws) <- tdef.mods.annotations do
1916
1947
witnessNamesOfParam(tdef) = ws
1917
1948
1918
- /** Is each name in `wnames` defined somewhere in the longest prefix of all `params`
1919
- * that have been typed ahead (i.e. that carry the TypedAhead attachment)?
1920
- */
1921
- def allParamsSeen (wnames : List [TermName ], params : List [MemberDef ]) =
1922
- (wnames.toSet[Name ] -- params.takeWhile(_.hasAttachment(TypedAhead )).map(_.name)).isEmpty
1949
+ /** Is each name in `wnames` defined somewhere in the previous parameters? */
1950
+ def allParamsSeen (wnames : List [TermName ], prevParams : Set [Name ]) =
1951
+ (wnames.toSet[Name ] -- prevParams).isEmpty
1923
1952
1924
1953
/** Enter and typecheck parameter list.
1925
1954
* Once all witness parameters for a context bound are seen, create a
1926
1955
* context bound companion for it.
1927
1956
*/
1928
1957
def completeParams (params : List [MemberDef ])(using Context ): Unit =
1929
- index(params)
1958
+ if indexingCtor || ! sym.isPrimaryConstructor then
1959
+ index(params)
1960
+ var prevParams = Set .empty[Name ]
1930
1961
for param <- params do
1931
- typedAheadExpr(param)
1962
+ if ! indexingCtor then
1963
+ typedAheadExpr(param)
1964
+
1965
+ prevParams += param.name
1932
1966
for (tdef, wnames) <- witnessNamesOfParam do
1933
- if wnames.contains(param.name) && allParamsSeen(wnames, params ) then
1967
+ if wnames.contains(param.name) && allParamsSeen(wnames, prevParams ) then
1934
1968
addContextBoundCompanionFor(symbolOfTree(tdef), wnames, params.map(symbolOfTree))
1935
1969
1936
1970
ddef.trailingParamss.foreach(completeParams)
@@ -1961,7 +1995,7 @@ class Namer { typer: Typer =>
1961
1995
def setTracked (param : ValDef )(using Context ): Unit =
1962
1996
val sym = symbolOfTree(param)
1963
1997
sym.maybeOwner.maybeOwner.infoOrCompleter match
1964
- case info : TempClassInfo if needsTracked(sym, param) =>
1998
+ case info : ClassInfo if needsTracked(sym, param) =>
1965
1999
typr.println(i " set tracked $param, $sym: ${sym.info} containing ${sym.info.memberNames(abstractTypeNameFilter).toList}" )
1966
2000
for acc <- info.decls.lookupAll(sym.name) if acc.is(ParamAccessor ) do
1967
2001
acc.resetFlag(PrivateLocal )
0 commit comments