diff options
author | Paul Phillips <paulp@improving.org> | 2013-02-09 19:30:30 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-02-09 19:41:08 -0800 |
commit | 747f6a8d24c628d05ab3acea0b95a82d04a71df3 (patch) | |
tree | 435f44dd8856c91e1ac4ba1da86d74178e0a3586 /src/compiler/scala/tools/nsc/typechecker/Infer.scala | |
parent | ce32c1af462de7d7c6b90efd56217e202a18d1e6 (diff) | |
parent | 81d8f9d3da656cfb05f125ba7cf70ca51a477240 (diff) | |
download | scala-747f6a8d24c628d05ab3acea0b95a82d04a71df3.tar.gz scala-747f6a8d24c628d05ab3acea0b95a82d04a71df3.tar.bz2 scala-747f6a8d24c628d05ab3acea0b95a82d04a71df3.zip |
Merge commit '81d8f9d3da' into merge-210
* excluded from merge:
[nomerge] SI-6667 Demote a new ambiguity error to a lint warning.
Revert "SI-6422: add missing Fractional and Integral alias in scala package"
[backport] SI-6482, lost bounds in extension methods.
* commit '81d8f9d3da': (31 commits)
reflecting @throws defined in Scala code
pullrequest feedback
SI-5833 Fixes tail-of-Nil problem in RefinedType#normalizeImpl
SI-6017 Scaladoc: Show all letters without dangling links
SI-6017 Generate Scaladoc's index links in Scala side
SI-5313 Minor code cleanup for store clobbering
SI-5313 Test clobbers on the back edge of a loop
SI-7033 Be symful when creating factory methods.
SI-7022 Additional test case for value class w. bounds
SI-7039 unapplySeq result type independent of subpattern count
evicts javac-artifacts.jar
SI-7008 @throws annotations are now populated in reflect
Fix SI-6578. Deprecated `askType` because of possible race conditions in type checker.
SI-7029 - Make test more robust
SI-7029 - Makes sure that uncaught exceptions are propagated to the UEH for the global ExecutionContext
SI-6941 tests
SI-6686 drop valdef unused in flatMapCond's block
...
Conflicts:
src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
src/reflect/scala/reflect/internal/Definitions.scala
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Infer.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 70 |
1 files changed, 42 insertions, 28 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 27f157e3a6..0207c841d2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -75,20 +75,31 @@ trait Infer extends Checkable { * @throws TypeError when the unapply[Seq] definition is ill-typed * @returns (null, null) when the expected number of sub-patterns cannot be satisfied by the given extractor * - * From the spec: + * This is the spec currently implemented -- TODO: update it. + * * 8.1.8 ExtractorPatterns * * An extractor pattern x(p1, ..., pn) where n ≥ 0 is of the same syntactic form as a constructor pattern. * However, instead of a case class, the stable identifier x denotes an object which has a member method named unapply or unapplySeq that matches the pattern. - * An unapply method in an object x matches the pattern x(p1, ..., pn) if it takes exactly one argument and one of the following applies: * - * n = 0 and unapply’s result type is Boolean. + * An `unapply` method with result type `R` in an object `x` matches the + * pattern `x(p_1, ..., p_n)` if it takes exactly one argument and, either: + * - `n = 0` and `R =:= Boolean`, or + * - `n = 1` and `R <:< Option[T]`, for some type `T`. + * The argument pattern `p1` is typed in turn with expected type `T`. + * - Or, `n > 1` and `R <:< Option[Product_n[T_1, ..., T_n]]`, for some + * types `T_1, ..., T_n`. The argument patterns `p_1, ..., p_n` are + * typed with expected types `T_1, ..., T_n`. + * + * An `unapplySeq` method in an object `x` matches the pattern `x(p_1, ..., p_n)` + * if it takes exactly one argument and its result type is of the form `Option[S]`, + * where either: + * - `S` is a subtype of `Seq[U]` for some element type `U`, (set `m = 0`) + * - or `S` is a `ProductX[T_1, ..., T_m]` and `T_m <: Seq[U]` (`m <= n`). * - * n = 1 and unapply’s result type is Option[T], for some type T. - * the (only) argument pattern p1 is typed in turn with expected type T + * The argument patterns `p_1, ..., p_n` are typed with expected types + * `T_1, ..., T_m, U, ..., U`. Here, `U` is repeated `n-m` times. * - * n > 1 and unapply’s result type is Option[(T1, ..., Tn)], for some types T1, ..., Tn. - * the argument patterns p1, ..., pn are typed in turn with expected types T1, ..., Tn */ def extractorFormalTypes(pos: Position, resTp: Type, nbSubPats: Int, unappSym: Symbol): (List[Type], List[Type]) = { val isUnapplySeq = unappSym.name == nme.unapplySeq @@ -100,31 +111,34 @@ trait Infer extends Checkable { else toRepeated } + // empty list --> error, otherwise length == 1 + lazy val optionArgs = resTp.baseType(OptionClass).typeArgs + // empty list --> not a ProductN, otherwise product element types + def productArgs = getProductArgs(optionArgs.head) + val formals = - if (nbSubPats == 0 && booleanExtractor && !isUnapplySeq) Nil - else resTp.baseType(OptionClass).typeArgs match { - case optionTArg :: Nil => - def productArgs = getProductArgs(optionTArg) + // convert Seq[T] to the special repeated argument type + // so below we can use formalTypes to expand formals to correspond to the number of actuals + if (isUnapplySeq) { + if (optionArgs.nonEmpty) + productArgs match { + case Nil => List(seqToRepeatedChecked(optionArgs.head)) + case normalTps :+ seqTp => normalTps :+ seqToRepeatedChecked(seqTp) + } + else throw new TypeError(s"result type $resTp of unapplySeq defined in ${unappSym.fullLocationString} does not conform to Option[_]") + } else { + if (booleanExtractor && nbSubPats == 0) Nil + else if (optionArgs.nonEmpty) if (nbSubPats == 1) { - if (isUnapplySeq) List(seqToRepeatedChecked(optionTArg)) - else { - val productArity = productArgs.size - if (productArity > 1 && settings.lint.value) - global.currentUnit.warning(pos, s"extractor pattern binds a single value to a Product${productArity} of type ${optionTArg}") - List(optionTArg) - } + val productArity = productArgs.size + if (productArity > 1 && settings.lint.value) + global.currentUnit.warning(pos, s"extractor pattern binds a single value to a Product${productArity} of type ${optionArgs.head}") + optionArgs } // TODO: update spec to reflect we allow any ProductN, not just TupleN - else productArgs match { - case Nil if isUnapplySeq => List(seqToRepeatedChecked(optionTArg)) - case tps if isUnapplySeq => tps.init :+ seqToRepeatedChecked(tps.last) - case tps => tps - } - case _ => - if (isUnapplySeq) - throw new TypeError(s"result type $resTp of unapplySeq defined in ${unappSym.owner+unappSym.owner.locationString} not in {Option[_], Some[_]}") - else - throw new TypeError(s"result type $resTp of unapply defined in ${unappSym.owner+unappSym.owner.locationString} not in {Boolean, Option[_], Some[_]}") + else productArgs + else + throw new TypeError(s"result type $resTp of unapply defined in ${unappSym.fullLocationString} does not conform to Option[_] or Boolean") } // for unapplySeq, replace last vararg by as many instances as required by nbSubPats |