Skip to content

Commit

Permalink
Merge pull request #7223 from dotty-staging/fix-7219
Browse files Browse the repository at this point in the history
Fix #7219: export forwarder should use TypeAlias for parameterless class
  • Loading branch information
liufengyun authored Sep 26, 2019
2 parents b63c3e5 + 80880d5 commit e7f0e2a
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 20 deletions.
31 changes: 11 additions & 20 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ast._
import Trees._, StdNames._, Scopes._, Denotations._, Comments._
import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._
import NameKinds.DefaultGetterName
import TypeApplications.TypeParamInfo
import ast.desugar, ast.desugar._
import ProtoTypes._
import util.Spans._
Expand Down Expand Up @@ -977,43 +978,33 @@ class Namer { typer: Typer =>
*/
def addForwarder(alias: TermName, mbr: SingleDenotation, span: Span): Unit =
if (whyNoForwarder(mbr) == "") {

/** The info of a forwarder to type `ref` which has info `info`
*/
def fwdInfo(ref: Type, info: Type): Type = info match {
case _: ClassInfo =>
HKTypeLambda.fromParams(info.typeParams, ref)
case _: TypeBounds =>
TypeAlias(ref)
case info: HKTypeLambda =>
info.derivedLambdaType(info.paramNames, info.paramInfos,
fwdInfo(ref.appliedTo(info.paramRefs), info.resultType))
case info => // should happen only in error cases
info
}

val sym = mbr.symbol
val forwarder =
if (mbr.isType)
ctx.newSymbol(
cls, alias.toTypeName,
Exported | Final,
fwdInfo(path.tpe.select(mbr.symbol), mbr.info),
TypeAlias(path.tpe.select(sym)),
coord = span)
// Note: This will always create unparameterzied aliases. So even if the original type is
// a parameterized class, say `C[X]` the alias will read `type C = d.C`. We currently do
// allow such type aliases. If we forbid them at some point (requiring the referred type to be
// fully applied), we'd have to change the scheme here as well.
else {
val (maybeStable, mbrInfo) =
if (mbr.symbol.isStableMember && mbr.symbol.isPublic)
(StableRealizable, ExprType(path.tpe.select(mbr.symbol)))
if (sym.isStableMember && sym.isPublic)
(StableRealizable, ExprType(path.tpe.select(sym)))
else
(EmptyFlags, mbr.info.ensureMethodic)
val mbrFlags = Exported | Method | Final | maybeStable | mbr.symbol.flags & RetainedExportFlags
val mbrFlags = Exported | Method | Final | maybeStable | sym.flags & RetainedExportFlags
ctx.newSymbol(cls, alias, mbrFlags, mbrInfo, coord = span)
}
forwarder.info = avoidPrivateLeaks(forwarder)
val forwarderDef =
if (forwarder.isType) tpd.TypeDef(forwarder.asType)
else {
import tpd._
val ref = path.select(mbr.symbol.asTerm)
val ref = path.select(sym.asTerm)
tpd.polyDefDef(forwarder.asTerm, targs => prefss =>
ref.appliedToTypes(targs).appliedToArgss(prefss)
)
Expand Down
18 changes: 18 additions & 0 deletions tests/pos-special/fatal-warnings/i7219.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
object Foo {
enum MyEnum {
case Red
case Blue(msg: String)
}
export MyEnum._
}

object Bar {
type Blue = Foo.Blue
}

import Foo._

def foo(a: MyEnum): Seq[Bar.Blue] = a match {
case Red => Seq.empty
case m: Foo.Blue => Seq(m)
}
18 changes: 18 additions & 0 deletions tests/pos-special/fatal-warnings/i7219b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
object Foo {
enum MyEnum {
case Red
case Blue(msg: String)
}
export MyEnum._
}

object Bar {
export Foo.Blue
}

import Foo._

def foo(a: MyEnum): Seq[Bar.Blue] = a match {
case Red => Seq.empty
case m: Foo.Blue => Seq(m)
}
36 changes: 36 additions & 0 deletions tests/pos/i7219.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class Foo {
object MyEnum {
class Blue
}
export MyEnum._

val a: MyEnum.Blue = ???
a : Blue // ok
}

object Test {
object Types {
type T <: AnyRef
type U = T
type TC[X] <: AnyRef
type UC[X] = TC[(X, X)]
class C
class D[X] extends C
def x1: T = ???
def x2: U = ???
def x3: TC[Int] = ???
def x4: UC[Int] = ???
def x5: C = C()
def x6: D[Int] = D()
}
export Types._
type D1 = Types.D
type U1 = Types.UC

val y1: T = x1
val y2: U = x2
val y3: TC[Int] = x3
val y4: UC[Int] = x4
val y5: C = x5
val y6: D[Int] = x6
}

0 comments on commit e7f0e2a

Please sign in to comment.