Skip to content

Commit 1f37b0c

Browse files
committed
Fix nullary overrides
Fix situations where a ()T method overrides a => T one, and vice versa.
1 parent d8e4442 commit 1f37b0c

21 files changed

+67
-56
lines changed

compiler/src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,8 @@ object Denotations {
408408

409409
/** Sym preference provided types also override */
410410
def prefer(sym1: Symbol, sym2: Symbol, info1: Type, info2: Type) =
411-
preferSym(sym1, sym2) && info1.overrides(info2)
411+
preferSym(sym1, sym2) &&
412+
info1.overrides(info2, sym1.matchNullaryLoosely || sym2.matchNullaryLoosely)
412413

413414
def handleDoubleDef =
414415
if (preferSym(sym1, sym2)) denot1

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,20 @@ object SymDenotations {
763763

764764
def isInlineMethod(implicit ctx: Context): Boolean = is(InlineMethod, butNot = Accessor)
765765

766+
/** ()T and => T types should be treated as equivalent for this symbol.
767+
* Note: For the moment, we treat Scala-2 compiled symbols as loose matching,
768+
* because the Scala library does not always follow the right conventions.
769+
* Examples are: isWhole(), toInt(), toDouble() in BigDecimal, Numeric, RichInt, ScalaNumberProxy.
770+
*/
771+
def matchNullaryLoosely(implicit ctx: Context): Boolean = {
772+
def test(sym: Symbol) =
773+
sym.is(JavaDefined) ||
774+
sym.owner == defn.AnyClass ||
775+
sym == defn.Object_clone ||
776+
sym.owner.is(Scala2x)
777+
test(symbol) || allOverriddenSymbols.exists(test)
778+
}
779+
766780
// ------ access to related symbols ---------------------------------
767781

768782
/* Modules and module classes are represented as follows:
@@ -938,7 +952,6 @@ object SymDenotations {
938952
else if (this.isClass) companionNamed(effectiveName.moduleClassName).sourceModule.moduleClass
939953
else NoSymbol
940954

941-
942955
/** Find companion class symbol with given name, or NoSymbol if none exists.
943956
* Three alternative strategies:
944957
* 1. If owner is a class, look in its members, otherwise

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -769,21 +769,23 @@ object Types {
769769
def relaxed_<:<(that: Type)(implicit ctx: Context) =
770770
(this <:< that) || (this isValueSubType that)
771771

772-
/** Is this type a legal type for a member that overrides another
773-
* member of type `that`? This is the same as `<:<`, except that
774-
* the types `()T`, `=> T` and `T` are seen as overriding
775-
* each other.
772+
/** Is this type a legal type for member `sym1` that overrides another
773+
* member `sym2` of type `that`? This is the same as `<:<`, except that
774+
* if `matchLoosely` evaluates to true the types `=> T` and `()T` are seen
775+
* as overriding each other.
776776
*/
777-
final def overrides(that: Type)(implicit ctx: Context) = {
778-
def result(tp: Type): Type = tp match {
779-
case ExprType(_) | MethodType(Nil) => tp.resultType
777+
final def overrides(that: Type, matchLoosely: => Boolean)(implicit ctx: Context): Boolean = {
778+
def widenNullary(tp: Type) = tp match {
779+
case tp @ MethodType(Nil) => tp.resultType
780780
case _ => tp
781781
}
782-
(this frozen_<:< that) || {
783-
val rthat = result(that)
784-
val rthis = result(this)
785-
(rthat.ne(that) || rthis.ne(this)) && (rthis frozen_<:< rthat)
786-
}
782+
((this.widenExpr frozen_<:< that.widenExpr) ||
783+
matchLoosely && {
784+
val this1 = widenNullary(this)
785+
val that1 = widenNullary(that)
786+
((this1 `ne` this) || (that1 `ne` that)) && this1.overrides(this1, matchLoosely = false)
787+
}
788+
)
787789
}
788790

789791
/** Is this type close enough to that type so that members

compiler/src/dotty/tools/dotc/sbt/ThunkHolder.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ private object SafeLazy {
114114
eval = null // clear the reference, ensuring the only memory we hold onto is the result
115115
t
116116
}
117-
def get: T = _t
117+
def get(): T = _t
118118
}
119119

120120
private[this] final class Strict[T <: AnyRef](val get: T) extends xsbti.api.Lazy[T] with java.io.Serializable

compiler/src/dotty/tools/dotc/typer/RefChecks.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,10 @@ object RefChecks {
257257
}
258258
else
259259
member.name.is(DefaultGetterName) || // default getters are not checked for compatibility
260-
memberTp.overrides(otherTp)
260+
memberTp.overrides(otherTp,
261+
member.matchNullaryLoosely || other.matchNullaryLoosely ||
262+
ctx.testScala2Mode(overrideErrorMsg("no longer has compatible type"),
263+
(if (member.owner == clazz) member else clazz).pos))
261264
catch {
262265
case ex: MissingType =>
263266
// can happen when called with upwardsSelf as qualifier of memberTp and otherTp,

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,16 +2045,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
20452045

20462046
/** Is reference to this symbol `f` automatically expanded to `f()`? */
20472047
def isAutoApplied(sym: Symbol): Boolean = {
2048-
def test(sym1: Symbol) =
2049-
sym1.is(JavaDefined) ||
2050-
sym1.owner == defn.AnyClass ||
2051-
sym1 == defn.Object_clone
20522048
sym.isConstructor ||
2053-
test(sym) ||
2054-
sym.allOverriddenSymbols.exists(test) ||
2055-
sym.owner.is(Scala2x) || // need to exclude Scala-2 compiled symbols for now, since the
2056-
// Scala library does not always follow the right conventions.
2057-
// Examples are: isWhole(), toInt(), toDouble() in BigDecimal, Numeric, RichInt, ScalaNumberProxy.
2049+
sym.matchNullaryLoosely ||
20582050
ctx.testScala2Mode(em"${sym.showLocated} requires () argument", tree.pos,
20592051
patch(tree.pos.endPos, "()"))
20602052
}

compiler/src/dotty/tools/dotc/util/Set.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ abstract class Set[T >: Null] {
2323

2424
def toList = iterator.toList
2525

26-
def clear: Unit
26+
def clear(): Unit
2727
}

compiler/src/dotty/tools/io/AbstractFile.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ abstract class AbstractFile extends Iterable[AbstractFile] {
186186
}
187187

188188
/** Returns all abstract subfiles of this abstract directory. */
189-
def iterator: Iterator[AbstractFile]
189+
def iterator(): Iterator[AbstractFile]
190190

191191
/** Returns the abstract file in this abstract directory with the specified
192192
* name. If there is no such file, returns `null`. The argument

compiler/src/dotty/tools/io/PlainFile.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ package io
99
/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */
1010
class PlainDirectory(givenPath: Directory) extends PlainFile(givenPath) {
1111
override def isDirectory = true
12-
override def iterator = givenPath.list filter (_.exists) map (x => new PlainFile(x))
12+
override def iterator() = givenPath.list filter (_.exists) map (x => new PlainFile(x))
1313
override def delete(): Unit = givenPath.deleteRecursively()
1414
}
1515

compiler/src/dotty/tools/io/VirtualDirectory.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ extends AbstractFile {
4747

4848
// the toList is so that the directory may continue to be
4949
// modified while its elements are iterated
50-
def iterator = files.values.toList.iterator
50+
def iterator() = files.values.toList.iterator
5151

5252
override def lookupName(name: String, directory: Boolean): AbstractFile =
5353
(files get name filter (_.isDirectory == directory)).orNull

0 commit comments

Comments
 (0)