summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/PatternTypers.scala
Commit message (Collapse)AuthorAgeFilesLines
* Avoid name table pollution with fresh existentialsJason Zaugg2016-11-081-1/+1
| | | | | | | | | | | | | | | During large compilations runs, the large numbers of globally unique fresh names for existentials captured from prefixes of `asSeenFrom`. is a) somewhat wasteful (all these names are interned in the name table) , and, b) form a pathological case for the current implementation of `Names#hashValue`, which leads to overfull hash-buckets in the name table. `hashValue` should probably be improved, but my attempts to do so have shown a small performance degradation in some benchmarks. So this commit starts by being more frugal with these names, only uniquely naming within an `asSeenFrom` operation. References scala/scala-dev#246
* SD-167 Fine tuning constructor pattern translationJason Zaugg2016-07-251-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - Avoid calling NoSymbol.owner when checking whether we're dealing with a case class constructor pattern or a general extractor. Tested manually with the test case in the ticket, no more output is produced under `-Xdev`. - Be more conservative about the conversion to a case class pattern: rather than looking just at the type of the pattern tree, also look at the tree itself to ensure its safe to elide. This change is analagous to SI-4859, which restricted rewrites of case apply calls to case constructors. I've manually tested that case class patterns are still efficiently translated: ``` object Test { def main(args: Array[String]) { Some(1) match { case Some(x) => } } } ``` ``` % qscalac -Xprint:patmat sandbox/test.scala [[syntax trees at end of patmat]] // test.scala package <empty> { object Test extends scala.AnyRef { def <init>(): Test.type = { Test.super.<init>(); () }; def main(args: Array[String]): Unit = { case <synthetic> val x1: Some[Int] = scala.Some.apply[Int](1); case4(){ if (x1.ne(null)) matchEnd3(()) else case5() }; case5(){ matchEnd3(throw new MatchError(x1)) }; matchEnd3(x: Unit){ x } } } } ```
* SI-9567 Fix pattern match on 23+ param, method local case classJason Zaugg2015-11-251-1/+1
| | | | | | | | | | | | | | | | | | | | | | Typechecking constructor patterns of method local case classes was only working because of the existence of the unapply method in the companion, which is used if navigation to the case class companion object fails. We now support defintion of, and pattern matching on, case classes with more than 22 parameters. These have no `unapply` method in the companion, as we don't have a large enough tuple type to return. So for such case classes, the fallback that we inadvertently relied on would no longer save us, and we'd end up with a compile error advising that the identifier in the constructor pattern was neither a case class nor an extractor. This is due to the propensity of `Symbol#companionXxx` to return `NoSymbol` when in the midst of typechecking. That method should only be relied upon after typechecking. During typechecking, `Namers#companionSymbolOf` should be used instead, which looks in the scopes of enclosing contexts for symbol companionship. That's what I've done in this commit.
* Improve method names (m-o)Janek Bogucki2015-06-281-2/+2
|
* Removed warningsEECOLOR2015-03-261-1/+1
| | | | | | | | | | | | | | | | | | | | | - Added `since` to deprecation statement - Added unit to parameter list - Removed usage of deprecated method polyType - Replaced deprecated `debugwarn` with `devWarning` - Changed switch statement to if else in order to remove a warning - Switched implementation of `init` and `processOptions` to prevent warning - Replaced deprecated `Console.readLine` with `scala.io.StdIn.readLine` - Replaced deprecated `startOrPoint` with `start` - Replaced deprecated `tpe_=` with `setType` - Replaced deprecated `typeCheck` with `typecheck` - Replaced deprecated `CompilationUnit.warning` with `typer.context.warning` - Replaced deprecated `scala.tools.nsc.util.ScalaClassLoader` with `scala.reflect.internal.util.ScalaClassLoader` - Replaced deprecated `scala.tools.ListOfNil` with `scala.reflect.internal.util.ListOfNil` - Replaced deprecated `scala.tools.utils.ScalaClassLoader` with `scala.reflect.internal.util.ScalaClassLoader` - Replaced deprecated `emptyValDef` with `noSelfType` - In `BoxesRunTime` removed unused method and commented out unused values. Did not delete to keep a reference to the values. If they are deleted people might wonder why `1` and `2` are not used. - Replaced deprecated `scala.tools.nsc.util.AbstractFileClassLoader` with `scala.reflect.internal.util.AbstractFileClassLoader`
* Fix many typos in docs and commentsmpociecha2014-12-141-1/+1
| | | | | | | | | | | | | This commit corrects many typos found in scaladocs, comments and documentation. It should reduce a bit number of PRs which fix one typo. There are no changes in the 'real' code except one corrected name of a JUnit test method and some error messages in exceptions. In the case of typos in other method or field names etc., I just skipped them. Obviously this commit doesn't fix all existing typos. I just generated in IntelliJ the list of potential typos and looked through it quickly.
* This ensures that typechecking custom unapplications in silent modeEugene Burmako2014-09-111-1/+1
| | | | | | doesn't leak uncatchable errors. Interestingly enough, the problem only manifested itself for custom unapply methods, not for synthetic ones generated for case classes.
* Remove another redundant forwarderAdriaan Moors2014-07-171-1/+1
| | | | | | | | | | In this case, `infer.issue -> context.issue`. Forwarders are dead weight that cause bit rot. They tend to acquire functionality, clutter their defining interface and dilute the purpose of the method they forward to.
* SI-5900 Fix pattern inference regressionJason Zaugg2014-02-121-3/+5
| | | | | | | | | | | | | | | | | | | | This commit does not close SI-5900. It only addresses a regression in 2.11 prereleases caused by SI-7886. The fix for SI-7886 was incomplete (as shown by the last commit) and incorrect (as shown by the regression in pos/t5900a.scala and the fact it ended up inferring type parameters.) I believe that the key to fixing this problem will be unifying the inference of case class constructor patterns and extractor patterns. I've explored that idea: https://gist.github.com/retronym/7704153 https://github.com/retronym/scala/compare/ticket/5900 But didn't quite get there.
* SI-7850 CCE in patmat with invalid isEmpty.Paul Phillips2013-12-151-5/+19
| | | | | | | | Name-based pattern matcher needed some hardening against unapply methods with the right name but wrong types. Only isEmpty methods which return Boolean are acceptable. Catching it directly rather than indirectly also allowed for better error messages.
* SI-7897, SI-6675 improves name-based patmatPaul Phillips2013-12-151-114/+8
| | | | | | | | | | | | | | | | | | | This emerges from a recent attempt to eliminate pattern matcher related duplication and to bake the scalac-independent logic out of it. I had in mind something a lot cleaner, but it was a whole lot of work to get it here and I can take it no further. Key file to admire is PatternExpander.scala, which should provide a basis for some separation of concerns. The bugs addressed are a CCE involving Tuple1 and an imprecise warning regarding multiple pattern crushing. Editorial: auto-tupling unapply results was a terrible idea which should never have escaped from the crib. It is tantamount to purposely throwing type safety down the toilet in the very place where people need type safety the most. See SI-6111 and SI-6675 for some other comments.
* Provide a way for unapply macro to obtain a list of subpattensDen Shabalin2013-12-101-1/+3
| | | | | | | | | | | | | | | | | | This commit introduces internal attachment that allows unapply macros to be aware of their sub patterns and tweak their expansion depending on that info. At the moment this is not possible due to the way pattern macros are expanded: case MacroPat(inner1, inner2) => ... During type checking this will expand as MacroPat.unapply(<unapply-dummy>) Meaning that macro can’t see inner1 and inner2 in it’s macroApplication. To circumvent this we attach that info as an attachment to the dummy.
* blackbox restriction #4: can't customize pattern matchingEugene Burmako2013-11-121-3/+4
| | | | | | When an application of a blackbox macro is used as an extractor in a pattern match, it triggers an unconditional compiler error, preventing customizations of pattern matching implemented with macros.
* decrease duplication of fresh* function definitionsDen Shabalin2013-10-181-1/+1
| | | | | | | | This commit extracts out freshTermName and freshTypeName to the top-level with implicit fresh name creator argument. This will let to refactor out more methods out of tree builder into treegen that are dependent on fresh name generator. We also save quite a bit of boilerplate by not having to redefined fresh functions all over the place.
* Merge pull request #3005 from paulp/pr/7886Paul Phillips2013-10-031-16/+25
|\ | | | | SI-7886 unsoundness in pattern matcher.
| * SI-6680 unsoundness in gadt typing.Paul Phillips2013-10-011-20/+23
| | | | | | | | | | | | | | Introduces -Xstrict-inference to deal with the significant gap between soundness and what presently compiles. I'm hopeful that it's TOO strict, because it finds e.g. 75 errors compiling immutable/IntMap.scala, but it might be that bad.
| * SI-7886 unsoundness in pattern matcher.Paul Phillips2013-10-011-1/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I tracked down what was behind the issue described here: // TODO: fix the illegal type bound in pos/t602 -- type inference // messes up before we get here: /*override def equals(x$1: Any): Boolean = ... // Span[Any] --> Any is not a legal type argument for Span! val o5: Option[com.mosol.sl.Span[Any]] = */ ...which led straight to the unsoundness seen in neg/t7886. It is dangerous to have an expected type of "Any" because the type system will blithely ignore kind errors, since "Any" can absorb anything. The consequence in this instance was that inferring the case constructor for a type like Foo[T <: Bound] if done with expected type Any, this would come up with Foo[Any]. I altered it to use expected type Foo[T], which lets the dummy type parameter survive to carry the bound forward and restores sense to the inference. The before/after output for -Xprint:patmat on pos/t602.scala is: 15c15 < if (x1.isInstanceOf[com.mosol.sl.Span[Any]]) --- > if (x1.isInstanceOf[com.mosol.sl.Span[K]]) 17c17 < <synthetic> val x2: com.mosol.sl.Span[Any] = \ (x1.asInstanceOf[com.mosol.sl.Span[Any]]: com.mosol.sl.Span[Any]); --- > <synthetic> val x2: com.mosol.sl.Span[K] = \ (x1.asInstanceOf[com.mosol.sl.Span[K]]: com.mosol.sl.Span[K]); 19,20c19,20 < val low$0: Option[Any] = x2.low; < val high$0: Option[Any] = x2.high; --- > val low$0: Option[K] = x2.low; > val high$0: Option[K] = x2.high; A file in the library depended (needlessly) on the unsoundness. It was easy to fix but reminds us this may affect existing code.
* | Removing unused code.Paul Phillips2013-10-021-11/+0
|/ | | | | | | Most of this was revealed via -Xlint with a flag which assumes closed world. I can't see how to check the assumes-closed-world code in without it being an ordeal. I'll leave it in a branch in case anyone wants to finish the long slog to the merge.
* SI-7643 Enable newPatternMatching in interactive.Jason Zaugg2013-09-061-6/+0
| | | | | | | | | | Without it, the enclosed test fails with: ArrayBuffer(Problem(RangePosition(partial-fun/src/PartialFun.scala, 62, 62, 77),type mismatch; found : Int => Int required: PartialFunction[Int,Int],2)) And with that, we can remove this option altogether.
* Logging cleanup.Paul Phillips2013-08-251-5/+1
| | | | | | | | | | | | | | Reduced the amount of extraneous logging noise at the default logging level. Was brought to my usual crashing halt by the discovery of identical logging statements throughout GenASM and elsewhere. I'm supposing the reason people so grossly underestimate the cost of such duplication is that most of the effects are in things which don't happen, aka "silent evidence". An example of a thing which isn't happening is the remainder of this commit, which exists only in parallel universes.
* Refined name-based patmat methods.Paul Phillips2013-08-181-16/+24
| | | | | | | | This fleshes out some of the slightly unfinished corners of the adventure, especially for unapplySeq. There's still an unhealthy amount of duplication and a paucity of specification, but I think it's in eminently good shape for a milestone.
* SI-5903 extractor macrosEugene Burmako2013-08-181-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Establishes a pattern that can be used to implement extractor macros that give the programmer control over signatures of unapplications at compile-time. === The pattern === In a nutshell, given an unapply method (for simplicity, in this example the scrutinee is of a concrete type, but it's also possible to have the extractor be polymorphic, as demonstrated in the tests): ``` def unapply(x: SomeType) = ??? ``` One can write a macro that generates extraction signatures for unapply on per-call basis, using the target of the calls (c.prefix) and the type of the scrutinee (that comes with x), and then communicate these signatures to the typechecker. For example, here's how one can define a macro that simply passes the scrutinee back to the pattern match (for information on how to express signatures that involve multiple extractees, visit https://github.com/scala/scala/pull/2848). ``` def unapply(x: SomeType) = macro impl def impl(c: Context)(x: c.Tree) = { q""" new { class Match(x: SomeType) { def isEmpty = false def get = x } def unapply(x: SomeType) = new Match(x) }.unapply($x) """ } ``` In addition to the matcher, which implements domain-specific matching logic, there's quite a bit of boilerplate here, but every part of it looks necessary to arrange a non-frustrating dialogue with the typer. Maybe something better can be done in this department, but I can't see how, without introducing modifications to the typechecker. Even though the pattern uses structural types, somehow no reflective calls are being generated (as verified by -Xlog-reflective-calls and then by manual examination of the produced code). That's a mystery to me, but that's also good news, since that means that extractor macros aren't going to induce performance penalties. Almost. Unfortunately, I couldn't turn matchers into value classes because one can't declare value classes local. Nevertheless, I'm leaving a canary in place (neg/t5903e) that will let us know once this restriction is lifted. === Use cases === In particular, the pattern can be used to implement shapeshifting pattern matchers for string interpolators without resorting to dirty tricks. For example, quasiquote unapplications can be unhardcoded now: ``` def doTypedApply(tree: Tree, fun0: Tree, args: List[Tree], ...) = { ... fun.tpe match { case ExtractorType(unapply) if mode.inPatternMode => // this hardcode in Typers.scala is no longer necessary if (unapply == QuasiquoteClass_api_unapply) macroExpandUnapply(...) else doTypedUnapply(tree, fun0, fun, args, mode, pt) } } ``` Rough implementation strategy here would involve writing an extractor macro that destructures c.prefix, analyzes parts of StringContext and then generates an appropriate matcher as outlined above. === Implementation details === No modifications to core logic of typer or patmat are necessary, as we're just piggybacking on https://github.com/scala/scala/pull/2848. The only minor change I introduced is a guard against misbehaving extractor macros that don't conform to the pattern (e.g. expand into blocks or whatever else). Without the guard we'd crash with an NPE, with the guard we get a sane compilation error.
* Pattern matcher: extractors become name-based.Paul Phillips2013-08-171-220/+198
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | An extractor is no longer required to return Option[T], and can instead return anything which directly contains methods with these signatures: def isEmpty: Boolean def get: T If the type of get contains methods with the names of product selectors (_1, _2, etc.) then the type and arity of the extraction is inferred from the type of get. If it does not contain _1, then it is a single value extractor analogous like Option[T]. This has significant benefits and opens new territory: - an AnyVal based Option-like class can be used which leverages null as None, and no allocations are necessary - for primitive types the benefit is squared (see below) - the performance difference between case classes and extractors should now be largely eliminated - this in turn allows us to recapture great swaths of memory which are currently squandered (e.g. every TypeRef has fields for pre and args, even though these are more than half the time NoPrefix and Nil) Here is a primitive example: final class OptInt(val x: Int) extends AnyVal { def get: Int = x def isEmpty = x == Int.MinValue // or whatever is appropriate } // This boxes TWICE: Int => Integer => Some(Integer) def unapply(x: Int): Option[Int] // This boxes NONCE def unapply(x: Int): OptInt As a multi-value example, after I contribute some methods to TypeRef: def isEmpty = false def get = this def _1 = pre def _2 = sym def _3 = args Then it's extractor becomes def unapply(x: TypeRef) = x Which, it need hardly be said, involves no allocations.
* Introduced classes to encapsulate extractor info.Paul Phillips2013-08-171-0/+123
| | | | To be put to use in a commit shortly to follow.
* Stylistic cleanups in patmat.Paul Phillips2013-08-171-11/+13
| | | | Should be behaviorally neutral.
* Move most of Typers#Typer#typedTyped into PatternTypers.Paul Phillips2013-08-171-0/+43
| | | | | | Again moving pattern-typing logic out of Typers. You can tell I like writing Typers#Typer#typedTyped.
* Pulled pattern typing methods from Typers.Paul Phillips2013-08-171-0/+319
To the extent possible this commit is purely the extraction of those methods into the newly created PatternTypers trait. The slicing and dicing of those methods will follow shortly.