From bd6ac1cd711efff5842c695b4052b827add0d5d8 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Thu, 19 Oct 2023 14:47:57 +0100 Subject: [PATCH] Tweak convertible implicits fix Rather than widen in viewExists, widen earlier, past type lambda parameters. This allows `foo2` in `i16453b2` from being listed as a possible implicit, as appropriate. [Cherry-picked a17552564ab467b25a90e6b6405683d4b03ddec7] --- compiler/src/dotty/tools/dotc/typer/Implicits.scala | 4 ++-- tests/neg/i16453b1.check | 8 ++++++++ tests/neg/i16453b1.scala | 12 ++++++++++++ tests/neg/i16453b2.check | 8 ++++++++ tests/neg/i16453b2.scala | 12 ++++++++++++ 5 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 tests/neg/i16453b1.check create mode 100644 tests/neg/i16453b1.scala create mode 100644 tests/neg/i16453b2.check create mode 100644 tests/neg/i16453b2.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala index 3872d0dd79d0..5ecddd6f4af0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala +++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala @@ -826,7 +826,7 @@ trait Implicits: && !to.isError && !ctx.isAfterTyper && ctx.mode.is(Mode.ImplicitsEnabled) - && from.widen.isValueType + && from.isValueType && ( from.isValueSubType(to) || inferView(dummyTreeOfType(from), to) (using ctx.fresh.addMode(Mode.ImplicitExploration).setExploreTyperState()).isSuccess @@ -958,7 +958,7 @@ trait Implicits: .filter { imp => !isImplicitDefConversion(imp.underlying) && imp.symbol != defn.Predef_conforms - && viewExists(imp, fail.expectedType) + && viewExists(imp.underlying.resultType, fail.expectedType) } else Nil diff --git a/tests/neg/i16453b1.check b/tests/neg/i16453b1.check new file mode 100644 index 000000000000..07f23c95d9ad --- /dev/null +++ b/tests/neg/i16453b1.check @@ -0,0 +1,8 @@ +-- [E172] Type Error: tests/neg/i16453b1.scala:11:19 ------------------------------------------------------------------- +11 | val ko = get[Int] // error + | ^ + |No given instance of type Ctx => Option[Int] was found for parameter fn of method get + | + |Note: implicit conversions are not automatically applied to arguments of using clauses. You will have to pass the argument explicitly. + |The following implicits in scope can be implicitly converted to Ctx => Option[Int]: + |- final lazy given val foo: Ctx => Int diff --git a/tests/neg/i16453b1.scala b/tests/neg/i16453b1.scala new file mode 100644 index 000000000000..4a99321a9421 --- /dev/null +++ b/tests/neg/i16453b1.scala @@ -0,0 +1,12 @@ +import scala.language.implicitConversions + +sealed trait Ctx +given ct[T]: Conversion[Ctx => T, Ctx => Option[T]] = fn => fn.andThen(Option.apply) + +def get[T](using fn: Ctx => Option[T]): Option[T] = ??? + +def Test = { + given foo: (Ctx => Int) = _ => 42 + val ok = get[Int](using summon[Ctx => Int]) + val ko = get[Int] // error +} diff --git a/tests/neg/i16453b2.check b/tests/neg/i16453b2.check new file mode 100644 index 000000000000..fc0a1fa37b82 --- /dev/null +++ b/tests/neg/i16453b2.check @@ -0,0 +1,8 @@ +-- [E172] Type Error: tests/neg/i16453b2.scala:11:19 ------------------------------------------------------------------- +11 | val ko = get[Int] // error + | ^ + |No given instance of type Ctx => Option[Int] was found for parameter fn of method get + | + |Note: implicit conversions are not automatically applied to arguments of using clauses. You will have to pass the argument explicitly. + |The following implicits in scope can be implicitly converted to Ctx => Option[Int]: + |- final given def foo2[A]: Ctx => Int diff --git a/tests/neg/i16453b2.scala b/tests/neg/i16453b2.scala new file mode 100644 index 000000000000..6cafeb54b540 --- /dev/null +++ b/tests/neg/i16453b2.scala @@ -0,0 +1,12 @@ +import scala.language.implicitConversions + +sealed trait Ctx +given ct[T]: Conversion[Ctx => T, Ctx => Option[T]] = fn => fn.andThen(Option.apply) + +def get[T](using fn: Ctx => Option[T]): Option[T] = ??? + +def Test = { + given foo2[A]: (Ctx => Int) = _ => 42 + val ok = get[Int](using summon[Ctx => Int]) + val ko = get[Int] // error +}