Skip to content

Commit 98bf4b2

Browse files
committed
Fix inversion of if, check for errors properly
1 parent ebb616c commit 98bf4b2

File tree

4 files changed

+86
-35
lines changed

4 files changed

+86
-35
lines changed

compiler/src/dotty/tools/dotc/reporting/messages.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2750,7 +2750,7 @@ class MissingImplicitArgument(
27502750
Option.when(ignoredConvertibleImplicits.nonEmpty)(
27512751
i"\n\nNote: implicit conversions are not automatically applied to arguments of using clauses. " +
27522752
i"You will have to pass the argument explicitly.\n" +
2753-
i"The following implicits in scope can be converted to ${pt.show}:" +
2753+
i"The following implicits in scope can be implicitly converted to ${pt.show}:" +
27542754
ignoredConvertibleImplicits.map { imp => s"\n- ${imp.symbol.showDcl}"}.mkString
27552755
)
27562756
super.msgPostscript

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

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -928,44 +928,46 @@ trait Implicits:
928928
else currImplicits.refs ::: allImplicits(currImplicits.outerImplicits)
929929

930930
/** Ensure an implicit is not a Scala 2-style implicit conversion, based on its type */
931-
def notImplicitConv(typ: Type): Boolean = typ match {
932-
case PolyType(_, resType) => notImplicitConv(resType)
933-
case mt: MethodType => mt.isImplicitMethod || mt.isContextualMethod
934-
case _ => true
935-
}
936-
937931
def isScala2Conv(typ: Type): Boolean = typ match {
938932
case PolyType(_, resType) => isScala2Conv(resType)
939-
case mt: MethodType =>
940-
(!mt.resultType.isImplicitMethod && !mt.resultType.isContextualMethod)
941-
|| isScala2Conv(mt.resultType)
933+
case mt: MethodType => !mt.isImplicitMethod && !mt.isContextualMethod
942934
case _ => false
943935
}
944936

945-
def ignoredConversions = arg.tpe match
937+
def hasErrors(tree: Tree): Boolean =
938+
if tree.tpe.isInstanceOf[ErrorType] then true
939+
else
940+
tree match {
941+
case Apply(_, List(arg)) => arg.tpe.isInstanceOf[ErrorType]
942+
case _ => false
943+
}
944+
945+
def ignoredConvertibleImplicits = arg.tpe match
946946
case fail: SearchFailureType =>
947-
// Get every implicit in scope and find Conversions for each
948947
if (fail.expectedType eq pt) || isFullyDefined(fail.expectedType, ForceDegree.none) then
948+
// Get every implicit in scope and try to convert each
949949
allImplicits(ctx.implicits)
950+
.distinctBy(_.underlyingRef.denot)
951+
.view
950952
.map(_.underlyingRef)
951953
.filter { imp =>
952-
if notImplicitConv(imp.underlying) then false
954+
if isScala2Conv(imp.underlying) || imp.symbol == defn.Predef_conforms then
955+
false
953956
else
954-
val locked = ctx.typerState.ownedVars
955-
val tryCtx = ctx.fresh
957+
// Using Mode.Printing will stop it from printing errors
956958
val tried = Contexts.withMode(Mode.Printing) {
957959
typed(
958960
tpd.ref(imp).withSpan(arg.span),
959961
fail.expectedType,
960-
locked
962+
ctx.typerState.ownedVars
961963
)
962-
}(using tryCtx)
963-
!tryCtx.reporter.hasErrors && fail.expectedType =:= tried.tpe
964+
}
965+
!hasErrors(tried) && fail.expectedType =:= tried.tpe
964966
}
965967
else
966968
Nil
967969

968-
MissingImplicitArgument(arg, pt, where, paramSymWithMethodCallTree, ignoredInstanceNormalImport, ignoredConversions)
970+
MissingImplicitArgument(arg, pt, where, paramSymWithMethodCallTree, ignoredInstanceNormalImport, ignoredConvertibleImplicits)
969971
}
970972

971973
/** A string indicating the formal parameter corresponding to a missing argument */

tests/neg/i16453.check

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,45 @@
1-
-- [E172] Type Error: tests/neg/i16453.scala:19:21 ---------------------------------------------------------------------
2-
19 | summon[Option[Int]] // error
1+
-- [E172] Type Error: tests/neg/i16453.scala:21:19 ---------------------------------------------------------------------
2+
21 | summon[List[Int]] // error
3+
| ^
4+
| No given instance of type List[Int] was found for parameter x of method summon in object Predef
5+
-- [E172] Type Error: tests/neg/i16453.scala:23:21 ---------------------------------------------------------------------
6+
23 | summon[Option[Int]] // error
37
| ^
48
|No given instance of type Option[Int] was found for parameter x of method summon in object Predef
59
|
610
|Note: implicit conversions are not automatically applied to arguments of using clauses. You will have to pass the argument explicitly.
7-
|The following conversions in scope can be converted to Option[Int]:
8-
|- given bar: Int
9-
-- [E172] Type Error: tests/neg/i16453.scala:20:25 ---------------------------------------------------------------------
10-
20 | implicitly[Option[Int]] // error
11+
|The following implicits in scope can be implicitly converted to Option[Int]:
12+
|- final lazy given val baz3: Char
13+
|- final lazy given val bar3: Int
14+
-- [E172] Type Error: tests/neg/i16453.scala:24:26 ---------------------------------------------------------------------
15+
24 | implicitly[Option[Char]] // error
16+
| ^
17+
|No given instance of type Option[Char] was found for parameter e of method implicitly in object Predef
18+
|
19+
|Note: implicit conversions are not automatically applied to arguments of using clauses. You will have to pass the argument explicitly.
20+
|The following implicits in scope can be implicitly converted to Option[Char]:
21+
|- final lazy given val baz3: Char
22+
-- [E172] Type Error: tests/neg/i16453.scala:25:20 ---------------------------------------------------------------------
23+
25 | implicitly[String] // error
24+
| ^
25+
|No given instance of type String was found for parameter e of method implicitly in object Predef
26+
|
27+
|Note: implicit conversions are not automatically applied to arguments of using clauses. You will have to pass the argument explicitly.
28+
|The following implicits in scope can be implicitly converted to String:
29+
|- final lazy given val baz3: Char
30+
-- [E172] Type Error: tests/neg/i16453.scala:35:16 ---------------------------------------------------------------------
31+
35 | summon[String] // error
32+
| ^
33+
|No given instance of type String was found for parameter x of method summon in object Predef
34+
|
35+
|Note: implicit conversions are not automatically applied to arguments of using clauses. You will have to pass the argument explicitly.
36+
|The following implicits in scope can be implicitly converted to String:
37+
|- implicit val baz2: Char
38+
-- [E172] Type Error: tests/neg/i16453.scala:36:25 ---------------------------------------------------------------------
39+
36 | implicitly[Option[Int]] // error
1140
| ^
12-
| No given instance of type Option[Int] was found for parameter e of method implicitly in object Predef
41+
|No given instance of type Option[Int] was found for parameter e of method implicitly in object Predef
42+
|
43+
|Note: implicit conversions are not automatically applied to arguments of using clauses. You will have to pass the argument explicitly.
44+
|The following implicits in scope can be implicitly converted to Option[Int]:
45+
|- implicit val bar2: Int

tests/neg/i16453.scala

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,36 @@ import scala.language.implicitConversions
22

33
trait Foo { type T }
44

5-
// Scala 3 style conversion
6-
given [T]: Conversion[T, Option[T]] = ???
7-
given [F <: Foo](using f: F): Conversion[f.T, Option[f.T]] = ???
8-
// Scala 2 style conversion
9-
implicit def toOption[T](t: T): Option[T] = Option(t)
10-
115
// This one is irrelevant, shouldn't be included in error message
12-
given irrelevant: Conversion[Int, Option[Long]] = ???
6+
given irrelevant: Long = ???
7+
8+
/** Use Scala 3 givens/conversions */
9+
def testScala3() = {
10+
given c1[T]: Conversion[T, Option[T]] = ???
11+
given c2[F <: Foo](using f: F): Conversion[f.T, Option[f.T]] = ???
12+
given Conversion[Char, String] = ???
13+
given Conversion[Char, Option[Int]] = ???
1314

14-
def test() = {
1515
given foo: Foo with
1616
type T = Int
17-
given bar: Int = 0
17+
given bar3: Int = 0
18+
given baz3: Char = 'a'
19+
20+
// This should get the usual error
21+
summon[List[Int]] // error
1822

1923
summon[Option[Int]] // error
24+
implicitly[Option[Char]] // error
25+
implicitly[String] // error
26+
}
27+
28+
/** Use Scala 2 implicits */
29+
def testScala2() = {
30+
implicit def toOpt[T](t: T): Option[T] = ???
31+
implicit def char2Str(c: Char): String = ???
32+
implicit val bar2: Int = 1
33+
implicit val baz2: Char = 'b'
34+
35+
summon[String] // error
2036
implicitly[Option[Int]] // error
2137
}

0 commit comments

Comments
 (0)