diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index 1c346ac7af20..c1a46f2cc83d 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -908,8 +908,9 @@ trait Applications extends Compatibility { * part. Return an optional value to indicate success. */ def tryWithImplicitOnQualifier(fun1: Tree, proto: FunProto)(using Context): Option[Tree] = - if (ctx.mode.is(Mode.SynthesizeExtMethodReceiver)) + if ctx.mode.is(Mode.SynthesizeExtMethodReceiver) || proto.hasErrorArg then // Suppress insertion of apply or implicit conversion on extension method receiver + // or if argument is erroneous by itself. None else tryInsertImplicitOnQualifier(fun1, proto, ctx.typerState.ownedVars) flatMap { fun2 => diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala index fcedd8a0cd56..440068e70915 100644 --- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -8,7 +8,7 @@ import Contexts._, Types._, Denotations._, Names._, StdNames._, NameOps._, Symbo import NameKinds.DepParamName import Trees._ import Constants._ -import util.{Stats, SimpleIdentityMap} +import util.{Stats, SimpleIdentityMap, SimpleIdentitySet} import Decorators._ import Uniques._ import config.Printers.typr @@ -282,6 +282,9 @@ object ProtoTypes { /** A map in which typed arguments can be stored to be later integrated in `typedArgs`. */ var typedArg: SimpleIdentityMap[untpd.Tree, Tree] = SimpleIdentityMap.empty + /** The argument that produced errors during typing */ + var errorArgs: SimpleIdentitySet[untpd.Tree] = SimpleIdentitySet.empty + /** The tupled or untupled version of this prototype, if it has been computed */ var tupledDual: Type = NoType @@ -341,6 +344,9 @@ object ProtoTypes { case _ => false } + /** Did an argument produce an error when typing? */ + def hasErrorArg = !state.errorArgs.isEmpty + private def cacheTypedArg(arg: untpd.Tree, typerFn: untpd.Tree => Tree, force: Boolean)(using Context): Tree = { var targ = state.typedArg(arg) if (targ == null) @@ -357,8 +363,11 @@ object ProtoTypes { targ = arg.withType(WildcardType) case _ => targ = typerFn(arg) - if (!ctx.reporter.hasUnreportedErrors) + if ctx.reporter.hasUnreportedErrors then + state.errorArgs += arg + else state.typedArg = state.typedArg.updated(arg, targ) + state.errorArgs -= arg } targ } diff --git a/tests/neg-custom-args/deprecation/t3235-minimal-v2.check b/tests/neg-custom-args/deprecation/t3235-minimal-v2.check new file mode 100644 index 000000000000..87a85f661f58 --- /dev/null +++ b/tests/neg-custom-args/deprecation/t3235-minimal-v2.check @@ -0,0 +1,8 @@ +-- Error: tests/neg-custom-args/deprecation/t3235-minimal-v2.scala:3:16 ------------------------------------------------ +3 | assert(math.round(123456789) == 123456789) // error + | ^^^^^^^^^^ + |method round in package scala.math is deprecated since 2.11.0: This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value? +-- Error: tests/neg-custom-args/deprecation/t3235-minimal-v2.scala:4:16 ------------------------------------------------ +4 | assert(math.round(1234567890123456789L) == 1234567890123456789L) // error + | ^^^^^^^^^^ + |method round in package scala.math is deprecated since 2.11.0: This is an integer type; there is no reason to round it. Perhaps you meant to call this with a floating-point value? diff --git a/tests/neg-custom-args/deprecation/t3235-minimal-v2.scala b/tests/neg-custom-args/deprecation/t3235-minimal-v2.scala new file mode 100644 index 000000000000..c56062076ee9 --- /dev/null +++ b/tests/neg-custom-args/deprecation/t3235-minimal-v2.scala @@ -0,0 +1,6 @@ +object Test { + def main(args: Array[String]): Unit = { + assert(math.round(123456789) == 123456789) // error + assert(math.round(1234567890123456789L) == 1234567890123456789L) // error + } +} diff --git a/tests/neg-custom-args/deprecation/t3235-minimal-v3.scala b/tests/neg-custom-args/deprecation/t3235-minimal-v3.scala new file mode 100644 index 000000000000..6af327811b5f --- /dev/null +++ b/tests/neg-custom-args/deprecation/t3235-minimal-v3.scala @@ -0,0 +1,5 @@ +object Test { + def main(args: Array[String]): Unit = { + assert(1234567890123456789L.round == 1234567890123456789L) // error + } +} diff --git a/tests/neg-custom-args/deprecation/t3235-minimal.check b/tests/neg-custom-args/deprecation/t3235-minimal.check new file mode 100644 index 000000000000..2a4dc60b898c --- /dev/null +++ b/tests/neg-custom-args/deprecation/t3235-minimal.check @@ -0,0 +1,4 @@ +-- Error: tests/neg-custom-args/deprecation/t3235-minimal.scala:3:21 --------------------------------------------------- +3 | assert(123456789.round == 123456789) // error + | ^^^^^^^^^^^^^^^ + |method round in class RichInt is deprecated since 2.11.0: this is an integer type; there is no reason to round it. Perhaps you meant to call this on a floating-point value? diff --git a/tests/neg-custom-args/deprecation/t3235-minimal.scala b/tests/neg-custom-args/deprecation/t3235-minimal.scala index 3aef0eea2dae..c09c56a329ca 100644 --- a/tests/neg-custom-args/deprecation/t3235-minimal.scala +++ b/tests/neg-custom-args/deprecation/t3235-minimal.scala @@ -1,8 +1,5 @@ object Test { def main(args: Array[String]): Unit = { assert(123456789.round == 123456789) // error - assert(math.round(123456789) == 123456789) // error - assert(1234567890123456789L.round == 1234567890123456789L) // error - assert(math.round(1234567890123456789L) == 1234567890123456789L) // error } } diff --git a/tests/neg/i12941.scala b/tests/neg/i12941.scala new file mode 100644 index 000000000000..0948cf7ce545 --- /dev/null +++ b/tests/neg/i12941.scala @@ -0,0 +1,28 @@ +object A: + def myFun(op: String ?=> Unit) = () + +@main def func: Unit = + A.myFun { + val res: String = summon[String] + println(ress) // error + } + +class I: + def runSth: Int = 1 + +abstract class A: + def myFun(op: I ?=> Unit) = + op(using I()) + 1 + +class B extends A + +def assertEquals(x: String, y: Int, z: Int): Unit = () + +@main def hello: Unit = + + B().myFun { + val res = summon[I].runSth + assertEquals("", 1, res, "asd") // error + println("Hello!") + } \ No newline at end of file diff --git a/tests/neg/i8861.scala b/tests/neg/i8861.scala index 744b49b0107b..87f1884f6155 100644 --- a/tests/neg/i8861.scala +++ b/tests/neg/i8861.scala @@ -20,7 +20,7 @@ object Test { ) def minimalFail[M](c: Container { type A = M }): M = c.visit( int = vi => vi.i : vi.A, - str = vs => vs.t : vs.A // error // error + str = vs => vs.t : vs.A // error ) def main(args: Array[String]): Unit = { diff --git a/tests/neg/i903.check b/tests/neg/i903.check new file mode 100644 index 000000000000..7e3b188dff85 --- /dev/null +++ b/tests/neg/i903.check @@ -0,0 +1,7 @@ +-- [E007] Type Mismatch Error: tests/neg/i903.scala:3:16 --------------------------------------------------------------- +3 | "".contains("", (_: Int)) // error + | ^^^^^^^^^^^^ + | Found: (String, Int) + | Required: CharSequence + +longer explanation available when compiling with `-explain` diff --git a/tests/neg/i903.scala b/tests/neg/i903.scala new file mode 100644 index 000000000000..03503ead463b --- /dev/null +++ b/tests/neg/i903.scala @@ -0,0 +1,4 @@ +object Test { + def test2 = + "".contains("", (_: Int)) // error +} diff --git a/tests/neg/zipped.check b/tests/neg/zipped.check new file mode 100644 index 000000000000..582d121cd9c3 --- /dev/null +++ b/tests/neg/zipped.check @@ -0,0 +1,11 @@ +-- [E007] Type Mismatch Error: tests/neg/zipped.scala:6:10 ------------------------------------------------------------- +6 | .map( (x: (Int, Int, Int)) => x match { case (x, y, z) => x + y + z }) // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Found: ((Int, Int, Int)) => Int + | Required: (Int, Int, Int) => Int + +longer explanation available when compiling with `-explain` +-- [E086] Syntax Error: tests/neg/zipped.scala:9:12 -------------------------------------------------------------------- +9 | .map( x => x match { case (x, y, z) => x + y + z }) // error + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | Wrong number of parameters, expected: 3 diff --git a/tests/neg/zipped.scala b/tests/neg/zipped.scala new file mode 100644 index 000000000000..a3b3d3ddac05 --- /dev/null +++ b/tests/neg/zipped.scala @@ -0,0 +1,10 @@ +object Test { + val xs: List[Int] = ??? + + // Does not work anynore since auto(un)tupling does not work after conversions + xs.lazyZip(xs).lazyZip(xs) + .map( (x: (Int, Int, Int)) => x match { case (x, y, z) => x + y + z }) // error + + xs.lazyZip(xs).lazyZip(xs) + .map( x => x match { case (x, y, z) => x + y + z }) // error +} \ No newline at end of file diff --git a/tests/pos/i903.scala b/tests/pos/i903.scala index 5afb6e53010c..dec98dbf2705 100644 --- a/tests/pos/i903.scala +++ b/tests/pos/i903.scala @@ -15,12 +15,4 @@ object Test { // f.apply(0) // ^ } - - def test2 = { - val f = "".contains("", (_: Int)) // dotc: - f.apply(0) - // sandbox/eta.scala:18: error: apply is not a member of Boolean(f) - // f.apply(0) - // ^ - } } diff --git a/tests/pos/zipped.scala b/tests/pos/zipped.scala index 2453b880cbc3..0d394bb953a5 100644 --- a/tests/pos/zipped.scala +++ b/tests/pos/zipped.scala @@ -23,12 +23,12 @@ object Test { .map( (x: Int, y: Int, z: Int) => x + y + z ) // OK // 4. The single parameter map works through an inserted conversion - xs.lazyZip(xs).lazyZip(xs) - .map( (x: (Int, Int, Int)) => x match { case (x, y, z) => x + y + z }) // now also OK + //xs.lazyZip(xs).lazyZip(xs) + // .map( (x: (Int, Int, Int)) => x match { case (x, y, z) => x + y + z }) // now also OK // 5. If we leave out the parameter type, it now works as well. - xs.lazyZip(xs).lazyZip(xs) - .map( x => x match { case (x, y, z) => x + y + z }) // now also OK + //xs.lazyZip(xs).lazyZip(xs) + // .map( x => x match { case (x, y, z) => x + y + z }) // now also OK // This means that the following works in Dotty 3.0 as well as 3.x for ((x, y, z) <- xs.lazyZip(xs).lazyZip(xs)) yield x + y + z