Skip to content

New bridge implementation #2342

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 7 commits into from
May 4, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
41 changes: 41 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/ElimErasedValueType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import TypeErasure.ErasedValueType, ValueClasses._
/** This phase erases ErasedValueType to their underlying type.
* It also removes the synthetic cast methods u2evt$ and evt2u$ which are
* no longer needed afterwards.
* Finally, it checks that we don't introduce "double definitions" of pairs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why put this in ElimErasedValueType ? Shouldn't it be a separate mini-phase?

* of methods that now have the same signature but were not considered matching
* before erasure.
*/
class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer {

Expand Down Expand Up @@ -67,6 +70,44 @@ class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer {
transformTypeOfTree(t)
}

/** Check that we don't have pairs of methods that override each other after
* this phase, yet do not have matching types before erasure.
* The before erasure test is performed after phase elimRepeated, so we
* do not need to special case pairs of `T* / Seq[T]` parameters.
*/
private def checkNoClashes(root: Symbol)(implicit ctx: Context) = {
val opc = new OverridingPairs.Cursor(root) {
override def exclude(sym: Symbol) =
!sym.is(Method) || sym.is(Bridge) || super.exclude(sym)
override def matches(sym1: Symbol, sym2: Symbol) =
sym1.signature == sym2.signature
}
def checkNoConflict(sym1: Symbol, sym2: Symbol, info: Type)(implicit ctx: Context): Unit = {
val site = root.thisType
val info1 = site.memberInfo(sym1)
val info2 = site.memberInfo(sym2)
if (!info1.matchesLoosely(info2))
ctx.error(
em"""double definition:
|$sym1: $info1 in ${sym1.owner} ${sym1.flags} and
|$sym2: $info2 in ${sym2.owner} ${sym2.flags}
|have same type after erasure: $info""",
root.pos)
}
val earlyCtx = ctx.withPhase(ctx.elimRepeatedPhase.next)
while (opc.hasNext) {
val sym1 = opc.overriding
val sym2 = opc.overridden
checkNoConflict(sym1, sym2, sym1.info)(earlyCtx)
opc.next()
}
}

override def transformTypeDef(tree: TypeDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
checkNoClashes(tree.symbol)
tree
}

override def transformInlined(tree: Inlined)(implicit ctx: Context, info: TransformerInfo): Tree =
transformTypeOfTree(tree)

Expand Down
3 changes: 3 additions & 0 deletions compiler/test/dotc/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ class tests extends CompilerTest {
@Test def neg_i1050 = compileFile(negCustomArgs, "i1050", List("-strict"))
@Test def neg_i1240 = compileFile(negCustomArgs, "i1240")(allowDoubleBindings)
@Test def neg_i2002 = compileFile(negCustomArgs, "i2002")(allowDoubleBindings)
@Test def neg_valueclasses_doubledefs = compileFile(negCustomArgs, "valueclasses-doubledefs")(allowDoubleBindings)
@Test def neg_valueclasses_doubledefs2 = compileFile(negCustomArgs, "valueclasses-doubledefs2")(allowDoubleBindings)
@Test def neg_valueclasses_pavlov = compileFile(negCustomArgs, "valueclasses-pavlov")(allowDoubleBindings)

val negTailcallDir = negDir + "tailcall/"
@Test def neg_tailcall_t1672b = compileFile(negTailcallDir, "t1672b")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ class Meter(val x: Double) extends AnyVal

class Foo {
def apply(x: Double) = x.toString
def apply(x: Meter) = x.toString
def apply(x: Meter) = x.toString // error: double def
}

10 changes: 10 additions & 0 deletions tests/neg/customArgs/valueclasses-doubledefs2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class Meter(val x: Double) extends AnyVal

trait A {
def apply(x: Double) = x.toString
}
trait B {
def apply(x: Meter) = x.toString
}

object Test extends A with B // error: double def
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ trait Foo[T <: AnyVal] extends Any {

class Box1(val value: String) extends AnyVal with Foo[Box2] {
def foo(x: String) = "foo(String): ok"
def foo(x: Box2) = "foo(Box2): ok"
def foo(x: Box2) = "foo(Box2): ok" // error: double def
}

class Box2(val value: String) extends AnyVal
Expand All @@ -17,7 +17,7 @@ object test2a {
val b1 = new Box1(null)
val b2 = new Box2(null)
val f: Foo[Box2] = b1
println(f.foo(""))
println(f.foo(b2))
println(f.foo("")) // error: cannot merge
println(f.foo(b2)) // error: cannot merge
}
}
7 changes: 0 additions & 7 deletions tests/untried/neg/valueclasses-doubledefs.check

This file was deleted.

7 changes: 0 additions & 7 deletions tests/untried/neg/valueclasses-pavlov.check

This file was deleted.