@@ -5,6 +5,8 @@ import scala.annotation.{switch, tailrec}
5
5
import scala .collection .mutable
6
6
import scala .reflect .io .AbstractFile
7
7
import Names .TastyName
8
+ import scala .reflect .internal .Variance
9
+ import scala .util .chaining ._
8
10
9
11
/** Unpickler for typed trees
10
12
* @param reader the reader from which to unpickle
@@ -29,18 +31,13 @@ class TreeUnpickler[Tasty <: TastyUniverse](
29
31
import TastyFlags ._
30
32
import Signature ._
31
33
import Contexts ._
32
- import TypeOps ._
33
34
34
35
@ inline
35
36
final protected def assertTasty (cond : Boolean , msg : => String )(implicit ctx : Context ): Unit =
36
37
if (! cond) {
37
38
errorTasty(msg)
38
39
}
39
40
40
- @ inline
41
- final protected def errorTasty (msg : String )(implicit ctx : Context ): Unit =
42
- reporter.error(noPosition, s " Scala 2 incompatible TASTy signature of ${ctx.source.name} in ${ctx.owner}: $msg" )
43
-
44
41
/** A map from addresses of definition entries to the symbols they define */
45
42
private val symAtAddr = new mutable.HashMap [Addr , Symbol ]
46
43
@@ -127,6 +124,12 @@ class TreeUnpickler[Tasty <: TastyUniverse](
127
124
override def complete (sym : Symbol ): Unit = throw new UnsupportedOperationException (" complete" )
128
125
}
129
126
127
+ final class ErrorCompleter (msg : Symbol => String ) extends TastyLazyType {
128
+ override def complete (sym : Symbol ): Unit = {
129
+ throw new symbolTable.TypeError (msg(sym))
130
+ }
131
+ }
132
+
130
133
class TreeReader (val reader : TastyReader ) {
131
134
import reader ._
132
135
@@ -294,38 +297,27 @@ class TreeUnpickler[Tasty <: TastyUniverse](
294
297
val tag = readByte()
295
298
ctx.log(s " reading type ${astTagToString(tag)} at $start" )
296
299
297
- def registeringType [T ](tp : Type , op : => T ): T = {
300
+ def registeringTypeWith [T ](tp : Type , op : => T ): T = {
298
301
typeAtAddr(start) = tp
299
302
op
300
303
}
301
304
302
305
def readLengthType (): Type = {
303
306
val end = readEnd()
304
307
305
- def readMethodic [N <: Name , PInfo <: Type , LT <: LambdaType ]
306
- (companion : LambdaTypeCompanion [N , PInfo , LT ], nameMap : TastyName => N )(implicit ctx : Context ): Type = {
307
- val complete = typeAtAddr.contains(start)
308
- val stored = typeAtAddr.getOrElse(start, {
308
+ def readMethodic [N <: Name , PInfo <: Type , LT <: LambdaType , Res <: Type ]
309
+ (companion : LambdaTypeCompanion [N , PInfo , LT , Res ], nameMap : TastyName => N )(implicit ctx : Context ): Res = {
310
+ val result = typeAtAddr.getOrElse(start, {
309
311
val nameReader = fork
310
312
nameReader.skipTree() // skip result
311
313
val paramReader = nameReader.fork
312
- val paramNames = nameReader.readParamNames(end).map(nameMap)
313
- companion(paramNames)(
314
- pt => registeringType (pt, paramReader.readParamTypes[PInfo ](end)),
315
- pt => readType())
314
+ val paramNames = nameReader.readParamNames(end)
315
+ companion(paramNames)(nameMap,
316
+ pt => registeringTypeWith (pt, paramReader.readParamTypes[PInfo ](end)),
317
+ pt => readType()).tap(typeAtAddr(start) = _)
316
318
})
317
319
goto(end)
318
- val canonical = {
319
- if (complete) {
320
- stored
321
- }
322
- else {
323
- val canonical = stored.asInstanceOf [LT ].canonicalForm
324
- typeAtAddr.update(start, canonical)
325
- canonical
326
- }
327
- }
328
- canonical
320
+ result.asInstanceOf [Res ]
329
321
}
330
322
331
323
val result =
@@ -357,12 +349,11 @@ class TreeUnpickler[Tasty <: TastyUniverse](
357
349
// // Note that the lambda "rt => ..." is not equivalent to a wildcard closure!
358
350
// // Eta expansion of the latter puts readType() out of the expression.
359
351
case APPLIEDtype =>
360
- val tpe = readType()
361
- mkTypeRef(tpe.typeSymbolDirect.owner.tpe, tpe.typeSymbolDirect, until(end)(readType()))
352
+ boundedAppliedType(readType(), until(end)(readType()))
362
353
case TYPEBOUNDS =>
363
354
val lo = readType()
364
355
val hi = readType()
365
- mkTypeBounds (lo, hi) // if (lo.isMatch && (lo `eq` hi)) MatchAlias(lo) else TypeBounds(lo, hi)
356
+ TypeBounds .bounded (lo, hi) // if (lo.isMatch && (lo `eq` hi)) MatchAlias(lo) else TypeBounds(lo, hi)
366
357
case ANNOTATEDtype =>
367
358
mkAnnotatedType(readType(), mkAnnotation(readTerm()))
368
359
case ANDtype =>
@@ -388,9 +379,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
388
379
case TYPELAMBDAtype =>
389
380
readMethodic(HKTypeLambda , _.toEncodedTermName.toTypeName)
390
381
case PARAMtype =>
391
- readTypeRef() match {
392
- case binder : LambdaType => binder.paramRefs(readNat())
393
- }
382
+ readTypeRef().typeParams(readNat()).ref
394
383
}
395
384
assert(currentAddr === end, s " $start $currentAddr $end ${astTagToString(tag)}" )
396
385
result
@@ -399,32 +388,21 @@ class TreeUnpickler[Tasty <: TastyUniverse](
399
388
def readSimpleType (): Type = {
400
389
(tag : @ switch) match {
401
390
case TYPEREFdirect | TERMREFdirect =>
402
- mkTypeRef(noPrefix, readSymRef(), Nil )
391
+ readSymRef().termRef
403
392
case TYPEREFsymbol | TERMREFsymbol =>
404
393
readSymNameRef()
405
394
case TYPEREFpkg =>
406
- readPackageRef().moduleClass.typeRef
395
+ readPackageRef().moduleClass.ref
407
396
case TERMREFpkg =>
408
397
readPackageRef().termRef
409
398
case TYPEREF =>
410
399
val name = readTastyName()
411
400
val pre = readType()
412
- if (pre.typeSymbol === defn.ScalaPackage && ( name === nme.And || name === nme.Or ) ) {
413
- if (name === nme.And ) {
414
- AndType
415
- }
416
- else {
417
- errorTasty(s " Union types are not currently supported, [found reference to scala. $name at Addr( $start) in ${ctx.classRoot}] " )
418
- errorType
419
- }
420
- }
421
- else {
422
- mkTypeRef(pre, name, selectingTerm = false )
423
- }
401
+ selectType(pre, name)
424
402
case TERMREF =>
425
- val sname = readTastyName()
403
+ val name = readTastyName()
426
404
val prefix = readType()
427
- mkTypeRef (prefix, sname, selectingTerm = true )
405
+ selectTerm (prefix, name )
428
406
case THIS =>
429
407
val sym = readType() match {
430
408
case tpe : TypeRef => tpe.sym
@@ -447,7 +425,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
447
425
val ref = readAddr()
448
426
typeAtAddr.getOrElseUpdate(ref, forkAt(ref).readType())
449
427
case BYNAMEtype =>
450
- mkAppliedType( defn.ByNameParamClass , readType()) // ExprType(readType())
428
+ defn.ByNameParamClass .ref( readType() :: Nil ) // ExprType(readType())
451
429
case ENUMconst =>
452
430
errorTasty(" Enum Constant" ) // Constant(readTypeRef().termSymbol)
453
431
errorType
@@ -462,14 +440,14 @@ class TreeUnpickler[Tasty <: TastyUniverse](
462
440
private def readSymNameRef ()(implicit ctx : Context ): Type = {
463
441
val sym = readSymRef()
464
442
val prefix = readType()
465
- val res = NamedType (prefix, sym)
466
- prefix match {
467
- case prefix : ThisType if (prefix.sym `eq` sym.owner) && sym.isTypeParameter /* && !sym.is(Opaque)*/ =>
468
- mkTypeRef(noPrefix, sym, Nil )
469
- // without this precaution we get an infinite cycle when unpickling pos/extmethods.scala
470
- // the problem arises when a self type of a trait is a type parameter of the same trait.
471
- case _ => res
472
- }
443
+ // TODO tasty: restore this if github:lampepfl/dotty/tests/pos/extmethods.scala causes infinite loop
444
+ // prefix match {
445
+ // case prefix: ThisType if (prefix.sym `eq` sym.owner) && sym.isTypeParameter /*&& !sym.is(Opaque)*/ =>
446
+ // mkAppliedType( sym, Nil)
447
+ // // without this precaution we get an infinite cycle when unpickling pos/extmethods.scala
448
+ // // the problem arises when a self type of a trait is a type parameter of the same trait.
449
+ // }
450
+ NamedType (prefix, sym)
473
451
}
474
452
475
453
private def readPackageRef ()(implicit ctx : Context ): TermSymbol = {
@@ -869,10 +847,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
869
847
val unsupported = completer.tastyFlagSet &~ supported
870
848
assertTasty(! unsupported, s " unsupported Scala 3 flags on $sym: ${show(unsupported)}" )
871
849
if (completer.tastyFlagSet.is(Inline )) {
872
- sym.addAnnotation(
873
- symbolTable.symbolOf[annotation.compileTimeOnly],
874
- Literal (Constant (s " Unsupported Scala 3 inline $sym" ))
875
- )
850
+ attachCompiletimeOnly(sym, s " Unsupported Scala 3 inline $sym" )
876
851
}
877
852
if (completer.tastyFlagSet.is(Extension )) ctx.log(s " $name is a Scala 3 extension method. " )
878
853
val typeParams = {
@@ -886,24 +861,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
886
861
}
887
862
val vparamss = readParamss(localCtx)
888
863
val tpt = readTpt()(localCtx)
889
- val valueParamss = ctx.normalizeIfConstructor(
890
- vparamss.map(_.map(symFromNoCycle)), name === nme.CONSTRUCTOR )
891
- // if (tname === TastyName.SimpleName("apply")
892
- // && sym.is(Synthetic)) {
893
- // sym.flags = sym.flags | Case
894
- // }
895
- // val retType =
896
- // if (tname === TastyName.SimpleName("unapply")
897
- // && sym.is(Synthetic)) {
898
- // sym.flags = sym.flags | Case
899
- // sym.owner.companion.caseFieldAccessors.map(_.tpe) match {
900
- // case Nil => defn.BooleanTpe
901
- // case value :: Nil => defn.optionType(dropNullaryMethod(value))
902
- // case values => defn.optionType(defn.tupleType(values.map(dropNullaryMethod)))
903
- // }
904
- // } else {
905
- // tpt.tpe
906
- // }
864
+ val valueParamss = ctx.normalizeIfConstructor(vparamss.map(_.map(symFromNoCycle)), name === nme.CONSTRUCTOR )
907
865
val resType = ctx.effectiveResultType(sym, typeParams, tpt.tpe)
908
866
sym.info = ctx.methodType(if (name === nme.CONSTRUCTOR ) Nil else typeParams, valueParamss, resType)
909
867
NoCycle (at = symAddr)
@@ -923,15 +881,22 @@ class TreeUnpickler[Tasty <: TastyUniverse](
923
881
readTemplate(symAddr)(localCtx)
924
882
}
925
883
else {
926
- sym.info = emptyTypeBounds // needed to avoid cyclic references when unpickling rhs, see i3816.scala
884
+ sym.info = TypeBounds .empty // needed to avoid cyclic references when unpickling rhs, see i3816.scala
927
885
// sym.setFlag(Provisional)
928
886
val rhs = readTpt()(localCtx)
929
887
sym.info = new NoCompleter {
930
888
override def completerTypeParams (sym : Symbol )(implicit ctx : Context ) =
931
889
rhs.tpe.typeParams
932
890
}
933
891
// TODO check for cycles
934
- sym.info = rhs.tpe.stripLowerBoundsIfPoly
892
+ sym.info = rhs.tpe match {
893
+ case bounds @ TypeBounds (lo : PolyType , hi : PolyType ) if ! (mergeableParams(lo,hi)) =>
894
+ new ErrorCompleter (owner =>
895
+ s " $owner has diverging type lambdas as bounds: $bounds" )
896
+ case tpe : TypeBounds => normaliseBounds(tpe)
897
+ case tpe => tpe
898
+ }
899
+ if (sym.is(Param )) sym.flags &= ~ (Private | Protected )
935
900
// sym.normalizeOpaque()
936
901
// sym.resetFlag(Provisional)
937
902
NoCycle (at = symAddr)
@@ -949,7 +914,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
949
914
}
950
915
case _ => sys.error(s " Reading new member with tag ${astTagToString(tag)}" )
951
916
}
952
- ctx.log(s " typed ${showSym(sym)} : ${sym.tpe} in owner ${showSym(sym.owner)}" )
917
+ ctx.log(s " typed ${showSym(sym)} : ${if ( sym.isClass) sym. tpe else sym.info } in owner ${showSym(sym.owner)}" )
953
918
goto(end)
954
919
noCycle
955
920
}
@@ -1277,7 +1242,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
1277
1242
val selector = if (isTerm) encoded else encoded.toTypeName
1278
1243
val localCtx = ctx // if (name === nme.CONSTRUCTOR) ctx.addMode(Mode.) else ctx
1279
1244
def tpeFun (localCtx : Context , selector : Name , qualType : Type ): Type =
1280
- if (sig `eq` NotAMethod ) mkTypeRef (qualType, name, isTerm)
1245
+ if (sig `eq` NotAMethod ) selectFromPrefix (qualType, name, isTerm)
1281
1246
else selectFromSig(qualType, selector, sig)(localCtx)
1282
1247
f(localCtx, selector, tpeFun)
1283
1248
}
@@ -1480,8 +1445,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
1480
1445
val tpe = mkIntersectionType(args.map(_.tpe))
1481
1446
CompoundTypeTree (args).setType(tpe)
1482
1447
} else {
1483
- val ownType = mkTypeRef(tycon.tpe.prefix, tycon.tpe.typeSymbolDirect, args.map(_.tpe))
1484
- AppliedTypeTree (tycon, args).setType(ownType)
1448
+ AppliedTypeTree (tycon, args).setType(boundedAppliedType(tycon.tpe, args.map(_.tpe)))
1485
1449
}
1486
1450
case ANNOTATEDtpt =>
1487
1451
val tpt = readTpt()
@@ -1490,7 +1454,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
1490
1454
case LAMBDAtpt =>
1491
1455
val tparams = readParams[NoCycle ](TYPEPARAM )
1492
1456
val body = readTpt()
1493
- TypeTree (TypeParamLambda (tparams.map(symFromNoCycle), body.tpe).canonicalForm ) // LambdaTypeTree(tparams, body)
1457
+ TypeTree (mkLambdaFromParams (tparams.map(symFromNoCycle), body.tpe)) // LambdaTypeTree(tparams, body)
1494
1458
// case MATCHtpt =>
1495
1459
// val fst = readTpt()
1496
1460
// val (bound, scrut) =
@@ -1499,7 +1463,7 @@ class TreeUnpickler[Tasty <: TastyUniverse](
1499
1463
case TYPEBOUNDStpt =>
1500
1464
val lo = readTpt()
1501
1465
val hi = if (currentAddr === end) lo else readTpt()
1502
- TypeBoundsTree (lo, hi).setType(mkTypeBounds (lo.tpe, hi.tpe))
1466
+ TypeBoundsTree (lo, hi).setType(TypeBounds .bounded (lo.tpe, hi.tpe))
1503
1467
// case HOLE =>
1504
1468
// readHole(end, isType = false)
1505
1469
// case _ =>
0 commit comments