Skip to content

Commit 5fce9c3

Browse files
committed
Fix lack of type avoidance in argument lifting
We need to manually increase the nestingLevel of symbols created by EtaExpansion#lift to compensate for the fact that they will end up in a block. Fixes #15174.
1 parent 965f164 commit 5fce9c3

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

compiler/src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -512,14 +512,15 @@ object Symbols {
512512
// ---- Symbol creation methods ----------------------------------
513513

514514
/** Create a symbol from its fields (info may be lazy) */
515-
def newSymbol[N <: Name](
515+
def newSymbol[N <: Name](using Context)(
516516
owner: Symbol,
517517
name: N,
518518
flags: FlagSet,
519519
info: Type,
520520
privateWithin: Symbol = NoSymbol,
521-
coord: Coord = NoCoord)(using Context): Symbol { type ThisName = N } = {
522-
val sym = new Symbol(coord, ctx.base.nextSymId, ctx.nestingLevel).asInstanceOf[Symbol { type ThisName = N }]
521+
coord: Coord = NoCoord,
522+
nestingLevel: Int = ctx.nestingLevel): Symbol { type ThisName = N } = {
523+
val sym = new Symbol(coord, ctx.base.nextSymId, nestingLevel).asInstanceOf[Symbol { type ThisName = N }]
523524
val denot = SymDenotation(sym, owner, name, flags, info, privateWithin)
524525
sym.denot = denot
525526
sym

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,10 @@ abstract class Lifter {
4949
// don't instantiate here, as the type params could be further constrained, see tests/pos/pickleinf.scala
5050
var liftedType = expr.tpe.widen.deskolemized
5151
if (liftedFlags.is(Method)) liftedType = ExprType(liftedType)
52-
val lifted = newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = spanCoord(expr.span))
52+
val lifted = newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = spanCoord(expr.span),
53+
// Lifted definitions will be added to a local block, so they need to be
54+
// at a higher nesting level to prevent leaks. See tests/pos/i15174.scala
55+
nestingLevel = ctx.nestingLevel + 1)
5356
defs += liftedDef(lifted, expr)
5457
.withSpan(expr.span)
5558
.changeNonLocalOwners(lifted)

tests/pos/i15174.scala

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
trait Error
2+
sealed abstract class Codec[A] {
3+
type AvroType
4+
def encode(a: A): Either[Error, AvroType]
5+
// def decode(value: Any): Either[Error, A]
6+
}
7+
8+
object Codec {
9+
type Aux[AvroType0, A] = Codec[A] {
10+
type AvroType = AvroType0
11+
}
12+
13+
final def instance[AvroType0, A](
14+
encode: A => Either[Error, AvroType0],
15+
// decode: Any => Either[Error, A]
16+
): Codec.Aux[AvroType0, A] = ???
17+
18+
implicit final def option[A](implicit codec: Codec[A]): Codec[Option[A]] = ???
19+
given Codec.Aux[Int, Int] = ???
20+
}
21+
22+
23+
@main def test() = {
24+
implicit val codec: Codec[Option[Int]] =
25+
Codec.instance(
26+
Codec.option[Int].encode
27+
// expands to:
28+
// {
29+
// val a: Codec[Option[Int]] = Codec.option[Int](Codec.given_Aux_Int_Int)
30+
// a.encode
31+
// },
32+
// Codec.option[Int].decode
33+
)
34+
}

0 commit comments

Comments
 (0)