Skip to content

Commit

Permalink
Merge pull request #15237 from smarter/bport-fix-lift-leak
Browse files Browse the repository at this point in the history
[backport] Fix lack of type avoidance in argument lifting
  • Loading branch information
Kordyjan authored May 24, 2022
2 parents 5cc0490 + 1ff2f92 commit 896c98c
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
7 changes: 4 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Symbols.scala
Original file line number Diff line number Diff line change
Expand Up @@ -512,14 +512,15 @@ object Symbols {
// ---- Symbol creation methods ----------------------------------

/** Create a symbol from its fields (info may be lazy) */
def newSymbol[N <: Name](
def newSymbol[N <: Name](using Context)(
owner: Symbol,
name: N,
flags: FlagSet,
info: Type,
privateWithin: Symbol = NoSymbol,
coord: Coord = NoCoord)(using Context): Symbol { type ThisName = N } = {
val sym = new Symbol(coord, ctx.base.nextSymId, ctx.nestingLevel).asInstanceOf[Symbol { type ThisName = N }]
coord: Coord = NoCoord,
nestingLevel: Int = ctx.nestingLevel): Symbol { type ThisName = N } = {
val sym = new Symbol(coord, ctx.base.nextSymId, nestingLevel).asInstanceOf[Symbol { type ThisName = N }]
val denot = SymDenotation(sym, owner, name, flags, info, privateWithin)
sym.denot = denot
sym
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ abstract class Lifter {
// don't instantiate here, as the type params could be further constrained, see tests/pos/pickleinf.scala
var liftedType = expr.tpe.widen.deskolemized
if (liftedFlags.is(Method)) liftedType = ExprType(liftedType)
val lifted = newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = spanCoord(expr.span))
val lifted = newSymbol(ctx.owner, name, liftedFlags | Synthetic, liftedType, coord = spanCoord(expr.span),
// Lifted definitions will be added to a local block, so they need to be
// at a higher nesting level to prevent leaks. See tests/pos/i15174.scala
nestingLevel = ctx.nestingLevel + 1)
defs += liftedDef(lifted, expr)
.withSpan(expr.span)
.changeNonLocalOwners(lifted)
Expand Down
34 changes: 34 additions & 0 deletions tests/pos/i15174.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
trait Error
sealed abstract class Codec[A] {
type AvroType
def encode(a: A): Either[Error, AvroType]
// def decode(value: Any): Either[Error, A]
}

object Codec {
type Aux[AvroType0, A] = Codec[A] {
type AvroType = AvroType0
}

final def instance[AvroType0, A](
encode: A => Either[Error, AvroType0],
// decode: Any => Either[Error, A]
): Codec.Aux[AvroType0, A] = ???

implicit final def option[A](implicit codec: Codec[A]): Codec[Option[A]] = ???
given Codec.Aux[Int, Int] = ???
}


@main def test() = {
implicit val codec: Codec[Option[Int]] =
Codec.instance(
Codec.option[Int].encode
// expands to:
// {
// val a: Codec[Option[Int]] = Codec.option[Int](Codec.given_Aux_Int_Int)
// a.encode
// },
// Codec.option[Int].decode
)
}

0 comments on commit 896c98c

Please sign in to comment.