Skip to content

Commit 7a840f5

Browse files
authored
Merge pull request #13219 from dotty-staging/fix-13190-backport
[backport] Fix separate compilation issues with opaque types
2 parents 3e099c3 + bbcc700 commit 7a840f5

File tree

22 files changed

+164
-14
lines changed

22 files changed

+164
-14
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ object SymDenotations {
407407
* @param tparams The type parameters with which the right-hand side bounds should be abstracted
408408
*
409409
*/
410-
def opaqueToBounds(info: Type, rhs: tpd.Tree, tparams: List[TypeParamInfo])(using Context): Type =
410+
def opaqueToBounds(info: Type, rhs: tpd.Tree, tparams: List[TypeSymbol])(using Context): Type =
411411

412412
def setAlias(tp: Type) =
413413
def recur(self: Type): Unit = self match

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4039,7 +4039,7 @@ object Types {
40394039
// ----- Type application: LambdaParam, AppliedType ---------------------
40404040

40414041
/** The parameter of a type lambda */
4042-
case class LambdaParam(tl: TypeLambda, n: Int) extends ParamInfo {
4042+
case class LambdaParam(tl: TypeLambda, n: Int) extends ParamInfo, printing.Showable {
40434043
type ThisName = TypeName
40444044

40454045
def isTypeParam(using Context): Boolean = tl.paramNames.head.isTypeName
@@ -4084,6 +4084,8 @@ object Types {
40844084
case _ =>
40854085
myVariance = Invariant
40864086
myVariance
4087+
4088+
def toText(printer: Printer): Text = printer.toText(this)
40874089
}
40884090

40894091
/** A type application `C[T_1, ..., T_n]` */

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -860,14 +860,24 @@ class TreeUnpickler(reader: TastyReader,
860860
sym.info = TypeBounds.empty // needed to avoid cyclic references when unpickling rhs, see i3816.scala
861861
sym.setFlag(Provisional)
862862
val rhs = readTpt()(using localCtx)
863-
sym.info = new NoCompleter {
863+
864+
sym.info = new NoCompleter:
864865
override def completerTypeParams(sym: Symbol)(using Context) =
865866
rhs.tpe.typeParams
866-
}
867-
sym.info = sym.opaqueToBounds(
868-
checkNonCyclic(sym, rhs.tpe.toBounds, reportErrors = false),
869-
rhs, rhs.tpe.typeParams)
870-
if sym.isOpaqueAlias then sym.typeRef.recomputeDenot() // make sure we see the new bounds from now on
867+
868+
def opaqueToBounds(info: Type): Type =
869+
val tparamSyms = rhs match
870+
case LambdaTypeTree(tparams, body) => tparams.map(_.symbol.asType)
871+
case _ => Nil
872+
sym.opaqueToBounds(info, rhs, tparamSyms)
873+
874+
val info = checkNonCyclic(sym, rhs.tpe.toBounds, reportErrors = false)
875+
if sym.isOpaqueAlias then
876+
sym.info = opaqueToBounds(info)
877+
sym.typeRef.recomputeDenot() // make sure we see the new bounds from now on
878+
else
879+
sym.info = info
880+
871881
sym.resetFlag(Provisional)
872882
TypeDef(rhs)
873883
}

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,12 @@ class PlainPrinter(_ctx: Context) extends Printer {
540540

541541
def toText(annot: Annotation): Text = s"@${annot.symbol.name}" // for now
542542

543+
def toText(param: LambdaParam): Text =
544+
varianceSign(param.paramVariance)
545+
~ toText(param.paramName)
546+
~ (if param.isTypeParam then "" else ": ")
547+
~ toText(param.paramInfo)
548+
543549
protected def escapedString(str: String): String = str flatMap escapedChar
544550

545551
def dclsText(syms: List[Symbol], sep: String): Text = Text(syms map dclText, sep)

compiler/src/dotty/tools/dotc/printing/Printer.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ package printing
44

55
import core._
66
import Texts._, ast.Trees._
7-
import Types.{Type, SingletonType}, Symbols.Symbol, Scopes.Scope, Constants.Constant,
7+
import Types.{Type, SingletonType, LambdaParam},
8+
Symbols.Symbol, Scopes.Scope, Constants.Constant,
89
Names.Name, Denotations._, Annotations.Annotation
910
import typer.Implicits.SearchResult
1011
import util.SourcePosition
@@ -130,6 +131,9 @@ abstract class Printer {
130131
/** Textual representation of type */
131132
def toText(tp: Type): Text
132133

134+
/** Textual representation of lambda param */
135+
def toText(tree: LambdaParam): Text
136+
133137
/** Textual representation of all symbols in given list,
134138
* using `dclText` for displaying each.
135139
*/

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ class Namer { typer: Typer =>
425425
* is still missing its parents. Parents are set to Nil when completion starts and are
426426
* set to the actual parents later. If a superclass completes a subclass in one
427427
* of its parents, the parents of the superclass or some intervening class might
428-
* not yet be set. This situation can be detected by asking for the baseType of Any -
428+
* not yet be set. This situation can be detected by asking for the baseType of Any -
429429
* if that type does not exist, one of the base classes of this class misses its parents.
430430
* If this situation arises, the computation of the superclass might be imprecise.
431431
* For instance, in i12722.scala, the superclass of `IPersonalCoinOps` is computed
@@ -988,9 +988,12 @@ class Namer { typer: Typer =>
988988
val unsafeInfo = if (isDerived) rhsBodyType else abstracted(rhsBodyType)
989989

990990
def opaqueToBounds(info: Type): Type =
991-
if sym.isOpaqueAlias && info.typeParams.nonEmpty && info.hkResult.typeParams.nonEmpty then
992-
report.error(em"opaque type alias cannot have multiple type parameter lists", rhs.srcPos)
993-
sym.opaqueToBounds(info, rhs1, tparamSyms)
991+
if sym.isOpaqueAlias then
992+
if info.typeParams.nonEmpty && info.hkResult.typeParams.nonEmpty then
993+
report.error(em"opaque type alias cannot have multiple type parameter lists", rhs.srcPos)
994+
sym.opaqueToBounds(info, rhs1, tparamSyms)
995+
else
996+
info
994997

995998
if (isDerived) sym.info = unsafeInfo
996999
else {

sbt-test/opaques/i12927/build.sbt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
scalaVersion := sys.props("plugin.scalaVersion")
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
object Foo:
2+
opaque type BlaBla[+T, D] = Int
3+
extension [T, D](token: BlaBla[T, D]) def data: D = ???
4+
5+
//To cause the crash, after initial clean compilation
6+
//replace `???` with `value.data` to cause the compiler crash
7+
def foo[W <: Int](value: Bar.BlaBla[W]): Unit = value.data
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
object Bar:
2+
type Fuzzy[W <: Int] = Int
3+
opaque type BlaBla[W <: Int] <: Foo.BlaBla[Fuzzy[W], Int] =
4+
Foo.BlaBla[Fuzzy[W], Int]

0 commit comments

Comments
 (0)