Skip to content

Commit 1c3a1ae

Browse files
authored
I18628 (#18841)
This PR fixes the minimized test of #18628 that previously runs infinitely on the global initialization checker.
2 parents e149e4c + 2c582c3 commit 1c3a1ae

File tree

5 files changed

+115
-1
lines changed

5 files changed

+115
-1
lines changed

compiler/src/dotty/tools/dotc/transform/init/Objects.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ object Objects:
589589
values.map(ref => ref.widen(height)).join
590590

591591
case Fun(code, thisV, klass, env) =>
592-
Fun(code, thisV.widenRefOrCold(height), klass, env.widen(height))
592+
Fun(code, thisV.widenRefOrCold(height), klass, env.widen(height - 1))
593593

594594
case ref @ OfClass(klass, outer, _, args, env) =>
595595
val outer2 = outer.widen(height - 1)

tests/init-global/neg/i18628.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
object Test:
2+
class Box(val x: Int)
3+
4+
def recur(a: => Box, b: => Box): Int =
5+
a.x + recur(a, b) + b.x // error // error
6+
7+
recur(Box(1), Box(2))

tests/init-global/neg/i18628_2.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
object Test:
2+
class Box(val x: Int)
3+
4+
def recur(a: => Box, b: Box): Int =
5+
a.x + recur(a, b) + b.x // error
6+
7+
recur(Box(1), Box(2))

tests/init-global/neg/i18628_3.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import scala.annotation.init.widen
2+
3+
object Test:
4+
class Box(val x: Int)
5+
6+
def recur(a: => Box, b: => Box): Int =
7+
a.x + recur(a: @widen(5), b: @widen(5)) + b.x // error // error
8+
9+
recur(Box(1), Box(2))

tests/init-global/pos/i18628.scala

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
abstract class Reader[+T] {
2+
def first: T
3+
4+
def rest: Reader[T]
5+
6+
def atEnd: Boolean
7+
}
8+
9+
trait Parsers {
10+
type Elem
11+
type Input = Reader[Elem]
12+
13+
sealed abstract class ParseResult[+T] {
14+
val successful: Boolean
15+
16+
def map[U](f: T => U): ParseResult[U]
17+
18+
def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U]
19+
}
20+
21+
sealed abstract class NoSuccess(val msg: String) extends ParseResult[Nothing] { // when we don't care about the difference between Failure and Error
22+
val successful = false
23+
24+
def map[U](f: Nothing => U) = this
25+
26+
def flatMapWithNext[U](f: Nothing => Input => ParseResult[U]): ParseResult[U]
27+
= this
28+
}
29+
30+
case class Failure(override val msg: String) extends NoSuccess(msg)
31+
32+
case class Error(override val msg: String) extends NoSuccess(msg)
33+
34+
case class Success[+T](result: T, val next: Input) extends ParseResult[T] {
35+
val successful = true
36+
37+
def map[U](f: T => U) = Success(f(result), next)
38+
39+
def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U] = f(result)(next) match {
40+
case s @ Success(result, rest) => Success(result, rest)
41+
case f: Failure => f
42+
case e: Error => e
43+
}
44+
}
45+
46+
case class ~[+a, +b](_1: a, _2: b) {
47+
override def toString = s"(${_1}~${_2})"
48+
}
49+
50+
abstract class Parser[+T] extends (Input => ParseResult[T]) {
51+
def apply(in: Input): ParseResult[T]
52+
53+
def ~ [U](q: => Parser[U]): Parser[~[T, U]] = {
54+
(for(a <- this; b <- q) yield new ~(a,b))
55+
}
56+
57+
def flatMap[U](f: T => Parser[U]): Parser[U]
58+
= Parser{ in => this(in) flatMapWithNext(f)}
59+
60+
def map[U](f: T => U): Parser[U] //= flatMap{x => success(f(x))}
61+
= Parser{ in => this(in) map(f)}
62+
63+
def ^^ [U](f: T => U): Parser[U] = map(f)
64+
}
65+
66+
def Parser[T](f: Input => ParseResult[T]): Parser[T]
67+
= new Parser[T]{ def apply(in: Input) = f(in) }
68+
69+
def accept(e: Elem): Parser[Elem] = acceptIf(_ == e)("'"+e+"' expected but " + _ + " found")
70+
71+
def acceptIf(p: Elem => Boolean)(err: Elem => String): Parser[Elem] = Parser { in =>
72+
if (in.atEnd) Failure("end of input")
73+
else if (p(in.first)) Success(in.first, in.rest)
74+
else Failure(err(in.first))
75+
}
76+
}
77+
78+
79+
object grammars3 extends Parsers {
80+
type Elem = String
81+
82+
val a: Parser[String] = accept("a")
83+
val b: Parser[String] = accept("b")
84+
85+
val AnBnCn: Parser[List[String]] = {
86+
repMany(a,b)
87+
}
88+
89+
def repMany[T](p: => Parser[T], q: => Parser[T]): Parser[List[T]] =
90+
p~repMany(p,q)~q ^^ {case x~xs~y => x::xs:::(y::Nil)}
91+
}

0 commit comments

Comments
 (0)