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

Hang on broken unapply macro #8158

Closed
scabug opened this issue Jan 17, 2014 · 5 comments
Closed

Hang on broken unapply macro #8158

scabug opened this issue Jan 17, 2014 · 5 comments
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented Jan 17, 2014

I had forgotten the outcome of discussion last year about name-based pattern matching, so trying to do patternless boolean extraction, I tried this broken form, which hangs the compiler, also on trunk:

package bug

import scala.language.experimental.macros
import scala.reflect.macros.{ WhiteboxContext => Context }
//import scala.reflect.macros.whitebox.Context

object Max {
  def impl(c: Context)(any: c.Expr[Any]): c.Expr[Any] = {
    import c.universe._
    def fail(msg: String) = c.abort(c.enclosingPosition, msg)
    val t = c.macroApplication match {
      case q"$_.unapply($unargs)" =>
        /* hangs
        */
        q"""
          new { 
            def isEmpty = false
            def get = this
            def unapply(x: String) = this
          }.unapply($unargs)
        """
        /*
        if get returns Unit or Boolean:
        wrong number of patterns for <$anon: AnyRef> offering Unit: expected 1, found 0
        */
        /* straightforward
        q"""
          new {
            def unapply(x: String) = true
          }.unapply($unargs)
        """
        */
      case _ => fail("bad appl")
    }
    c.Expr[Any](t)
  }
}

with sample usage

package bug

import scala.language.experimental.macros
import org.junit.Test

object X {
  def unapply(any: Any): Any = macro Max.impl
} 
    
class BugTest {
  @Test def bug(): Unit = {
    "any" match {
      case X() =>
      case _ => ???
    }   
  }
}
@scabug
Copy link
Author

scabug commented Jan 17, 2014

Imported From: https://issues.scala-lang.org/browse/SI-8158?orig=1
Reporter: @som-snytt
Affected Versions: 2.11.0-M7

@scabug
Copy link
Author

scabug commented Jan 18, 2014

@xeno-by said (edited on Jan 18, 2014 9:59:51 AM UTC):
I first thought that the hang is caused by infinite macro expansion, but apparently both doTypedUnapply and the macro impl are called only once. The problem is however localized in typer, because -Xprint:typer never prints anything. upd. In particular patmat.alignPatterns(fun1, args).unexpandedFormals seems to be at fault.

@scabug
Copy link
Author

scabug commented Jan 18, 2014

@xeno-by said:
Allright, here's what's going on. The macro emits

{
  final class $anon extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    def isEmpty = false;
    def get = this;
    def unapply(x: String) = this
  };
  new $anon()
}.unapply(<unapply-selector>)

Then this code under the alias of fun1 gets into https://github.com/xeno-by/scala/blob/master/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala#L306. Then patmat.alignPatterns(fun1, args) is called, which figures out that there's an arityError (https://github.com/xeno-by/scala/blob/master/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala#L108), which gets reported by stringifying the type of fun1, which looks like TypeRef(NoPrefix, TypeName("$anon"), List()).

Apparently it's the stringification that causes an infinite loop, because the type is self-referential. I thought we detect these cases already, but apparently not quite. I'll figure this out and submit a pull request later today.

@scabug
Copy link
Author

scabug commented Jan 18, 2014

@som-snytt said:
Thanks, I'd started looking through that code to see what I was supposed to do. I'll finish reading it at my leisure.

I'd hoped to work in a pun on "The Secret World of Arrietty" (or ArityError) before the bug was fixed.

@scabug
Copy link
Author

scabug commented Jan 19, 2014

@xeno-by said:
scala/scala#3385

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants