Skip to content

Typechecking partial functions is not idempotent #6187

Closed
@scabug

Description

@scabug

The following macro definition and usage shows a problematic interaction between resetLocalAttrs and partial functions.

Usage:

def m[T](t: T): List[List[T]] =
  demo( List((t,true)) collect { case (x,true) => x } )

Definition:

def demo[T](t: T): List[T] = macro macroImpl[T]

def macroImpl[T: c.AbsTypeTag](c: Context)(t: c.Expr[T]): c.Expr[List[T]] =
{
  val r = c.universe.reify { List(t.splice) }
  c.Expr[List[T]]( c.resetLocalAttrs(r.tree) )
}

The error is:

class Any is abstract; cannot be instantiated
     demo( List((t,true)) collect { case (x,true) => x })
                                  ^

The tree before and after calling resetLocalAttrs:

Before:

 immutable.this.List.apply(immutable.this.List.apply[(T, Boolean)](scala.Tuple2.apply[T, Boolean](t, true)).collect[T, List[T]]({
  @SerialVersionUID(0) final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[(T, Boolean),T] with Serializable {
    def <init>(): anonymous class $anonfun = {
      $anonfun.super.<init>();
      ()
    };
    final override def applyOrElse[A1 >: Nothing <: (T, Boolean), B1 >: T <: Any](x$1: A1, default: A1 => B1): B1 = (x$1: A1 @unchecked) match {
      case (_1: T, _2: Boolean)(T, Boolean)((x @ _), true) => x
    };
    final def isDefinedAt(x$1: (T, Boolean)): Boolean = (x$1: (T, Boolean) @unchecked) match {
      case (_1: T, _2: Boolean)(T, Boolean)((x @ _), true) => true
    }
  };
  new anonymous class $anonfun()
})(immutable.this.List.canBuildFrom[T]))

After:

 immutable.this.List.apply(immutable.this.List.apply[(T, Boolean)](scala.Tuple2.apply[T, Boolean](t, true)).collect[T, List[T]]({
  final <synthetic> class $anonfun extends scala.runtime.AbstractPartialFunction[(T, Boolean),T] with Serializable {
    def <init>() = {
      super.<init>();
      ()
    };
    final override def applyOrElse[A1 <: (T, Boolean), B1 >: T](x$1, default) = (x$1: <type ?>) match {
      case (_1: T, _2: Boolean)(T, Boolean)((x @ _), true) => x
    };
    final def isDefinedAt(x$1: (T, Boolean)): Boolean = (x$1: (T, Boolean) @unchecked) match {
      case (_1: T, _2: Boolean)(T, Boolean)((x @ _), true) => true
    }
  };
  new <type ?>()
})(immutable.this.List.canBuildFrom[T])) 

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions