Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Protect agains scope extrusion in macros #7142

Closed
LPTK opened this issue Aug 30, 2019 · 4 comments
Closed

Protect agains scope extrusion in macros #7142

LPTK opened this issue Aug 30, 2019 · 4 comments

Comments

@LPTK
Copy link
Contributor

@LPTK LPTK commented Aug 30, 2019

In the absence of either a way to track scopes in types (as done in Squid), or of an effect system to prevent effects from occurring inside unquotes, macros can currently crash the compiler due to scope extrusion.

minimized code

Macro definition:

package macros
import scala.quoted._

def oops given QuoteContext = {
  var v = '{0};
  val q = '{ x: Int => ${ v = '{x}; v } }
  '{$q($v)}
}
inline def test = ${oops}

Macro use:

package macrotest

def foo = macros.test
Stack trace
[error] Could not find proxy for x: Int in List(val x, method $anonfun, method foo, module class Test$package$, module class macrotest, module class <root>), encl = method foo, owners = method foo, package object Test$package, package macrotest, package <root>; enclosures = method foo, package object Test$package, package macrotest, package <root>
[error] dotty.tools.dotc.transform.LambdaLift$Lifter.searchIn$1(LambdaLift.scala:381)
[error] dotty.tools.dotc.transform.LambdaLift$Lifter.proxy(LambdaLift.scala:394)
[error] dotty.tools.dotc.transform.LambdaLift$Lifter.proxyRef(LambdaLift.scala:412)
[error] dotty.tools.dotc.transform.LambdaLift.transformIdent(LambdaLift.scala:526)
[error] dotty.tools.dotc.transform.MegaPhase.goIdent(MegaPhase.scala:551)
[error] dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:225)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:394)
[error] dotty.tools.dotc.transform.MegaPhase.transformTrees$$anonfun$1(MegaPhase.scala:420)
[error] scala.collection.immutable.List.mapConserve(List.scala:179)
[error] dotty.tools.dotc.transform.MegaPhase.transformTrees(MegaPhase.scala:420)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:271)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:396)
[error] dotty.tools.dotc.transform.MegaPhase.transformTrees$$anonfun$1(MegaPhase.scala:420)
[error] scala.collection.immutable.List.mapConserve(List.scala:179)
[error] dotty.tools.dotc.transform.MegaPhase.transformTrees(MegaPhase.scala:420)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:271)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:396)
[error] dotty.tools.dotc.transform.MegaPhase.transformTrees$$anonfun$1(MegaPhase.scala:420)
[error] scala.collection.immutable.List.mapConserve(List.scala:179)
[error] dotty.tools.dotc.transform.MegaPhase.transformTrees(MegaPhase.scala:420)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:271)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:396)
[error] dotty.tools.dotc.transform.MegaPhase.mapDefDef$1(MegaPhase.scala:245)
[error] dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:248)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:394)
[error] dotty.tools.dotc.transform.MegaPhase.transformStat$2(MegaPhase.scala:404)
[error] dotty.tools.dotc.transform.MegaPhase.$anonfun$1(MegaPhase.scala:409)
[error] scala.collection.immutable.List.mapConserve(List.scala:179)
[error] dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:409)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:339)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:396)
[error] dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:251)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:394)
[error] dotty.tools.dotc.transform.MegaPhase.transformStat$2(MegaPhase.scala:404)
[error] dotty.tools.dotc.transform.MegaPhase.$anonfun$1(MegaPhase.scala:409)
[error] scala.collection.immutable.List.mapConserve(List.scala:179)
[error] dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:409)
[error] dotty.tools.dotc.transform.MegaPhase.mapPackage$1(MegaPhase.scala:356)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:359)
[error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:396)
[error] dotty.tools.dotc.transform.MegaPhase.transformUnit(MegaPhase.scala:415)
[error] dotty.tools.dotc.transform.MegaPhase.run(MegaPhase.scala:427)
[error] dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:316)
[error] scala.collection.immutable.List.map(List.scala:286)
[error] dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:318)
[error] dotty.tools.dotc.Run.runPhases$4$$anonfun$4(Run.scala:158)
[error] dotty.runtime.function.JProcedure1.apply(JProcedure1.java:15)
[error] dotty.runtime.function.JProcedure1.apply(JProcedure1.java:10)
[error] scala.collection.IndexedSeqOptimized.foreach(IndexedSeqOptimized.scala:36)
[error] scala.collection.IndexedSeqOptimized.foreach$(IndexedSeqOptimized.scala:33)
[error] scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:198)
[error] dotty.tools.dotc.Run.runPhases$5(Run.scala:170)
[error] dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:178)
[error] dotty.runtime.function.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
[error] dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:102)
[error] dotty.tools.dotc.Run.compileUnits(Run.scala:185)
[error] dotty.tools.dotc.Run.compileSources(Run.scala:120)
[error] dotty.tools.dotc.Run.compile(Run.scala:104)
[error] dotty.tools.dotc.Driver.doCompile(Driver.scala:34)
[error] dotty.tools.dotc.Driver.process(Driver.scala:172)
[error] dotty.tools.dotc.Main.process(Main.scala)
[error] xsbt.CachedCompilerImpl.run(CachedCompilerImpl.java:69)
[error] xsbt.CompilerInterface.run(CompilerInterface.java:41)
[error] sun.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
[error] sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] java.lang.reflect.Method.invoke(Method.java:498)
[error] sbt.internal.inc.AnalyzingCompiler.call(AnalyzingCompiler.scala:237)
[error] sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:111)
[error] sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:90)
[error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$3(MixedAnalyzingCompiler.scala:82)
[error] scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
[error] sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:133)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:73)
[error] sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:116)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:307)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:307)
[error] sbt.internal.inc.Incremental$.doCompile(Incremental.scala:106)
[error] sbt.internal.inc.Incremental$.$anonfun$compile$4(Incremental.scala:87)
[error] sbt.internal.inc.IncrementalCommon.recompileClasses(IncrementalCommon.scala:116)
[error] sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:63)
[error] sbt.internal.inc.Incremental$.$anonfun$compile$3(Incremental.scala:89)
[error] sbt.internal.inc.Incremental$.manageClassfiles(Incremental.scala:134)
[error] sbt.internal.inc.Incremental$.compile(Incremental.scala:80)
[error] sbt.internal.inc.IncrementalCompile$.apply(Compile.scala:67)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:311)
[error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:269)
[error] sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:159)
[error] sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:238)
[error] sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:69)
[error] sbt.Defaults$.compileIncrementalTaskImpl(Defaults.scala:1549)
[error] sbt.Defaults$.$anonfun$compileIncrementalTask$1(Defaults.scala:1523)
[error] scala.Function1.$anonfun$compose$1(Function1.scala:44)
[error] sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:40)
[error] sbt.std.Transform$$anon$4.work(System.scala:67)
[error] sbt.Execute.$anonfun$submit$2(Execute.scala:269)
[error] sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
[error] sbt.Execute.work(Execute.scala:278)
[error] sbt.Execute.$anonfun$submit$1(Execute.scala:269)
[error] sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178)
[error] sbt.CompletionService$$anon$2.call(CompletionService.scala:37)
[error] java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
[error] java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
[error] java.lang.Thread.run(Thread.java:745)

Another way to trigger the crash:

import scala.util.control.NonLocalReturns._

def oops given QuoteContext: Expr[Int] =
  returning('{ {x: Int => ${ throwReturn('x) }} apply 0 })
@odersky

This comment has been minimized.

Copy link
Contributor

@odersky odersky commented Sep 26, 2019

I think this is for after 3.0 since we have to figure out what to do on effects first.

@odersky odersky removed this from To do in Scala 3.0 Planning Sep 26, 2019
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Oct 31, 2019
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Oct 31, 2019
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Nov 1, 2019
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Nov 12, 2019
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 15, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 16, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 16, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 16, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 16, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 16, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 16, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 16, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 16, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 20, 2020
nicolasstucki added a commit to dotty-staging/dotty that referenced this issue Jan 20, 2020
nicolasstucki added a commit that referenced this issue Jan 23, 2020
Fix #7142: Detect scope extrusions in macros and run
@LPTK

This comment has been minimized.

Copy link
Contributor Author

@LPTK LPTK commented Jan 23, 2020

@nicolasstucki here's a related scope extrusion problem, which still causes a crash. I'm afraid the issue needs to be reopened:

package macros
import scala.quoted._

var saved = Option.empty[Expr[Int]]

def oops(given QuoteContext) = {
  if (saved.isEmpty) '{ (x: Int) => ${ saved = Some('{x}); 'x } }
  else saved.get
}
inline def test = ${oops}

object Test {
  macros.test
  macros.test // crash
}
Compilation output
exception while typing x of class class dotty.tools.dotc.ast.Trees$Ident # 74815
exception while typing {
  x
} of class class dotty.tools.dotc.ast.Trees$Inlined # 19567
exception while typing final module class Test$() extends Object(), _root_.scala.Serializable { this: Test.type =>
  {
    {
      {
        def $anonfun(x: Int): Int =
          {
            {
              x
            }
          }
        closure($anonfun)
      }
    }
  }
  {
    x
  }
} of class class dotty.tools.dotc.ast.Trees$TypeDef # 19569
exception while typing package <empty> {
  final lazy module val Test: Test$ = new Test$()
  final module class Test$() extends Object(), _root_.scala.Serializable { this: Test.type =>
    {
      {
        {
          def $anonfun(x: Int): Int =
            {
              {
                x
              }
            }
          closure($anonfun)
        }
      }
    }
    {
      x
    }
  }
} of class class dotty.tools.dotc.ast.Trees$PackageDef # 19570
*** error while checking tests/neg-macros/i7142/Test_2.scala after phase typer ***
java.lang.AssertionError: assertion failed: undefined symbol value x at line 11 while compiling tests/neg-macros/i7142/Test_2.scala
Fatal compiler crash when compiling: tests/neg-macros/i7142:
assertion failed: undefined symbol value x at line 11
dotty.DottyPredef$.assertFail(DottyPredef.scala:17)
dotty.tools.dotc.transform.TreeChecker$Checker.assertDefined(TreeChecker.scala:207)
dotty.tools.dotc.transform.TreeChecker$Checker.typedIdent(TreeChecker.scala:342)
dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:2130)
dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2208)
dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:123)
dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:304)
dotty.tools.dotc.typer.Typer.typed(Typer.scala:2247)
dotty.tools.dotc.typer.Typer.typed(Typer.scala:2243)
dotty.tools.dotc.typer.Typer.typed(Typer.scala:2259)
dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:289)
dotty.tools.dotc.typer.Typer.typedInlined(Typer.scala:1361)
dotty.tools.dotc.transform.TreeChecker$Checker.typedInlined$$anonfun$1(TreeChecker.scala:463)
dotty.tools.dotc.transform.TreeChecker$Checker.withDefinedSyms(TreeChecker.scala:171)
dotty.tools.dotc.transform.TreeChecker$Checker.typedInlined(TreeChecker.scala:463)
dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2172)
dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2209)
dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:123)
dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:304)
dotty.tools.dotc.typer.Typer.typed(Typer.scala:2247)
dotty.tools.dotc.typer.Typer.typed(Typer.scala:2259)
dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:289)
dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:2303)
dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:2325)
dotty.tools.dotc.transform.TreeChecker$Checker.typedStats(TreeChecker.scala:478)
dotty.tools.dotc.typer.Typer.typedClassDef(Typer.scala:1812)
dotty.tools.dotc.transform.TreeChecker$Checker.typedClassDef(TreeChecker.scala:418)
dotty.tools.dotc.typer.Typer.typedNamed$1(Typer.scala:2141)
dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2208)
dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:123)
dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:304)
dotty.tools.dotc.typer.Typer.typed(Typer.scala:2247)
dotty.tools.dotc.typer.Typer.typed(Typer.scala:2259)
dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:289)
dotty.tools.dotc.typer.Typer.traverse$1(Typer.scala:2281)
dotty.tools.dotc.typer.Typer.typedStats(Typer.scala:2325)
dotty.tools.dotc.transform.TreeChecker$Checker.typedStats(TreeChecker.scala:478)
dotty.tools.dotc.typer.Typer.typedPackageDef(Typer.scala:1938)
dotty.tools.dotc.typer.Typer.typedUnnamed$1(Typer.scala:2182)
dotty.tools.dotc.typer.Typer.typedUnadapted(Typer.scala:2209)
dotty.tools.dotc.typer.ReTyper.typedUnadapted(ReTyper.scala:123)
dotty.tools.dotc.transform.TreeChecker$Checker.typedUnadapted(TreeChecker.scala:304)
dotty.tools.dotc.typer.Typer.typed(Typer.scala:2247)
dotty.tools.dotc.typer.Typer.typed(Typer.scala:2259)
dotty.tools.dotc.transform.TreeChecker$Checker.typed(TreeChecker.scala:289)
dotty.tools.dotc.typer.Typer.typedExpr(Typer.scala:2367)
dotty.tools.dotc.transform.TreeChecker.check(TreeChecker.scala:124)
dotty.tools.dotc.transform.TreeChecker.run(TreeChecker.scala:97)
dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:315)
scala.collection.immutable.List.map(List.scala:219)
dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:316)
dotty.tools.dotc.Run.runPhases$4$$anonfun$4(Run.scala:167)
dotty.runtime.function.JProcedure1.apply(JProcedure1.java:15)
dotty.runtime.function.JProcedure1.apply(JProcedure1.java:10)
scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323)
dotty.tools.dotc.Run.runPhases$5(Run.scala:177)
dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:185)
dotty.runtime.function.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:65)
dotty.tools.dotc.Run.compileUnits(Run.scala:192)
dotty.tools.dotc.Run.compileSources(Run.scala:129)
dotty.tools.dotc.Run.compile(Run.scala:112)
dotty.tools.dotc.Driver.doCompile(Driver.scala:36)
dotty.tools.dotc.Driver.process(Driver.scala:189)
dotty.tools.dotc.Driver.process(Driver.scala:158)
dotty.tools.vulpix.ParallelTesting$Test.compile(ParallelTesting.scala:483)
dotty.tools.vulpix.ParallelTesting$CompilationLogic.compileTestSource$$anonfun$2$$anonfun$1(ParallelTesting.scala:208)
scala.collection.immutable.List.map(List.scala:223)
dotty.tools.vulpix.ParallelTesting$CompilationLogic.compileTestSource$$anonfun$1(ParallelTesting.scala:208)
scala.util.Try$.apply(Try.scala:210)
dotty.tools.vulpix.ParallelTesting$CompilationLogic.dotty$tools$vulpix$ParallelTesting$CompilationLogic$$compileTestSource(ParallelTesting.scala:209)
dotty.tools.vulpix.ParallelTesting$$anon$2.checkTestSource$$anonfun$1(ParallelTesting.scala:252)
dotty.runtime.function.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
dotty.tools.vulpix.ParallelTesting$Test.tryCompile(ParallelTesting.scala:424)
dotty.tools.vulpix.ParallelTesting$$anon$2.checkTestSource(ParallelTesting.scala:255)
dotty.tools.vulpix.ParallelTesting$Test$LoggedRunnable.run(ParallelTesting.scala:323)
dotty.tools.vulpix.ParallelTesting$$anon$2.run(ParallelTesting.scala:250)
java.util.concurrent.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1386)
java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
@LPTK

This comment has been minimized.

Copy link
Contributor Author

@LPTK LPTK commented Jan 23, 2020

And here's another one to watch out for:

package macros
import scala.quoted._

var saved = Option.empty[Expr[Any]]

def oops(c: Expr[Any])(given QuoteContext) = {
  if saved.isEmpty then
    saved = Some(c)
    c
  else saved.get
}
inline def test(c: Any) = ${oops('c)}

object Test {
  class A(x: Int) {
    macros.test(x)
  }
  class B(y: String) {
    macros.test(y)
  }
}

exception while typing final module class Test$() extends Object(), _root_.scala.Serializable { this: Test.type =>
  class A(x: Int) extends Object() {
    private[this] val x: Int
    {
      {
        A.this.x
      }
    }
  }
  class B(y: String) extends Object() {
    private[this] val y: String
    {
      {
        A.this.x
      }
    }
  }
} of class class dotty.tools.dotc.ast.Trees$TypeDef # 20675
...
*** error while checking tests/neg-macros/i7142/Test_2.scala after phase typer ***
java.lang.AssertionError: assertion failed: error while typing A.this, value <local B> is not contained in class A while compiling tests/neg-macros/i7142/Test_2.scala
Fatal compiler crash when compiling: tests/neg-macros/i7142:
assertion failed: error while typing A.this, value <local B> is not contained in class A
dotty.DottyPredef$.assertFail(DottyPredef.scala:17)
dotty.tools.dotc.transform.TreeChecker$Checker.typedThis(TreeChecker.scala:383)
...
nicolasstucki added a commit that referenced this issue Feb 5, 2020
Fix #7142: Detect escaped variables across macro expansion
@LPTK

This comment has been minimized.

Copy link
Contributor Author

@LPTK LPTK commented Feb 5, 2020

@nicolasstucki @liufengyun, the second example still crashes the compiler!

// Macro_1.scala

package macros
import scala.quoted._

var saved = Option.empty[Expr[Any]]

def oops(c: Expr[Any])(given QuoteContext) = {
  if saved.isEmpty then
    saved = Some(c)
    c
  else saved.get
}
inline def test(c: Any) = ${oops('c)}
// Test_2.scala

object Test {
  class A(x: Int) {
    macros.test(x)
  }
  class B(y: String) {
    macros.test(y)
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.