-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Protect agains scope extrusion in macros #7142
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
Labels
Comments
I think this is for after 3.0 since we have to figure out what to do on effects first. |
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
@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 outputexception 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) |
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
@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
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:
Macro use:
Stack trace
Another way to trigger the crash:
The text was updated successfully, but these errors were encountered: