wix-incubator / accord

Accord: A sane validation library for Scala
http://wix.github.io/accord/
Other
530 stars 55 forks source link

PartialFunction in validator leads to UnsupportedOperationException: Position.start on NoPosition #120

Closed timcharper closed 6 years ago

timcharper commented 6 years ago

The bug can be easily reproduced by pasting the following code into an Ammonite repl:

import $ivy.`com.wix::accord-core:0.7.1`
import com.wix.accord._
import com.wix.accord.dsl._
case class Thing(people: List[String])

val thingValidator = validator[Thing] { t =>
  t.people.collect { case p if p != "" => p } is notEmpty
}

Produces the following stack trace:

cmd4.sc:1: exception during macro expansion:
java.lang.UnsupportedOperationException: Position.start on NoPosition
    at scala.reflect.internal.util.Position.fail(Position.scala:17)
    at scala.reflect.internal.util.UndefinedPosition.start(Position.scala:94)
    at scala.reflect.internal.util.UndefinedPosition.start(Position.scala:90)
    at com.wix.accord.transform.MacroHelper$class.startPos(MacroHelper.scala:71)
    at com.wix.accord.transform.ValidationTransform.startPos(ValidationTransform.scala:24)
    at com.wix.accord.transform.ExpressionDescriber$$anonfun$1.applyOrElse(ExpressionDescriber.scala:50)
    at com.wix.accord.transform.ExpressionDescriber$$anonfun$1.applyOrElse(ExpressionDescriber.scala:50)
    at scala.runtime.AbstractPartialFunction.apply(AbstractPartialFunction.scala:36)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1657)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1654)
    at scala.reflect.api.Trees$Traverser.traverseTypeAscription(Trees.scala:2478)
    at scala.reflect.internal.Trees$$anonfun$traverseMemberDef$1$1.apply$mcV$sp(Trees.scala:1209)
    at scala.reflect.api.Trees$Traverser.atOwner(Trees.scala:2507)
    at scala.reflect.internal.Trees$class.traverseMemberDef$1(Trees.scala:1203)
    at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1328)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1658)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1654)
    at scala.reflect.api.Trees$Traverser.traverseTrees(Trees.scala:2484)
    at scala.reflect.api.Trees$Traverser.traverseParams(Trees.scala:2492)
    at scala.reflect.api.Trees$Traverser.traverseParamss(Trees.scala:2493)
    at scala.reflect.internal.Trees$$anonfun$traverseMemberDef$1$1.apply$mcV$sp(Trees.scala:1213)
    at scala.reflect.api.Trees$Traverser.atOwner(Trees.scala:2507)
    at scala.reflect.internal.Trees$class.traverseMemberDef$1(Trees.scala:1203)
    at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1328)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1658)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1654)
    at scala.reflect.api.Trees$Traverser.traverseStats(Trees.scala:2497)
    at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1232)
    at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1330)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1658)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1654)
    at scala.reflect.internal.Trees$$anonfun$traverseMemberDef$1$1.apply$mcV$sp(Trees.scala:1207)
    at scala.reflect.api.Trees$Traverser.atOwner(Trees.scala:2507)
    at scala.reflect.internal.Trees$class.traverseMemberDef$1(Trees.scala:1203)
    at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1328)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1658)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1654)
    at scala.reflect.api.Trees$Traverser.traverseTrees(Trees.scala:2484)
    at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1234)
    at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1330)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1658)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1654)
    at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1277)
    at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1330)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1658)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1654)
    at scala.reflect.api.Trees$Traverser.traverseTrees(Trees.scala:2484)
    at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1284)
    at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1330)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1658)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1654)
    at scala.reflect.internal.Trees$class.traverseComponents$1(Trees.scala:1283)
    at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1330)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:16)
    at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2475)
    at scala.reflect.internal.Trees$CollectTreeTraverser.traverse(Trees.scala:1658)
    at scala.reflect.internal.Trees$TreeContextApiImpl.collect(Trees.scala:118)
    at com.wix.accord.transform.ExpressionDescriber$class.prettyPrint(ExpressionDescriber.scala:50)
    at com.wix.accord.transform.ValidationTransform.prettyPrint(ValidationTransform.scala:24)
    at com.wix.accord.transform.ExpressionDescriber$class.genericDescription(ExpressionDescriber.scala:130)
    at com.wix.accord.transform.ValidationTransform.genericDescription(ValidationTransform.scala:24)
    at com.wix.accord.transform.ExpressionDescriber$class.describeTree(ExpressionDescriber.scala:123)
    at com.wix.accord.transform.ValidationTransform.describeTree(ValidationTransform.scala:24)
    at com.wix.accord.transform.RuleFinder$ValidatorApplication$$anonfun$2.apply(RuleFinder.scala:90)
    at com.wix.accord.transform.RuleFinder$ValidatorApplication$$anonfun$2.apply(RuleFinder.scala:90)
    at scala.Option.getOrElse(Option.scala:121)
    at com.wix.accord.transform.RuleFinder$ValidatorApplication$.unapply(RuleFinder.scala:90)
    at com.wix.accord.transform.RuleFinder$ValidatorApplication$.unapply(RuleFinder.scala:106)
    at com.wix.accord.transform.ValidationTransform$$anonfun$rewriteValidationRules$1.isDefinedAt(ValidationTransform.scala:201)
    at com.wix.accord.transform.ValidationTransform$$anonfun$rewriteValidationRules$1.isDefinedAt(ValidationTransform.scala:200)
    at scala.PartialFunction$OrElse.isDefinedAt(PartialFunction.scala:165)
    at scala.PartialFunction$OrElse.isDefinedAt(PartialFunction.scala:165)
    at scala.PartialFunction$OrElse.isDefinedAt(PartialFunction.scala:165)
    at com.wix.accord.transform.PatternHelper$$anon$2.traverse(PatternHelper.scala:84)
    at com.wix.accord.transform.PatternHelper$class.collectFromPattern(PatternHelper.scala:89)
    at com.wix.accord.transform.ValidationTransform.collectFromPattern(ValidationTransform.scala:24)
    at com.wix.accord.transform.ValidationTransform.transformed(ValidationTransform.scala:220)
    at com.wix.accord.transform.ValidationTransform$.apply(ValidationTransform.scala:240)
holograph commented 6 years ago

Thanks for the report @timcharper! Which Scala version are you using here?

holograph commented 6 years ago

(Reproduced with 2.12.3, leaving the comment in case other versions are also affected)

timcharper commented 6 years ago

Hi @holograph ! I reproduced it with both Scala 2.12.3 and Scala 2.11.11 :)

timcharper commented 6 years ago

🎉 Thank you @holograph !