Skip to content

Commit e7f0e2a

Browse files
authored
Merge pull request #7223 from dotty-staging/fix-7219
Fix #7219: export forwarder should use TypeAlias for parameterless class
2 parents b63c3e5 + 80880d5 commit e7f0e2a

File tree

4 files changed

+83
-20
lines changed

4 files changed

+83
-20
lines changed

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

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import ast._
77
import Trees._, StdNames._, Scopes._, Denotations._, Comments._
88
import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._
99
import NameKinds.DefaultGetterName
10+
import TypeApplications.TypeParamInfo
1011
import ast.desugar, ast.desugar._
1112
import ProtoTypes._
1213
import util.Spans._
@@ -977,43 +978,33 @@ class Namer { typer: Typer =>
977978
*/
978979
def addForwarder(alias: TermName, mbr: SingleDenotation, span: Span): Unit =
979980
if (whyNoForwarder(mbr) == "") {
980-
981-
/** The info of a forwarder to type `ref` which has info `info`
982-
*/
983-
def fwdInfo(ref: Type, info: Type): Type = info match {
984-
case _: ClassInfo =>
985-
HKTypeLambda.fromParams(info.typeParams, ref)
986-
case _: TypeBounds =>
987-
TypeAlias(ref)
988-
case info: HKTypeLambda =>
989-
info.derivedLambdaType(info.paramNames, info.paramInfos,
990-
fwdInfo(ref.appliedTo(info.paramRefs), info.resultType))
991-
case info => // should happen only in error cases
992-
info
993-
}
994-
981+
val sym = mbr.symbol
995982
val forwarder =
996983
if (mbr.isType)
997984
ctx.newSymbol(
998985
cls, alias.toTypeName,
999986
Exported | Final,
1000-
fwdInfo(path.tpe.select(mbr.symbol), mbr.info),
987+
TypeAlias(path.tpe.select(sym)),
1001988
coord = span)
989+
// Note: This will always create unparameterzied aliases. So even if the original type is
990+
// a parameterized class, say `C[X]` the alias will read `type C = d.C`. We currently do
991+
// allow such type aliases. If we forbid them at some point (requiring the referred type to be
992+
// fully applied), we'd have to change the scheme here as well.
1002993
else {
1003994
val (maybeStable, mbrInfo) =
1004-
if (mbr.symbol.isStableMember && mbr.symbol.isPublic)
1005-
(StableRealizable, ExprType(path.tpe.select(mbr.symbol)))
995+
if (sym.isStableMember && sym.isPublic)
996+
(StableRealizable, ExprType(path.tpe.select(sym)))
1006997
else
1007998
(EmptyFlags, mbr.info.ensureMethodic)
1008-
val mbrFlags = Exported | Method | Final | maybeStable | mbr.symbol.flags & RetainedExportFlags
999+
val mbrFlags = Exported | Method | Final | maybeStable | sym.flags & RetainedExportFlags
10091000
ctx.newSymbol(cls, alias, mbrFlags, mbrInfo, coord = span)
10101001
}
10111002
forwarder.info = avoidPrivateLeaks(forwarder)
10121003
val forwarderDef =
10131004
if (forwarder.isType) tpd.TypeDef(forwarder.asType)
10141005
else {
10151006
import tpd._
1016-
val ref = path.select(mbr.symbol.asTerm)
1007+
val ref = path.select(sym.asTerm)
10171008
tpd.polyDefDef(forwarder.asTerm, targs => prefss =>
10181009
ref.appliedToTypes(targs).appliedToArgss(prefss)
10191010
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
object Foo {
2+
enum MyEnum {
3+
case Red
4+
case Blue(msg: String)
5+
}
6+
export MyEnum._
7+
}
8+
9+
object Bar {
10+
type Blue = Foo.Blue
11+
}
12+
13+
import Foo._
14+
15+
def foo(a: MyEnum): Seq[Bar.Blue] = a match {
16+
case Red => Seq.empty
17+
case m: Foo.Blue => Seq(m)
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
object Foo {
2+
enum MyEnum {
3+
case Red
4+
case Blue(msg: String)
5+
}
6+
export MyEnum._
7+
}
8+
9+
object Bar {
10+
export Foo.Blue
11+
}
12+
13+
import Foo._
14+
15+
def foo(a: MyEnum): Seq[Bar.Blue] = a match {
16+
case Red => Seq.empty
17+
case m: Foo.Blue => Seq(m)
18+
}

tests/pos/i7219.scala

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
class Foo {
2+
object MyEnum {
3+
class Blue
4+
}
5+
export MyEnum._
6+
7+
val a: MyEnum.Blue = ???
8+
a : Blue // ok
9+
}
10+
11+
object Test {
12+
object Types {
13+
type T <: AnyRef
14+
type U = T
15+
type TC[X] <: AnyRef
16+
type UC[X] = TC[(X, X)]
17+
class C
18+
class D[X] extends C
19+
def x1: T = ???
20+
def x2: U = ???
21+
def x3: TC[Int] = ???
22+
def x4: UC[Int] = ???
23+
def x5: C = C()
24+
def x6: D[Int] = D()
25+
}
26+
export Types._
27+
type D1 = Types.D
28+
type U1 = Types.UC
29+
30+
val y1: T = x1
31+
val y2: U = x2
32+
val y3: TC[Int] = x3
33+
val y4: UC[Int] = x4
34+
val y5: C = x5
35+
val y6: D[Int] = x6
36+
}

0 commit comments

Comments
 (0)