aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala77
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala2
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala3
-rw-r--r--test/dotc/tests.scala3
-rw-r--r--tests/neg/typers.scala4
5 files changed, 47 insertions, 42 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 16a151e89..cd46918cf 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -268,50 +268,52 @@ object Denotations {
}
case denot1: SingleDenotation =>
if (denot1 eq denot2) denot1
- else if (denot1.signature matches denot2.signature) {
+ else {
val info1 = denot1.info
val info2 = denot2.info
- val sym1 = denot1.symbol
- val sym2 = denot2.symbol
- val sym2Accessible = sym2.isAccessibleFrom(pre)
-
- /** Does `sym1` come before `sym2` in the linearization of `pre`? */
- def precedes(sym1: Symbol, sym2: Symbol) = {
- def precedesIn(bcs: List[ClassSymbol]): Boolean = bcs match {
- case bc :: bcs1 => (sym1 eq bc) || !(sym2 eq bc) && precedesIn(bcs1)
- case Nil => true
+ if (denot1.signature.matches(denot2.signature) &&
+ denot1.info.matches(denot2.info)) {
+ val sym1 = denot1.symbol
+ val sym2 = denot2.symbol
+ val sym2Accessible = sym2.isAccessibleFrom(pre)
+
+ /** Does `sym1` come before `sym2` in the linearization of `pre`? */
+ def precedes(sym1: Symbol, sym2: Symbol) = {
+ def precedesIn(bcs: List[ClassSymbol]): Boolean = bcs match {
+ case bc :: bcs1 => (sym1 eq bc) || !(sym2 eq bc) && precedesIn(bcs1)
+ case Nil => true
+ }
+ sym1.derivesFrom(sym2) ||
+ !sym2.derivesFrom(sym1) && precedesIn(pre.baseClasses)
}
- sym1.derivesFrom(sym2) ||
- !sym2.derivesFrom(sym1) && precedesIn(pre.baseClasses)
- }
- /** Preference according to partial pre-order (isConcrete, precedes) */
- def preferSym(sym1: Symbol, sym2: Symbol) =
- sym1.eq(sym2) ||
- sym1.isAsConcrete(sym2) &&
- (!sym2.isAsConcrete(sym1) || precedes(sym1.owner, sym2.owner))
+ /** Preference according to partial pre-order (isConcrete, precedes) */
+ def preferSym(sym1: Symbol, sym2: Symbol) =
+ sym1.eq(sym2) ||
+ sym1.isAsConcrete(sym2) &&
+ (!sym2.isAsConcrete(sym1) || precedes(sym1.owner, sym2.owner))
- /** Sym preference provided types also override */
- def prefer(sym1: Symbol, sym2: Symbol, info1: Type, info2: Type) =
- preferSym(sym1, sym2) && info1.overrides(info2)
+ /** Sym preference provided types also override */
+ def prefer(sym1: Symbol, sym2: Symbol, info1: Type, info2: Type) =
+ preferSym(sym1, sym2) && info1.overrides(info2)
- if (sym2Accessible && prefer(sym2, sym1, info2, info1)) denot2
- else {
- val sym1Accessible = sym1.isAccessibleFrom(pre)
- if (sym1Accessible && prefer(sym1, sym2, info1, info2)) denot1
- else if (sym1Accessible && sym2.exists && !sym2Accessible) denot1
- else if (sym2Accessible && sym1.exists && !sym1Accessible) denot2
+ if (sym2Accessible && prefer(sym2, sym1, info2, info1)) denot2
else {
- val sym =
- if (!sym1.exists) sym2
- else if (!sym2.exists) sym1
- else if (preferSym(sym2, sym1)) sym2
- else sym1
- new JointRefDenotation(sym, info1 & info2, denot1.validFor & denot2.validFor)
+ val sym1Accessible = sym1.isAccessibleFrom(pre)
+ if (sym1Accessible && prefer(sym1, sym2, info1, info2)) denot1
+ else if (sym1Accessible && sym2.exists && !sym2Accessible) denot1
+ else if (sym2Accessible && sym1.exists && !sym1Accessible) denot2
+ else {
+ val sym =
+ if (!sym1.exists) sym2
+ else if (!sym2.exists) sym1
+ else if (preferSym(sym2, sym1)) sym2
+ else sym1
+ new JointRefDenotation(sym, info1 & info2, denot1.validFor & denot2.validFor)
+ }
}
- }
+ } else NoDenotation
}
- else NoDenotation
}
if (this eq that) this
@@ -333,7 +335,7 @@ object Denotations {
def | (that: Denotation, pre: Type)(implicit ctx: Context): Denotation = {
def unionDenot(denot1: SingleDenotation, denot2: SingleDenotation): Denotation =
- if (denot1.signature matches denot2.signature) {
+ if (denot1.matches(denot2)) {
val sym1 = denot1.symbol
val sym2 = denot2.symbol
val info1 = denot1.info
@@ -472,6 +474,9 @@ object Denotations {
if (sig matches situated.signature) this else NoDenotation
}
+ def matches(other: SingleDenotation)(implicit ctx: Context): Boolean =
+ signature.matches(other.signature) && info.matches(other.info)
+
// ------ Forming types -------------------------------------------
/** The TypeRef representing this type denotation at its original location. */
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index 8376dd4e9..9092523db 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -312,7 +312,7 @@ trait Checking {
def checkDecl(decl: Symbol): Unit = {
for (other <- seen(decl.name)) {
typr.println(i"conflict? $decl $other")
- if (decl.signature matches other.signature) {
+ if (decl.matches(other)) {
def doubleDefError(decl: Symbol, other: Symbol): Unit = {
def ofType = if (decl.isType) "" else d": ${other.info}"
def explanation =
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 1ae0bec0c..3247592c3 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -63,7 +63,8 @@ trait TypeAssigner {
val parentType = info.instantiatedParents.reduceLeft(ctx.typeComparer.andType(_, _))
def addRefinement(parent: Type, decl: Symbol) = {
val inherited = parentType.findMember(decl.name, info.cls.thisType, Private)
- val inheritedInfo = inherited.atSignature(decl.info .signature).info
+ val inheritedInfo = inherited.atSignature(decl.info.signature).info
+ // @smarter atSignature probably wrong now; we are now missing out on types that refine the result type
if (inheritedInfo.exists && decl.info <:< inheritedInfo && !(inheritedInfo <:< decl.info))
typr.echo(
i"add ref $parent $decl --> ",
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 403a99a19..2b5b86be1 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -104,7 +104,7 @@ class tests extends CompilerTest {
@Test def neg_typedapply() = compileFile(negDir, "typedapply", xerrors = 4)
@Test def neg_typedidents() = compileFile(negDir, "typedIdents", xerrors = 2)
@Test def neg_assignments() = compileFile(negDir, "assignments", xerrors = 3)
- @Test def neg_typers() = compileFile(negDir, "typers", xerrors = 12)(allowDoubleBindings)
+ @Test def neg_typers() = compileFile(negDir, "typers", xerrors = 10)(allowDoubleBindings)
@Test def neg_privates() = compileFile(negDir, "privates", xerrors = 2)
@Test def neg_rootImports = compileFile(negDir, "rootImplicits", xerrors = 2)
@Test def neg_templateParents() = compileFile(negDir, "templateParents", xerrors = 3)
@@ -115,7 +115,6 @@ class tests extends CompilerTest {
@Test def neg_overrides = compileFile(negDir, "overrides", xerrors = 11)
@Test def neg_i39 = compileFile(negDir, "i39", xerrors = 2)
@Test def neg_i50_volatile = compileFile(negDir, "i50-volatile", xerrors = 6)
- @Test def neg_t0273_doubledefs = compileFile(negDir, "t0273", xerrors = 1)
@Test def neg_zoo = compileFile(negDir, "zoo", xerrors = 12)
val negTailcallDir = negDir + "tailcall/"
diff --git a/tests/neg/typers.scala b/tests/neg/typers.scala
index b5bd1fa2c..9fcc63e38 100644
--- a/tests/neg/typers.scala
+++ b/tests/neg/typers.scala
@@ -22,11 +22,11 @@ object typers {
val z: Int
def z(): String // error: double def
- def f(x: Any) = () // error: double def
+ def f(x: Any) = () // OK!
def f(x: AnyRef): AnyRef
def g(x: Object): Unit
- def g[T](x: T): T = x // error: double def
+ def g[T](x: T): T = x // OK!
}