diff --git a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala index 53c210a0f0e4..b786f618c89a 100644 --- a/compiler/src/dotty/tools/dotc/transform/init/Objects.scala +++ b/compiler/src/dotty/tools/dotc/transform/init/Objects.scala @@ -589,7 +589,7 @@ object Objects: values.map(ref => ref.widen(height)).join case Fun(code, thisV, klass, env) => - Fun(code, thisV.widenRefOrCold(height), klass, env.widen(height)) + Fun(code, thisV.widenRefOrCold(height), klass, env.widen(height - 1)) case ref @ OfClass(klass, outer, _, args, env) => val outer2 = outer.widen(height - 1) diff --git a/tests/init-global/neg/i18628.scala b/tests/init-global/neg/i18628.scala new file mode 100644 index 000000000000..798b3204338c --- /dev/null +++ b/tests/init-global/neg/i18628.scala @@ -0,0 +1,7 @@ +object Test: + class Box(val x: Int) + + def recur(a: => Box, b: => Box): Int = + a.x + recur(a, b) + b.x // error // error + + recur(Box(1), Box(2)) \ No newline at end of file diff --git a/tests/init-global/neg/i18628_2.scala b/tests/init-global/neg/i18628_2.scala new file mode 100644 index 000000000000..4ad428035441 --- /dev/null +++ b/tests/init-global/neg/i18628_2.scala @@ -0,0 +1,7 @@ +object Test: + class Box(val x: Int) + + def recur(a: => Box, b: Box): Int = + a.x + recur(a, b) + b.x // error + + recur(Box(1), Box(2)) diff --git a/tests/init-global/neg/i18628_3.scala b/tests/init-global/neg/i18628_3.scala new file mode 100644 index 000000000000..101674cffb6f --- /dev/null +++ b/tests/init-global/neg/i18628_3.scala @@ -0,0 +1,9 @@ +import scala.annotation.init.widen + +object Test: + class Box(val x: Int) + + def recur(a: => Box, b: => Box): Int = + a.x + recur(a: @widen(5), b: @widen(5)) + b.x // error // error + + recur(Box(1), Box(2)) \ No newline at end of file diff --git a/tests/init-global/pos/i18628.scala b/tests/init-global/pos/i18628.scala new file mode 100644 index 000000000000..71d9a1ed30a8 --- /dev/null +++ b/tests/init-global/pos/i18628.scala @@ -0,0 +1,91 @@ +abstract class Reader[+T] { + def first: T + + def rest: Reader[T] + + def atEnd: Boolean +} + +trait Parsers { + type Elem + type Input = Reader[Elem] + + sealed abstract class ParseResult[+T] { + val successful: Boolean + + def map[U](f: T => U): ParseResult[U] + + def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U] + } + + sealed abstract class NoSuccess(val msg: String) extends ParseResult[Nothing] { // when we don't care about the difference between Failure and Error + val successful = false + + def map[U](f: Nothing => U) = this + + def flatMapWithNext[U](f: Nothing => Input => ParseResult[U]): ParseResult[U] + = this + } + + case class Failure(override val msg: String) extends NoSuccess(msg) + + case class Error(override val msg: String) extends NoSuccess(msg) + + case class Success[+T](result: T, val next: Input) extends ParseResult[T] { + val successful = true + + def map[U](f: T => U) = Success(f(result), next) + + def flatMapWithNext[U](f: T => Input => ParseResult[U]): ParseResult[U] = f(result)(next) match { + case s @ Success(result, rest) => Success(result, rest) + case f: Failure => f + case e: Error => e + } + } + + case class ~[+a, +b](_1: a, _2: b) { + override def toString = s"(${_1}~${_2})" + } + + abstract class Parser[+T] extends (Input => ParseResult[T]) { + def apply(in: Input): ParseResult[T] + + def ~ [U](q: => Parser[U]): Parser[~[T, U]] = { + (for(a <- this; b <- q) yield new ~(a,b)) + } + + def flatMap[U](f: T => Parser[U]): Parser[U] + = Parser{ in => this(in) flatMapWithNext(f)} + + def map[U](f: T => U): Parser[U] //= flatMap{x => success(f(x))} + = Parser{ in => this(in) map(f)} + + def ^^ [U](f: T => U): Parser[U] = map(f) + } + + def Parser[T](f: Input => ParseResult[T]): Parser[T] + = new Parser[T]{ def apply(in: Input) = f(in) } + + def accept(e: Elem): Parser[Elem] = acceptIf(_ == e)("'"+e+"' expected but " + _ + " found") + + def acceptIf(p: Elem => Boolean)(err: Elem => String): Parser[Elem] = Parser { in => + if (in.atEnd) Failure("end of input") + else if (p(in.first)) Success(in.first, in.rest) + else Failure(err(in.first)) + } +} + + +object grammars3 extends Parsers { + type Elem = String + + val a: Parser[String] = accept("a") + val b: Parser[String] = accept("b") + + val AnBnCn: Parser[List[String]] = { + repMany(a,b) + } + + def repMany[T](p: => Parser[T], q: => Parser[T]): Parser[List[T]] = + p~repMany(p,q)~q ^^ {case x~xs~y => x::xs:::(y::Nil)} +} \ No newline at end of file