Skip to content

Commit bf994f9

Browse files
authored
Fix widen types before checking an implicit view exists (#18719)
Fixes #18650
2 parents 5f5b517 + 8a2773f commit bf994f9

File tree

6 files changed

+55
-39
lines changed

6 files changed

+55
-39
lines changed

Diff for: compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

+1
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ private sealed trait YSettings:
421421
val YshowVarBounds: Setting[Boolean] = BooleanSetting("-Yshow-var-bounds", "Print type variables with their bounds.")
422422

423423
val YnoDecodeStacktraces: Setting[Boolean] = BooleanSetting("-Yno-decode-stacktraces", "Show raw StackOverflow stacktraces, instead of decoding them into triggering operations.")
424+
val YnoEnrichErrorMessages: Setting[Boolean] = BooleanSetting("-Yno-enrich-error-messages", "Show raw error messages, instead of enriching them with contextual information.")
424425

425426
val Yinstrument: Setting[Boolean] = BooleanSetting("-Yinstrument", "Add instrumentation code that counts allocations and closure creations.")
426427
val YinstrumentDefs: Setting[Boolean] = BooleanSetting("-Yinstrument-defs", "Add instrumentation code that counts method calls; needs -Yinstrument to be set, too.")

Diff for: compiler/src/dotty/tools/dotc/report.scala

+11-38
Original file line numberDiff line numberDiff line change
@@ -132,50 +132,26 @@ object report:
132132
private object messageRendering extends MessageRendering
133133

134134
// Should only be called from Run#enrichErrorMessage.
135-
def enrichErrorMessage(errorMessage: String)(using Context): String = try {
135+
def enrichErrorMessage(errorMessage: String)(using Context): String =
136+
if ctx.settings.YnoEnrichErrorMessages.value then errorMessage
137+
else try enrichErrorMessage1(errorMessage)
138+
catch case _: Throwable => errorMessage // don't introduce new errors trying to report errors, so swallow exceptions
139+
140+
private def enrichErrorMessage1(errorMessage: String)(using Context): String = {
141+
import untpd.*, config.Settings.*
136142
def formatExplain(pairs: List[(String, Any)]) = pairs.map((k, v) => f"$k%20s: $v").mkString("\n")
137143

138144
val settings = ctx.settings.userSetSettings(ctx.settingsState).sortBy(_.name)
139-
val tree = ctx.tree
140-
val sym = tree.symbol
141-
val pos = tree.sourcePos
142-
val path = pos.source.path
143-
val site = ctx.outersIterator.map(_.owner).filter(sym => !sym.exists || sym.isClass || sym.is(Method)).next()
144-
145-
import untpd.*
146-
extension (tree: Tree) def summaryString: String = tree match
147-
case Literal(const) => s"Literal($const)"
148-
case Ident(name) => s"Ident(${name.decode})"
149-
case Select(qual, name) => s"Select(${qual.summaryString}, ${name.decode})"
150-
case tree: NameTree => (if tree.isType then "type " else "") + tree.name.decode
151-
case tree => s"${tree.className}${if tree.symbol.exists then s"(${tree.symbol})" else ""}"
145+
def showSetting(s: Setting[?]): String = if s.value == "" then s"${s.name} \"\"" else s"${s.name} ${s.value}"
152146

153147
val info1 = formatExplain(List(
154148
"while compiling" -> ctx.compilationUnit,
155149
"during phase" -> ctx.phase.megaPhase,
156150
"mode" -> ctx.mode,
157151
"library version" -> scala.util.Properties.versionString,
158152
"compiler version" -> dotty.tools.dotc.config.Properties.versionString,
159-
"settings" -> settings.map(s => if s.value == "" then s"${s.name} \"\"" else s"${s.name} ${s.value}").mkString(" "),
160-
))
161-
val symbolInfos = if sym eq NoSymbol then List("symbol" -> sym) else List(
162-
"symbol" -> sym.showLocated,
163-
"symbol definition" -> s"${sym.showDcl} (a ${sym.className})",
164-
"symbol package" -> sym.enclosingPackageClass.fullName,
165-
"symbol owners" -> sym.showExtendedLocation,
166-
)
167-
val info2 = formatExplain(List(
168-
"tree" -> tree.summaryString,
169-
"tree position" -> (if pos.exists then s"$path:${pos.line + 1}:${pos.column}" else s"$path:<unknown>"),
170-
"tree type" -> tree.typeOpt.show,
171-
) ::: symbolInfos ::: List(
172-
"call site" -> s"${site.showLocated} in ${site.enclosingPackageClass}"
153+
"settings" -> settings.map(showSetting).mkString(" "),
173154
))
174-
val context_s = try
175-
s""" == Source file context for tree position ==
176-
|
177-
|${messageRendering.messageAndPos(Diagnostic.Error("", pos))}""".stripMargin
178-
catch case _: Exception => "<Cannot read source file>"
179155
s"""
180156
| $errorMessage
181157
|
@@ -184,9 +160,6 @@ object report:
184160
| https://github.com/lampepfl/dotty/issues/new/choose
185161
|
186162
|$info1
187-
|
188-
|$info2
189-
|
190-
|$context_s""".stripMargin
191-
} catch case _: Throwable => errorMessage // don't introduce new errors trying to report errors, so swallow exceptions
163+
|""".stripMargin
164+
}
192165
end report

Diff for: compiler/src/dotty/tools/dotc/typer/Implicits.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ trait Implicits:
850850
&& !to.isError
851851
&& !ctx.isAfterTyper
852852
&& ctx.mode.is(Mode.ImplicitsEnabled)
853-
&& from.isValueType
853+
&& from.widen.isValueType
854854
&& ( from.isValueSubType(to)
855855
|| inferView(dummyTreeOfType(from), to)
856856
(using ctx.fresh.addMode(Mode.ImplicitExploration).setExploreTyperState()).isSuccess

Diff for: tests/neg/i18650.min.scala

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Church[B]:
2+
type Nat = Tuple1[B]
3+
4+
class Test:
5+
given makeChurch[C]: Church[C] = ??? // necessary to cause crash
6+
7+
def churchTest(c: Church[Int]): Unit =
8+
val res1 = summon[c.Nat =:= Int] // error (not a compiler crash)

Diff for: tests/neg/i18650.min2.scala

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Church[B]:
2+
type Nat = Tuple1[B]
3+
4+
class Test2:
5+
given makeChurch2[C](using DummyImplicit): Church[C] = ???
6+
7+
def churchTest2(c: Church[Int]): Unit =
8+
val res2 = summon[c.Nat =:= Int] // error (not a compiler crash)

Diff for: tests/neg/i18650.scala

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
trait Lam:
2+
type F[_]
3+
extension [A, B](f: F[A => B]) def apply(arg: F[A]): F[B]
4+
def lam[A, B](f: F[A] => F[B]): F[A => B]
5+
final def id[A]: F[A => A] = lam(identity[F[A]])
6+
7+
object LamInterpreter extends Lam:
8+
type F[t] = t
9+
def lam[A, B](f: F[A] => F[B]): F[A => B] = f
10+
extension [A, B](f: F[A => B]) def apply(arg: F[A]): F[B] = f(arg)
11+
12+
13+
class Church[A](using val l: Lam):
14+
import l.*
15+
type Nat = F[(A => A) => (A => A)]
16+
def zero: Nat = id
17+
extension (n: Nat) def suc: Nat = lam(f => lam(x => f(n(f)(x))))
18+
19+
given [A](using l: Lam): Church[A] = Church()
20+
21+
22+
@main
23+
def churchTest =
24+
given Lam = LamInterpreter
25+
val c: Church[Int] = summon
26+
summon[c.Nat =:= ((Int => Int) => (Int => Int))] // error (not a compiler crash)

0 commit comments

Comments
 (0)