Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #7219: export forwarder should use TypeAlias for parameterless class #7223

Merged
merged 3 commits into from
Sep 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
}