Skip to content

Commit cfe5e55

Browse files
committed
Fix #7459: Fix two crash conditions in Inliner
1 parent 86c2687 commit cfe5e55

File tree

3 files changed

+74
-9
lines changed

3 files changed

+74
-9
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ object Inferencing {
4343
if (isFullyDefined(tp, ForceDegree.all)) tp
4444
else throw new Error(i"internal error: type of $what $tp is not fully defined, pos = $span") // !!! DEBUG
4545

46-
4746
/** Instantiate selected type variables `tvars` in type `tp` */
4847
def instantiateSelected(tp: Type, tvars: List[Type])(implicit ctx: Context): Unit =
4948
if (tvars.nonEmpty)

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

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import Names.{Name, TermName}
1818
import NameKinds.{InlineAccessorName, InlineBinderName, InlineScrutineeName}
1919
import ProtoTypes.selectionProto
2020
import SymDenotations.SymDenotation
21-
import Inferencing.fullyDefinedType
21+
import Inferencing.isFullyDefined
2222
import config.Printers.inlining
2323
import ErrorReporting.errorTree
2424
import dotty.tools.dotc.tastyreflect.ReflectionImpl
@@ -242,8 +242,10 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
242242

243243
inlining.println(i"-----------------------\nInlining $call\nWith RHS $rhsToInline")
244244

245-
// Make sure all type arguments to the call are fully determined
246-
for (targ <- callTypeArgs) fullyDefinedType(targ.tpe, "inlined type argument", targ.span)
245+
// Make sure all type arguments to the call are fully determined,
246+
// but continue if that's not achievable (or else i7459.scala would crash).
247+
for arg <- callTypeArgs do
248+
isFullyDefined(arg.tpe, ForceDegree.all)
247249

248250
/** A map from parameter names of the inlineable method to references of the actual arguments.
249251
* For a type argument this is the full argument type.
@@ -316,9 +318,9 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
316318

317319
/** Populate `paramBinding` and `bindingsBuf` by matching parameters with
318320
* corresponding arguments. `bindingbuf` will be further extended later by
319-
* proxies to this-references.
321+
* proxies to this-references. Issue an error if some arguments are missing.
320322
*/
321-
private def computeParamBindings(tp: Type, targs: List[Tree], argss: List[List[Tree]]): Unit = tp match {
323+
private def computeParamBindings(tp: Type, targs: List[Tree], argss: List[List[Tree]]): Boolean = tp match
322324
case tp: PolyType =>
323325
tp.paramNames.lazyZip(targs).foreach { (name, arg) =>
324326
paramSpan(name) = arg.span
@@ -327,8 +329,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
327329
computeParamBindings(tp.resultType, Nil, argss)
328330
case tp: MethodType =>
329331
if argss.isEmpty then
330-
// can happen if arguments have errors, see i7438.scala
331332
ctx.error(i"mising arguments for inline method $inlinedMethod", call.sourcePos)
333+
false
332334
else
333335
tp.paramNames.lazyZip(tp.paramInfos).lazyZip(argss.head).foreach { (name, paramtp, arg) =>
334336
paramSpan(name) = arg.span
@@ -341,7 +343,7 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
341343
case _ =>
342344
assert(targs.isEmpty)
343345
assert(argss.isEmpty)
344-
}
346+
true
345347

346348
// Compute val-definitions for all this-proxies and append them to `bindingsBuf`
347349
private def computeThisBindings() = {
@@ -450,7 +452,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(implicit ctx: Context) {
450452
}
451453

452454
// Compute bindings for all parameters, appending them to bindingsBuf
453-
computeParamBindings(inlinedMethod.info, callTypeArgs, callValueArgss)
455+
if !computeParamBindings(inlinedMethod.info, callTypeArgs, callValueArgss) then
456+
return call
454457

455458
// make sure prefix is executed if it is impure
456459
if (!isIdempotentExpr(inlineCallPrefix)) registerType(inlinedMethod.owner.thisType)

tests/neg/i7459.scala

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
object Foo {
2+
inline def summon[T](x: T): T = x match {
3+
case t: T => t
4+
}
5+
println(summon)
6+
}
7+
8+
import scala.deriving._
9+
import scala.compiletime.erasedValue
10+
11+
inline def summon[T](given t:T): T = t match {
12+
case t: T => t
13+
}
14+
15+
inline def summonAll[T <: Tuple]: List[Eq[_]] = inline erasedValue[T] match {
16+
case _: Unit => Nil
17+
case _: (t *: ts) => summon[Eq[t]] :: summonAll[ts]
18+
}
19+
20+
trait Eq[T] {
21+
def eqv(x: T, y: T): Boolean
22+
}
23+
24+
object Eq {
25+
given Eq[Int] {
26+
def eqv(x: Int, y: Int) = x == y
27+
}
28+
29+
def check(elem: Eq[_])(x: Any, y: Any): Boolean =
30+
elem.asInstanceOf[Eq[Any]].eqv(x, y)
31+
32+
def iterator[T](p: T) = p.asInstanceOf[Product].productIterator
33+
34+
def eqSum[T](s: Mirror.SumOf[T], elems: List[Eq[_]]): Eq[T] =
35+
new Eq[T] {
36+
def eqv(x: T, y: T): Boolean = {
37+
val ordx = s.ordinal(x)
38+
(s.ordinal(y) == ordx) && check(elems(ordx))(x, y)
39+
}
40+
}
41+
42+
def eqProduct[T](p: Mirror.ProductOf[T], elems: List[Eq[_]]): Eq[T] =
43+
new Eq[T] {
44+
def eqv(x: T, y: T): Boolean =
45+
iterator(x).zip(iterator(y)).zip(elems.iterator).forall {
46+
case ((x, y), elem) => check(elem)(x, y)
47+
}
48+
}
49+
50+
inline given derived[T](given m: Mirror.Of[T]): Eq[T] = {
51+
val elemInstances = summonAll[m.MirroredElemTypes]
52+
inline m match {
53+
case s: Mirror.SumOf[T] => eqSum(s, elemInstances)
54+
case p: Mirror.ProductOf[T] => eqProduct(p, elemInstances)
55+
}
56+
}
57+
}
58+
59+
60+
enum Opt[+T] derives Eq {
61+
case Sm(t: T)
62+
case Nn
63+
}

0 commit comments

Comments
 (0)