Skip to content

Fix 791 #798

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

Merged
merged 5 commits into from
Sep 18, 2015
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
1 change: 1 addition & 0 deletions src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ class Compiler {
new ClassOf),
List(new PatternMatcher,
new ExplicitOuter,
new ExplicitSelf,
new Splitter),
List(new VCInlineMethods,
new SeqLiterals,
Expand Down
6 changes: 5 additions & 1 deletion src/dotty/tools/dotc/core/TypeErasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,11 @@ object TypeErasure {
case nil =>
bestSoFar
}
loop(tp1.baseClasses, defn.ObjectClass).typeRef
val t = loop(tp1.baseClasses, defn.ObjectClass)
if (t eq defn.AnyValClass)
// while AnyVal is a valid common super class for primitives it does not exist after erasure
defn.ObjectType
else t.typeRef
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2530,7 +2530,7 @@ object Types {
def selfType(implicit ctx: Context): Type = {
if (selfTypeCache == null)
selfTypeCache = {
def fullRef = fullyAppliedRef(cls.typeRef, cls.typeParams)
def fullRef = fullyAppliedRef
val given = givenSelfType
val raw =
if (!given.exists) fullRef
Expand Down Expand Up @@ -2561,6 +2561,9 @@ object Types {
base
}

/** The class type with all type parameters */
def fullyAppliedRef(implicit ctx: Context): Type = fullyAppliedRef(cls.typeRef, cls.typeParams)

def rebase(tp: Type)(implicit ctx: Context): Type =
if ((prefix eq cls.owner.thisType) || !cls.owner.isClass || ctx.erasedTypes) tp
else tp.substThis(cls.owner.asClass, prefix)
Expand Down
4 changes: 3 additions & 1 deletion src/dotty/tools/dotc/transform/Erasure.scala
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,10 @@ object Erasure extends TypeTestsCasts{
assert(false, s"failure creating bridge from ${newDefSym} to ${parentSym}, reason: $reason")
???
}
var excluded = NoBridgeFlags
if (!newDefSym.is(Flags.Protected)) excluded |= Flags.Protected // needed to avoid "weaker access" assertion failures in expandPrivate
val bridge = ctx.newSymbol(currentClass,
parentSym.name, parentSym.flags &~ NoBridgeFlags | Flags.Bridge, parentSym.info, coord = newDefSym.owner.coord).asTerm
parentSym.name, parentSym.flags &~ excluded | Flags.Bridge, parentSym.info, coord = newDefSym.owner.coord).asTerm
bridge.enteredAfter(ctx.phase.prev.asInstanceOf[DenotTransformer]) // this should be safe, as we're executing in context of next phase
ctx.debuglog(s"generating bridge from ${newDefSym} to $bridge")

Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/transform/ExpandPrivate.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class ExpandPrivate extends MiniPhaseTransform with IdentityDenotTransformer { t
}
val fail = sym.allOverriddenSymbols.findSymbol(x => !hasWeakerAccess(x))
if (fail.exists) {
assert(false, i"${sym.showFullName} has weaker access that superclass method ${fail.showFullName}")
assert(false, i"${sym.showFullName}: ${sym.info} has weaker access than superclass method ${fail.showFullName}: ${fail.info}")
}
case _ =>
}
Expand Down
37 changes: 37 additions & 0 deletions src/dotty/tools/dotc/transform/ExplicitSelf.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package dotty.tools.dotc
package transform

import core._
import Contexts.Context
import Types._
import TreeTransforms._
import Decorators._
import ast.Trees._
import Flags._

/** Transform references of the form
*
* C.this.m
*
* where `C` is a class with explicit self type and `C` is not a
* subclass of the owner of `m` to
*
* C.this.asInstanceOf[S].m
*
* where `S` is the self type of `C`.
*/
class ExplicitSelf extends MiniPhaseTransform { thisTransform =>
import ast.tpd._

override def phaseName = "explicitSelf"

override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = tree match {
case Select(thiz: This, name) if name.isTermName =>
val cls = thiz.symbol.asClass
val cinfo = cls.classInfo
if (cinfo.givenSelfType.exists && !cls.derivesFrom(tree.symbol.owner))
cpy.Select(tree)(thiz.asInstance(cinfo.selfType), name)
else tree
case _ => tree
}
}
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1117,7 +1117,7 @@ trait Applications extends Compatibility { self: Typer =>
case cdef: CaseDef => tpd.cpy.CaseDef(cdef)(body = adapt(cdef.body, pt))
case _ => adaptInterpolated(tree, pt, tree)
}
harmonizeWith(trees)(_.tpe, adapt)
if (ctx.isAfterTyper) trees else harmonizeWith(trees)(_.tpe, adapt)
}

/** If all `types` are numeric value types, and they are not all the same type,
Expand Down
11 changes: 11 additions & 0 deletions tests/run/OrType.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class B(val x: Int)
class C(val x: Double)

object Test{
def bar(x: B | C): Int | Double = x.x
def main(args: Array[String]): Unit = {
val b = new B(1)
val c = new C(1)
bar(if (b.hashCode > c.hashCode) b else c)
}
}
1 change: 1 addition & 0 deletions tests/run/i789.check
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
atPhase: 2
20 changes: 20 additions & 0 deletions tests/run/i789.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
trait Periods { self: Context =>

def atPhase(id: Int): Unit = println(s"atPhase: $id")

}

class Phase(val id: Int)

trait Phases { self: Context =>
def atPhase(phase: Phase): Unit = self.atPhase(phase.id)
}

trait Context extends Phases with Periods

object Test extends Context {

def main(args: Array[String]) = atPhase(new Phase(2))

}