Skip to content

Commit 76a779d

Browse files
committed
Always compute asSeenFroms on opaque companion members
1 parent 5eb66d4 commit 76a779d

File tree

9 files changed

+117
-35
lines changed

9 files changed

+117
-35
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,9 +694,20 @@ object desugar {
694694
tdef.withFlags(tdef.mods.flags &~ Opaque)
695695
}
696696
else {
697+
def completeForwarder(fwd: Tree) = tdef.rhs match {
698+
case LambdaTypeTree(tparams, tpt) =>
699+
val tparams1 =
700+
for (tparam <- tparams)
701+
yield tparam.withMods(tparam.mods | Synthetic)
702+
assert(tparams.ne(tparams1))
703+
lambdaAbstract(tparams1,
704+
AppliedTypeTree(fwd, tparams.map(tparam => Ident(tparam.name))))
705+
case _ =>
706+
fwd
707+
}
697708
val moduleName = tdef.name.toTermName
698709
val aliasType = cpy.TypeDef(tdef)(
699-
rhs = Select(Ident(moduleName), tdef.name))
710+
rhs = completeForwarder(Select(Ident(moduleName), tdef.name)))
700711
val localType = tdef.withFlags(Synthetic | Opaque)
701712
val companions = moduleDef(ModuleDef(
702713
moduleName, Template(emptyConstructor, Nil, EmptyValDef, localType :: Nil))

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -763,9 +763,10 @@ object SymDenotations {
763763
*/
764764
def membersNeedAsSeenFrom(pre: Type)(implicit ctx: Context): Boolean =
765765
!( this.isTerm
766-
|| this.isStaticOwner
766+
|| this.isStaticOwner && !this.isOpaqueCompanion
767767
|| ctx.erasedTypes
768-
|| (pre eq NoPrefix) || (pre eq thisType)
768+
|| (pre eq NoPrefix)
769+
|| (pre eq thisType)
769770
)
770771

771772
/** Is this symbol concrete, or that symbol deferred? */

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
5353
tp match {
5454
case tp: NamedType =>
5555
val sym = tp.symbol
56-
if (sym.isStatic || (tp.prefix `eq` NoPrefix)) tp
56+
if (sym.isStaticOwner || (tp.prefix `eq` NoPrefix)) tp
5757
else derivedSelect(tp, atVariance(variance max 0)(this(tp.prefix)))
5858
case tp: ThisType =>
5959
toPrefix(pre, cls, tp.cls)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3884,7 +3884,7 @@ object Types {
38843884
extends CachedClassInfo(prefix, cls, Nil, decls, selfInfo) {
38853885

38863886
/** Install classinfo with known parents in `denot` s */
3887-
def finalize(denot: SymDenotation, parents: List[Type])(implicit ctx: Context): Unit =
3887+
def finalize(denot: SymDenotation, parents: List[Type], selfInfo: TypeOrSymbol)(implicit ctx: Context): Unit =
38883888
denot.info = ClassInfo(prefix, cls, parents, decls, selfInfo)
38893889

38903890
override def derivedClassInfo(prefix: Type)(implicit ctx: Context): ClassInfo =

compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ object Scala2Unpickler {
128128
else
129129
registerCompanionPair(scalacCompanion, denot.classSymbol)
130130

131-
tempInfo.finalize(denot, normalizedParents) // install final info, except possibly for typeparams ordering
131+
tempInfo.finalize(denot, normalizedParents, ost) // install final info, except possibly for typeparams ordering
132132
denot.ensureTypeParamsInCorrectOrder()
133133
}
134134
}

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

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -908,24 +908,10 @@ class Namer { typer: Typer =>
908908

909909
addAnnotations(denot.symbol)
910910

911-
/** The self type of an opaque companion is refined with the type-alias
912-
* of the original opaque type
913-
*/
914-
def refineOpaqueCompanionSelfType(mt: Type, stats: List[Tree]): RefinedType = stats match {
915-
case (td @ TypeDef(localName, rhs)) :: _
916-
if td.mods.is(SyntheticOpaque) && localName == name.stripModuleClassSuffix =>
917-
val alias = typedAheadType(rhs)(ctx.outer).tpe
918-
RefinedType(mt, localName, TypeAlias(alias))
919-
case _ :: stats1 =>
920-
refineOpaqueCompanionSelfType(mt, stats1)
921-
}
922-
923-
val selfInfo =
911+
val selfInfo: TypeOrSymbol =
924912
if (self.isEmpty) NoType
925913
else if (cls.is(Module)) {
926-
var moduleType = cls.owner.thisType select sourceModule
927-
if (cls.isOpaqueCompanion)
928-
moduleType = refineOpaqueCompanionSelfType(moduleType, rest)
914+
val moduleType = cls.owner.thisType select sourceModule
929915
if (self.name == nme.WILDCARD) moduleType
930916
else recordSym(
931917
ctx.newSymbol(cls, self.name, self.mods.flags, moduleType, coord = self.pos),
@@ -950,7 +936,32 @@ class Namer { typer: Typer =>
950936
ensureFirstIsClass(parents.map(checkedParentType(_)), cls.pos))
951937
typr.println(i"completing $denot, parents = $parents%, %, parentTypes = $parentTypes%, %")
952938

953-
tempInfo.finalize(denot, parentTypes)
939+
val finalSelfInfo: TypeOrSymbol =
940+
if (cls.isOpaqueCompanion) {
941+
// The self type of an opaque companion is refined with the type-alias of the original opaque type
942+
def refineOpaqueCompanionSelfType(mt: Type, stats: List[Tree]): RefinedType = (stats: @unchecked) match {
943+
case (td @ TypeDef(localName, rhs)) :: _
944+
if td.mods.is(SyntheticOpaque) && localName == name.stripModuleClassSuffix =>
945+
// create a context owned by the current opaque helper symbol,
946+
// but otherwise corresponding to the context enclosing the opaque
947+
// companion object, since that's where the rhs was defined.
948+
val aliasCtx = ctx.outer.fresh.setOwner(symbolOfTree(td))
949+
val alias = typedAheadType(rhs)(aliasCtx).tpe
950+
RefinedType(mt, localName, TypeAlias(alias))
951+
case _ :: stats1 =>
952+
refineOpaqueCompanionSelfType(mt, stats1)
953+
}
954+
selfInfo match {
955+
case self: Type =>
956+
refineOpaqueCompanionSelfType(self, rest)
957+
case self: Symbol =>
958+
self.info = refineOpaqueCompanionSelfType(self.info, rest)
959+
self
960+
}
961+
}
962+
else selfInfo
963+
964+
tempInfo.finalize(denot, parentTypes, finalSelfInfo)
954965

955966
Checking.checkWellFormed(cls)
956967
if (isDerivedValueClass(cls)) cls.setFlag(Final)

tests/neg/opaque-groups.scala

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package object groups {
2+
trait Semigroup[A] {
3+
def combine(x: A, y: A): A
4+
}
5+
6+
object Semigroup {
7+
def instance[A](f: (A, A) => A): Semigroup[A] =
8+
new Semigroup[A] {
9+
def combine(x: A, y: A): A = f(x, y)
10+
}
11+
}
12+
13+
type Id[A] = A
14+
15+
trait Wrapping[F[_]] {
16+
def wraps[G[_], A](ga: G[A]): G[F[A]]
17+
def unwrap[G[_], A](ga: G[F[A]]): G[A]
18+
}
19+
20+
abstract class Wrapper[F[_]] { self =>
21+
def wraps[G[_], A](ga: G[A]): G[F[A]]
22+
def unwrap[G[_], A](gfa: G[F[A]]): G[A]
23+
24+
final def apply[A](a: A): F[A] = wraps[Id, A](a)
25+
26+
implicit object WrapperWrapping extends Wrapping[F] {
27+
def wraps[G[_], A](ga: G[A]): G[F[A]] = self.wraps(ga)
28+
def unwrap[G[_], A](ga: G[F[A]]): G[A] = self.unwrap(ga)
29+
}
30+
}
31+
32+
// The following definition does not typecheck since the `First`
33+
// parent argument refers to the outer `First`, not the synthetic inner one.
34+
// See pos/opaque-groups.scala for a version that copmpiles.
35+
opaque type First[A] = A
36+
object First extends Wrapper[First] { // error: object creation impossible
37+
def wraps[G[_], A](ga: G[A]): G[First[A]] = ga // error: overriding
38+
def unwrap[G[_], A](gfa: G[First[A]]): G[A] = gfa
39+
implicit def firstSemigroup[A]: Semigroup[First[A]] =
40+
Semigroup.instance((x, y) => x)
41+
}
42+
43+
opaque type Last[A] = A
44+
object Last extends Wrapper[Last] { // error: object creation impossible
45+
def wraps[G[_], A](ga: G[A]): G[Last[A]] = ga // error: overriding
46+
def unwrap[G[_], A](gfa: G[Last[A]]): G[A] = gfa
47+
implicit def lastSemigroup[A]: Semigroup[Last[A]] =
48+
Semigroup.instance((x, y) => y)
49+
}
50+
}

tests/pos/opaque-groups.scala

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ package object groups {
1717
def unwrap[G[_], A](ga: G[F[A]]): G[A]
1818
}
1919

20-
abstract class Wrapper[F[_]] { self =>
20+
abstract class Wrapper { self =>
21+
type F[_]
2122
def wraps[G[_], A](ga: G[A]): G[F[A]]
2223
def unwrap[G[_], A](gfa: G[F[A]]): G[A]
2324

@@ -30,63 +31,71 @@ package object groups {
3031
}
3132

3233
opaque type First[A] = A
33-
object First extends Wrapper[First] {
34+
object First extends Wrapper {
35+
type F = First
3436
def wraps[G[_], A](ga: G[A]): G[First[A]] = ga
3537
def unwrap[G[_], A](gfa: G[First[A]]): G[A] = gfa
3638
implicit def firstSemigroup[A]: Semigroup[First[A]] =
3739
Semigroup.instance((x, y) => x)
3840
}
3941

4042
opaque type Last[A] = A
41-
object Last extends Wrapper[Last] {
43+
object Last extends Wrapper {
44+
type F = Last
4245
def wraps[G[_], A](ga: G[A]): G[Last[A]] = ga
4346
def unwrap[G[_], A](gfa: G[Last[A]]): G[A] = gfa
4447
implicit def lastSemigroup[A]: Semigroup[Last[A]] =
4548
Semigroup.instance((x, y) => y)
4649
}
4750

4851
opaque type Min[A] = A
49-
object Min extends Wrapper[Min] {
52+
object Min extends Wrapper {
53+
type F = Min
5054
def wraps[G[_], A](ga: G[A]): G[Min[A]] = ga
5155
def unwrap[G[_], A](gfa: G[Min[A]]): G[A] = gfa
5256
implicit def minSemigroup[A](implicit o: Ordering[A]): Semigroup[Min[A]] =
5357
Semigroup.instance(o.min)
5458
}
5559

5660
opaque type Max[A] = A
57-
object Max extends Wrapper[Max] {
61+
object Max extends Wrapper {
62+
type F = Max
5863
def wraps[G[_], A](ga: G[A]): G[Max[A]] = ga
5964
def unwrap[G[_], A](gfa: G[Max[A]]): G[A] = gfa
6065
implicit def maxSemigroup[A](implicit o: Ordering[A]): Semigroup[Max[A]] =
6166
Semigroup.instance(o.max)
6267
}
6368

6469
opaque type Plus[A] = A
65-
object Plus extends Wrapper[Plus] {
70+
object Plus extends Wrapper {
71+
type F = Plus
6672
def wraps[G[_], A](ga: G[A]): G[Plus[A]] = ga
6773
def unwrap[G[_], A](gfa: G[Plus[A]]): G[A] = gfa
6874
implicit def plusSemigroup[A](implicit n: Numeric[A]): Semigroup[Plus[A]] =
6975
Semigroup.instance(n.plus)
7076
}
7177

7278
opaque type Times[A] = A
73-
object Times extends Wrapper[Times] {
79+
object Times extends Wrapper {
80+
type F = Times
7481
def wraps[G[_], A](ga: G[A]): G[Times[A]] = ga
7582
def unwrap[G[_], A](gfa: G[Times[A]]): G[A] = gfa
7683
implicit def timesSemigroup[A](implicit n: Numeric[A]): Semigroup[Times[A]] =
7784
Semigroup.instance(n.times)
7885
}
7986

8087
opaque type Reversed[A] = A
81-
object Reversed extends Wrapper[Reversed] {
88+
object Reversed extends Wrapper {
89+
type F = Reversed
8290
def wraps[G[_], A](ga: G[A]): G[Reversed[A]] = ga
8391
def unwrap[G[_], A](gfa: G[Reversed[A]]): G[A] = gfa
8492
implicit def reversedOrdering[A](implicit o: Ordering[A]): Ordering[Reversed[A]] =
8593
o.reverse
8694
}
8795

8896
opaque type Unordered[A] = A
89-
object Unordered extends Wrapper[Unordered] {
97+
object Unordered extends Wrapper {
98+
type F = Unordered
9099
def wraps[G[_], A](ga: G[A]): G[Unordered[A]] = ga
91100
def unwrap[G[_], A](gfa: G[Unordered[A]]): G[A] = gfa
92101
implicit def unorderedOrdering[A]: Ordering[Unordered[A]] =

tests/pos/opaque-immutable-array.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ object ia {
55
opaque type IArray[A1] = Array[A1]
66

77
object IArray {
8-
inline def initialize[A](body: => Array[A]): IArray[A] = body
9-
inline def size[A](ia: IArray[A]): Int = ia.length
10-
inline def get[A](ia: IArray[A], i: Int): A = ia(i)
8+
def initialize[A](body: => Array[A]): IArray[A] = body
9+
def size[A](ia: IArray[A]): Int = ia.length
10+
def get[A](ia: IArray[A], i: Int): A = ia(i)
1111

1212
// return a sorted copy of the array
1313
def sorted[A <: AnyRef : math.Ordering](ia: IArray[A]): IArray[A] = {

0 commit comments

Comments
 (0)