Skip to content

Commit 2c23a5e

Browse files
committed
Merge pull request scala#3974 from xeno-by/topic/buffer-pattern-expander-errors
This ensures that typechecking custom unapplications in silent mode
2 parents 190c672 + 3b35177 commit 2c23a5e

File tree

7 files changed

+44
-12
lines changed

7 files changed

+44
-12
lines changed

src/compiler/scala/tools/nsc/transform/UnCurry.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ abstract class UnCurry extends InfoTransform
459459
case UnApply(fn, args) =>
460460
val fn1 = transform(fn)
461461
val args1 = fn.symbol.name match {
462-
case nme.unapplySeq => transformArgs(tree.pos, fn.symbol, args, patmat.alignPatterns(tree).expectedTypes)
462+
case nme.unapplySeq => transformArgs(tree.pos, fn.symbol, args, patmat.alignPatterns(global.typer.context, tree).expectedTypes)
463463
case _ => args
464464
}
465465
treeCopy.UnApply(tree, fn1, args1)

src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ trait MatchTranslation {
377377
object ExtractorCall {
378378
// TODO: check unargs == args
379379
def apply(tree: Tree): ExtractorCall = tree match {
380-
case UnApply(unfun, args) => new ExtractorCallRegular(alignPatterns(tree), unfun, args) // extractor
381-
case Apply(fun, args) => new ExtractorCallProd(alignPatterns(tree), fun, args) // case class
380+
case UnApply(unfun, args) => new ExtractorCallRegular(alignPatterns(context, tree), unfun, args) // extractor
381+
case Apply(fun, args) => new ExtractorCallProd(alignPatterns(context, tree), fun, args) // case class
382382
}
383383
}
384384

src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ trait ScalacPatternExpanders {
1818
import global._
1919
import definitions._
2020
import treeInfo._
21+
import analyzer._
2122

2223
type PatternAligned = ScalacPatternExpander#Aligned
2324

@@ -94,7 +95,7 @@ trait ScalacPatternExpanders {
9495
def tupleExtractor(extractor: Extractor): Extractor =
9596
extractor.copy(fixed = tupleType(extractor.fixed) :: Nil)
9697

97-
private def validateAligned(tree: Tree, aligned: Aligned): Aligned = {
98+
private def validateAligned(context: Context, tree: Tree, aligned: Aligned): Aligned = {
9899
import aligned._
99100

100101
def owner = tree.symbol.owner
@@ -103,8 +104,8 @@ trait ScalacPatternExpanders {
103104
def offerString = if (extractor.isErroneous) "" else s" offering $offering"
104105
def arityExpected = ( if (extractor.hasSeq) "at least " else "" ) + productArity
105106

106-
def err(msg: String) = reporter.error(tree.pos, msg)
107-
def warn(msg: String) = reporter.warning(tree.pos, msg)
107+
def err(msg: String) = context.error(tree.pos, msg)
108+
def warn(msg: String) = context.warning(tree.pos, msg)
108109
def arityError(what: String) = err(s"$what patterns for $owner$offerString: expected $arityExpected, found $totalArity")
109110

110111
if (isStar && !isSeq)
@@ -117,7 +118,7 @@ trait ScalacPatternExpanders {
117118
aligned
118119
}
119120

120-
def apply(sel: Tree, args: List[Tree]): Aligned = {
121+
def apply(context: Context, sel: Tree, args: List[Tree]): Aligned = {
121122
val fn = sel match {
122123
case Unapplied(fn) => fn
123124
case _ => sel
@@ -145,12 +146,12 @@ trait ScalacPatternExpanders {
145146
}
146147

147148
val normalizedExtractor = if (requiresTupling) tupleExtractor(extractor) else extractor
148-
validateAligned(fn, Aligned(patterns, normalizedExtractor))
149+
validateAligned(context, fn, Aligned(patterns, normalizedExtractor))
149150
}
150151

151-
def apply(tree: Tree): Aligned = tree match {
152-
case Apply(fn, args) => apply(fn, args)
153-
case UnApply(fn, args) => apply(fn, args)
152+
def apply(context: Context, tree: Tree): Aligned = tree match {
153+
case Apply(fn, args) => apply(context, fn, args)
154+
case UnApply(fn, args) => apply(context, fn, args)
154155
}
155156
}
156157
}

src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ trait PatternTypers {
309309
// the union of the expected type and the inferred type of the argument to unapply
310310
val glbType = glb(ensureFullyDefined(pt) :: unapplyArg.tpe_* :: Nil)
311311
val wrapInTypeTest = canRemedy && !(fun1.symbol.owner isNonBottomSubClass ClassTagClass)
312-
val formals = patmat.alignPatterns(fun1, args).unexpandedFormals
312+
val formals = patmat.alignPatterns(context.asInstanceOf[analyzer.Context], fun1, args).unexpandedFormals
313313
val args1 = typedArgsForFormals(args, formals, mode)
314314
val result = UnApply(fun1, args1) setPos tree.pos setType glbType
315315

test/files/pos/t8719.check

Whitespace-only changes.

test/files/pos/t8719/Macros_1.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import scala.language.experimental.macros
2+
import scala.reflect.macros.TypecheckException
3+
import scala.reflect.macros.whitebox.Context
4+
5+
object Macros {
6+
def typecheck_impl(c: Context)(code: c.Expr[String]): c.Expr[Option[String]] = {
7+
import c.universe._
8+
9+
val Expr(Literal(Constant(codeStr: String))) = code
10+
11+
try {
12+
c.typecheck(c.parse(codeStr))
13+
c.Expr(q"None: Option[String]")
14+
} catch {
15+
case e: TypecheckException =>
16+
c.Expr(q"Some(${ e.toString }): Option[String]")
17+
}
18+
}
19+
20+
def typecheck(code: String): Option[String] = macro typecheck_impl
21+
}

test/files/pos/t8719/Test_2.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
case class Foo(i: Int, c: Char)
2+
3+
object Bar {
4+
def unapply(foo: Foo): Option[(Int, Char)] = Some((foo.i, foo.c))
5+
}
6+
7+
object Test extends App {
8+
println(Macros.typecheck("val Foo(x, y, z) = Foo(1, 'a')"))
9+
println(Macros.typecheck("val Bar(x, y, z) = Foo(1, 'a')"))
10+
}

0 commit comments

Comments
 (0)