Skip to content

Commit

Permalink
Test overloading changes and reported warning messages
Browse files Browse the repository at this point in the history
Note that in tests/neg/multiparamlist-overload-3.7 Test2 we now
get an error in both Parts as intended. But they are, however, different ones:
Part1 is a TypeMismatch Error, whereas Part2 is a NoMatchingOverload Error.

This is due to the fact that `resolveOverloaded` will first
find the candidate alternatives by considering only the 1st parameter list
and commit early if there is a single one, e.g. Test2.Part1.
If not, we recursively continue with the found alternatives and
recompute the candidate alternatives based on the 2nd parameter list,
which may rule out all of them, and hence lead to a different message.
  • Loading branch information
EugeneFlesselle committed Aug 20, 2024
1 parent 2e0cff0 commit f40c609
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 2 deletions.
36 changes: 36 additions & 0 deletions tests/neg/i10901.check
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
-- [E008] Not Found Error: tests/neg/i10901.scala:45:38 ----------------------------------------------------------------
45 | val pos1: Point2D[Int,Double] = x º y // error
| ^^^
| value º is not a member of object BugExp4Point2D.IntT.
| An extension method was tried, but could not be fully constructed:
|
| º(x)
|
| failed with:
|
| Ambiguous overload. The overloaded alternatives of method º in object dsl with types
| [T1, T2]
| (x: BugExp4Point2D.ColumnType[T1])
| (y: BugExp4Point2D.ColumnType[T2])
| (using evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| [T1, T2]
| (x: T1)
| (y: BugExp4Point2D.ColumnType[T2])
| (using evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| both match arguments ((x : BugExp4Point2D.IntT.type))((y : BugExp4Point2D.DoubleT.type))
-- [E008] Not Found Error: tests/neg/i10901.scala:48:38 ----------------------------------------------------------------
48 | val pos4: Point2D[Int,Double] = x º 201.1 // error
| ^^^
|value º is not a member of object BugExp4Point2D.IntT.
|An extension method was tried, but could not be fully constructed:
|
| º(x)
|
| failed with:
|
| Ambiguous overload. The overloaded alternatives of method º in object dsl with types
| [T1, T2]
| (x: BugExp4Point2D.ColumnType[T1])
| (y: T2)(using evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| [T1, T2](x: T1)(y: T2)(using evidence$1: Numeric[T1], evidence$2: Numeric[T2]): BugExp4Point2D.Point2D[T1, T2]
| both match arguments ((x : BugExp4Point2D.IntT.type))((201.1d : Double))
-- [E008] Not Found Error: tests/neg/i10901.scala:62:16 ----------------------------------------------------------------
62 | val y = "abc".foo // error
| ^^^^^^^^^
Expand Down
4 changes: 2 additions & 2 deletions tests/neg/i10901.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ object BugExp4Point2D {
val x = IntT
val y = DoubleT

val pos1: Point2D[Int,Double] = x º y // ok
val pos1: Point2D[Int,Double] = x º y // error
val pos2: Point2D[Int,Double] = 100 º 200.1 // ok
val pos3: Point2D[Int,Double] = 101 º y // ok
val pos4: Point2D[Int,Double] = x º 201.1 // ok
val pos4: Point2D[Int,Double] = x º 201.1 // error

}
}
Expand Down
27 changes: 27 additions & 0 deletions tests/neg/multiparamlist-overload-3.6.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-- [E007] Type Mismatch Error: tests/neg/multiparamlist-overload-3.6.scala:33:21 ---------------------------------------
33 | val r = f(new B)(new A) // error since resolves to R2 in 3.6 (and 3.7) as expected
| ^^^^^
| Found: A
| Required: B
|
| longer explanation available when compiling with `-explain`
-- Warning: tests/neg/multiparamlist-overload-3.6.scala:20:10 ----------------------------------------------------------
20 | val r = f(new B)(new C) // resolves to R1 in 3.6
| ^
| Overloading resolution for arguments (B)(C) between alternatives
| (x: B)(y: B): R3
| (x: B)(y: A): R2
| (x: A)(y: C): R1
| will change.
| Current choice : (x: A)(y: C): R1
| New choice from Scala 3.7: (x: B)(y: B): R3
-- Warning: tests/neg/multiparamlist-overload-3.6.scala:40:12 ----------------------------------------------------------
40 | val r = f(new B)(new A) // resolves to R1 in 3.6
| ^
| Overloading resolution for arguments (B)(A) between alternatives
| (x: B)(y: C): R3
| (x: B)(y: B): R2
| (x: A)(y: A): R1
| will change.
| Current choice : (x: A)(y: A): R1
| New choice from Scala 3.7: none
43 changes: 43 additions & 0 deletions tests/neg/multiparamlist-overload-3.6.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import scala.language.`3.6`

class A
class B extends A
class C extends B

class R1
class R2
class R3

// The alternatives are ordered from most genereal to most specific in each test,
// with respect to a lexicographic ordering by parameter list.


object Test1:
def f(x: A)(y: C) = new R1
def f(x: B)(y: A) = new R2
def f(x: B)(y: B) = new R3

val r = f(new B)(new C) // resolves to R1 in 3.6
val _: R1 = r
end Test1


object Test2:
// R1 is the only applicable alternative in both parts
// but it is only resolved to in Part2 by adding (an unapplicable) R3

object Part1:
def f(x: A)(y: A) = new R1
def f(x: B)(y: B) = new R2

val r = f(new B)(new A) // error since resolves to R2 in 3.6 (and 3.7) as expected

object Part2:
def f(x: A)(y: A) = new R1
def f(x: B)(y: B) = new R2
def f(x: B)(y: C) = new R3

val r = f(new B)(new A) // resolves to R1 in 3.6
val _: R1 = r

end Test2
25 changes: 25 additions & 0 deletions tests/neg/multiparamlist-overload-3.7.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
-- [E007] Type Mismatch Error: tests/neg/multiparamlist-overload-3.7.scala:33:21 ---------------------------------------
33 | val r = f(new B)(new A) // error since resolves to R2 in 3.7 (and 3.6), as expected
| ^^^^^
| Found: A
| Required: B
|
| longer explanation available when compiling with `-explain`
-- [E134] Type Error: tests/neg/multiparamlist-overload-3.7.scala:40:12 ------------------------------------------------
40 | val r = f(new B)(new A) // error since resolves to R2 in 3.7, as in Part1
| ^
| None of the overloaded alternatives of method f in object Part2 with types
| (x: B)(y: C): R3
| (x: B)(y: B): R2
| (x: A)(y: A): R1
| match arguments (B)(A)
-- Warning: tests/neg/multiparamlist-overload-3.7.scala:20:10 ----------------------------------------------------------
20 | val r = f(new B)(new C) // resolves to R3 in 3.7
| ^
| Overloading resolution for arguments (B)(C) between alternatives
| (x: B)(y: B): R3
| (x: B)(y: A): R2
| (x: A)(y: C): R1
| has changed.
| Previous choice : (x: A)(y: C): R1
| New choice from Scala 3.7: (x: B)(y: B): R3
42 changes: 42 additions & 0 deletions tests/neg/multiparamlist-overload-3.7.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import scala.language.`3.7-migration`

class A
class B extends A
class C extends B

class R1
class R2
class R3

// The alternatives are ordered from most genereal to most specific in each test,
// with respect to a lexicographic ordering by parameter list.


object Test1:
def f(x: A)(y: C) = new R1
def f(x: B)(y: A) = new R2
def f(x: B)(y: B) = new R3

val r = f(new B)(new C) // resolves to R3 in 3.7
val _: R3 = r
end Test1


object Test2:
// R1 is the only applicable alternative in both parts
// but it is never resolved to since R2 has a more specific 1st parameter list

object Part1:
def f(x: A)(y: A) = new R1
def f(x: B)(y: B) = new R2

val r = f(new B)(new A) // error since resolves to R2 in 3.7 (and 3.6), as expected

object Part2:
def f(x: A)(y: A) = new R1
def f(x: B)(y: B) = new R2
def f(x: B)(y: C) = new R3

val r = f(new B)(new A) // error since resolves to R2 in 3.7, as in Part1

end Test2
22 changes: 22 additions & 0 deletions tests/neg/scalatest-overload-3.7.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import scala.language.`3.7`

class TestBody1
class TestBody2

class StartWithWord
class EndWithWord

class Matchers:
extension (leftSideString: String)
def should(body: TestBody1): Unit = ()
def should(body: TestBody2): Unit = ()

extension [T](leftSideValue: T)
def should(word: StartWithWord)(using T <:< String): Unit = ()
def should(word: EndWithWord)(using T <:< String): Unit = ()

def endWith(rightSideString: String): EndWithWord = new EndWithWord

class Test extends Matchers:
def test(): Unit =
"hello world" should endWith ("world") // error
22 changes: 22 additions & 0 deletions tests/pos/scalatest-overload-3.6.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import scala.language.`3.6`

class TestBody1
class TestBody2

class StartWithWord
class EndWithWord

class Matchers:
extension (leftSideString: String)
def should(body: TestBody1): Unit = ()
def should(body: TestBody2): Unit = ()

extension [T](leftSideValue: T)
def should(word: StartWithWord)(using T <:< String): Unit = ()
def should(word: EndWithWord)(using T <:< String): Unit = ()

def endWith(rightSideString: String): EndWithWord = new EndWithWord

class Test extends Matchers:
def test(): Unit =
"hello world" should endWith ("world") // ok, error in 3.7

0 comments on commit f40c609

Please sign in to comment.