From 0114f790a47b543feb4ffe47187fb3adcfae8aa7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 6 Dec 2021 18:51:34 +0100 Subject: [PATCH] Handle hoisted super arguments correctly in elimByName Fixes #14010 --- .../tools/dotc/transform/HoistSuperArgs.scala | 2 +- .../dotc/transform/TransformByNameApply.scala | 6 ++- tests/pos/i14010.scala | 46 +++++++++++++++++++ tests/pos/i14010a.scala | 3 ++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 tests/pos/i14010.scala create mode 100644 tests/pos/i14010a.scala diff --git a/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala b/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala index ca584561b711..e1bcc7e6a9b4 100644 --- a/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala +++ b/compiler/src/dotty/tools/dotc/transform/HoistSuperArgs.scala @@ -88,7 +88,7 @@ class HoistSuperArgs extends MiniPhase with IdentityDenotTransformer { thisPhase def newSuperArgMethod(argType: Type) = { val (staticFlag, methOwner) = if (cls.owner.is(Package)) (JavaStatic, cls) else (EmptyFlags, cls.owner) - val argTypeWrtConstr = argType.subst(origParams, allParamRefs(constr.info)) + val argTypeWrtConstr = argType.widenTermRefExpr.subst(origParams, allParamRefs(constr.info)) // argType with references to paramRefs of the primary constructor instead of // local parameter accessors newSymbol( diff --git a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala index af0998293904..9eb9b3f0ad5a 100644 --- a/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala +++ b/compiler/src/dotty/tools/dotc/transform/TransformByNameApply.scala @@ -11,7 +11,8 @@ import Types._ import Flags._ import Decorators._ import DenotTransformers._ -import core.StdNames.nme +import StdNames.nme +import NameKinds.SuperArgName import ast.Trees._ import reporting.trace @@ -51,7 +52,8 @@ abstract class TransformByNameApply extends MiniPhase { thisPhase: DenotTransfor if qual.tpe.derivesFrom(defn.Function0) && (isPureExpr(qual) || qual.symbol.isAllOf(Inline | Param)) => wrap(qual) case _ => - if (isByNameRef(arg) || arg.symbol == defn.cbnArg) arg + if isByNameRef(arg) || arg.symbol == defn.cbnArg || arg.symbol.name.is(SuperArgName) + then arg else wrap(mkByNameClosure(arg, argType)) } case _ => diff --git a/tests/pos/i14010.scala b/tests/pos/i14010.scala new file mode 100644 index 000000000000..a881f783f39b --- /dev/null +++ b/tests/pos/i14010.scala @@ -0,0 +1,46 @@ +abstract class LazyList[+T] { + def head: T + def tail: LazyList[T] + def isEmpty: Boolean + def push[E >: T](top: => E): LazyList[E] = + new Push[E](top, this) + //def map[R](f: T => R): LazyList[R] + def append[E >: T](that: => LazyList[E]): LazyList[E] +} + +private class Push[+T](top: => T, stack: => LazyList[T]) extends LazyList[T] { + override def head: T = + top + override def tail: LazyList[T] = + stack + override def isEmpty: Boolean = + false + //override def map[R](f: T => R): LazyList[R] = + // new Push[R](f(top), stack.map(f)) { + // override def map[R2](f2: R => R2): LazyList[R2] = + // Push.this.map(f2 compose f) + // } + override def append[E >: T](that: => LazyList[E]): LazyList[E] = + new Push[E](top, stack.append(that)) { + override def append[E2 >: E](that2: => LazyList[E2]): LazyList[E2] = + Push.this.append(that.append(that2)) + } +} + +object LazyList { + val empty = + new LazyList[Nothing] { + override def head: Nothing = + throw new NoSuchElementException + override def tail: LazyList[Nothing] = + throw new UnsupportedOperationException + override def isEmpty: Boolean = + true + //override def map[R](f: _ => R): LazyList[R] = + // this + override def append[E](that: => LazyList[E]): LazyList[E] = + that + } + def apply[T](elements: T*): LazyList[T] = + elements.foldRight[LazyList[T]](empty)(new Push(_, _)) +} \ No newline at end of file diff --git a/tests/pos/i14010a.scala b/tests/pos/i14010a.scala new file mode 100644 index 000000000000..5e77f55fdf62 --- /dev/null +++ b/tests/pos/i14010a.scala @@ -0,0 +1,3 @@ +class Foo(top: => Int) { + def foo: Any = new Foo(top) { } +} \ No newline at end of file