summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/Logic.scala9
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala23
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala24
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala12
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala20
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala9
-rw-r--r--src/reflect/scala/reflect/internal/TreeInfo.scala3
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala19
-rw-r--r--test/files/neg/t7185.check7
-rw-r--r--test/files/neg/t7185.scala3
-rw-r--r--test/files/pos/t7126.scala11
-rw-r--r--test/files/run/t7185.check34
-rw-r--r--test/files/run/t7185.scala12
-rw-r--r--test/files/run/t7214.scala57
17 files changed, 200 insertions, 51 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 703922b20a..55e78df4b7 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -2144,8 +2144,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
val start = st.pop()
seen ::= LocVarEntry(lv, start, end)
case _ =>
- // TODO SI-6049
- getCurrentCUnit().warning(iPos, "Visited SCOPE_EXIT before visiting corresponding SCOPE_ENTER. SI-6049")
+ // TODO SI-6049 track down the cause for these.
+ debugwarn(s"$iPos: Visited SCOPE_EXIT before visiting corresponding SCOPE_ENTER. SI-6191")
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
index 4fc71a7410..4be84d8ca5 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/Logic.scala
@@ -287,7 +287,11 @@ trait Logic extends Debugging {
def findModelFor(f: Formula): Model
def findAllModelsFor(f: Formula): List[Model]
}
+}
+// naive CNF translation and simple DPLL solver
+trait SimpleSolver extends Logic {
+ import PatternMatchingStats._
trait CNF extends PropositionalLogic {
/** Override Array creation for efficiency (to not go through reflection). */
@@ -397,7 +401,8 @@ trait Logic extends Debugging {
}
}
- trait DPLLSolver extends CNF {
+ // simple solver using DPLL
+ trait Solver extends CNF {
// a literal is a (possibly negated) variable
def Lit(sym: Sym, pos: Boolean = true) = new Lit(sym, pos)
class Lit(val sym: Sym, val pos: Boolean) {
@@ -516,7 +521,7 @@ trait Logic extends Debugging {
}
}
-trait ScalaLogic extends Logic { self: PatternMatching =>
+trait ScalaLogic extends Interface with Logic with TreeAndTypeAnalysis {
trait TreesAndTypesDomain extends PropositionalLogic with CheckableTreeAndTypeAnalysis {
type Type = global.Type
type Tree = global.Tree
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
index 86eb3c9666..ceb4d26a0b 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala
@@ -125,7 +125,7 @@ trait TreeAndTypeAnalysis extends Debugging {
}
}
-trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
+trait MatchAnalysis extends TreeAndTypeAnalysis with ScalaLogic with MatchTreeMaking {
import PatternMatchingStats._
import global.{Tree, Type, Symbol, CaseDef, atPos,
Select, Block, ThisType, SingleType, NoPrefix, NoType, definitions, needsOuterTest,
@@ -141,7 +141,7 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
* Represent a match as a formula in propositional logic that encodes whether the match matches (abstractly: we only consider types)
*
*/
- trait TreeMakerApproximation extends TreeMakers with PropositionalLogic with TreesAndTypesDomain with CheckableTreeAndTypeAnalysis { self: CodegenCore =>
+ trait TreeMakerApproximation extends TreeMakers with TreesAndTypesDomain {
object Test {
var currId = 0
}
@@ -348,7 +348,7 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
}
}
- trait SymbolicMatchAnalysis extends TreeMakerApproximation { self: CodegenCore =>
+ trait MatchAnalyses extends TreeMakerApproximation {
def uncheckedWarning(pos: Position, msg: String) = global.currentUnit.uncheckedWarning(pos, msg)
def warn(pos: Position, ex: AnalysisBudget.Exception, kind: String) = uncheckedWarning(pos, s"Cannot check match for $kind.\n${ex.advice}")
@@ -498,7 +498,7 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
// a way to construct a value that will make the match fail: a constructor invocation, a constant, an object of some type)
class CounterExample {
- protected[SymbolicMatchAnalysis] def flattenConsArgs: List[CounterExample] = Nil
+ protected[MatchAnalyses] def flattenConsArgs: List[CounterExample] = Nil
def coveredBy(other: CounterExample): Boolean = this == other || other == WildcardExample
}
case class ValueExample(c: ValueConst) extends CounterExample { override def toString = c.toString }
@@ -513,11 +513,11 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
}
}
case class ListExample(ctorArgs: List[CounterExample]) extends CounterExample {
- protected[SymbolicMatchAnalysis] override def flattenConsArgs: List[CounterExample] = ctorArgs match {
+ protected[MatchAnalyses] override def flattenConsArgs: List[CounterExample] = ctorArgs match {
case hd :: tl :: Nil => hd :: tl.flattenConsArgs
case _ => Nil
}
- protected[SymbolicMatchAnalysis] lazy val elems = flattenConsArgs
+ protected[MatchAnalyses] lazy val elems = flattenConsArgs
override def coveredBy(other: CounterExample): Boolean =
other match {
@@ -691,5 +691,16 @@ trait MatchAnalysis extends TreeAndTypeAnalysis { self: PatternMatching =>
// this is the variable we want a counter example for
VariableAssignment(scrutVar).toCounterExample()
}
+
+ def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): Unit = {
+ unreachableCase(prevBinder, cases, pt) foreach { caseIndex =>
+ reportUnreachable(cases(caseIndex).last.pos)
+ }
+ if (!unchecked) {
+ val counterExamples = exhaustive(prevBinder, cases, pt)
+ if (counterExamples.nonEmpty)
+ reportMissingCases(prevBinder.pos, counterExamples)
+ }
+ }
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala
index 273aebd71e..416bdf50f0 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala
@@ -17,7 +17,7 @@ import scala.reflect.internal.util.NoPosition
* We have two modes in which to emit trees: optimized (the default)
* and pure (aka "virtualized": match is parametric in its monad).
*/
-trait MatchCodeGen { self: PatternMatching =>
+trait MatchCodeGen extends Interface {
import PatternMatchingStats._
import global.{nme, treeInfo, definitions, gen, Tree, Type, Symbol, NoSymbol,
appliedType, NoType, MethodType, newTermName, Name,
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
index c14b4ebc3b..ebc2750a4d 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala
@@ -19,7 +19,7 @@ import scala.reflect.internal.util.NoPosition
*
* TODO: split out match analysis
*/
-trait MatchOptimization { self: PatternMatching =>
+trait MatchOptimization extends MatchTreeMaking with MatchAnalysis {
import PatternMatchingStats._
import global.{Tree, Type, Symbol, NoSymbol, CaseDef, atPos,
ConstantType, Literal, Constant, gen, EmptyTree,
@@ -205,7 +205,7 @@ trait MatchOptimization { self: PatternMatching =>
//// DCE
- trait DeadCodeElimination extends TreeMakers { self: CodegenCore =>
+ trait DeadCodeElimination extends TreeMakers {
// TODO: non-trivial dead-code elimination
// e.g., the following match should compile to a simple instanceof:
// case class Ident(name: String)
@@ -217,7 +217,7 @@ trait MatchOptimization { self: PatternMatching =>
}
//// SWITCHES -- TODO: operate on Tests rather than TreeMakers
- trait SwitchEmission extends TreeMakers with OptimizedMatchMonadInterface { self: CodegenCore =>
+ trait SwitchEmission extends TreeMakers with OptimizedMatchMonadInterface {
import treeInfo.isGuardedCase
abstract class SwitchMaker {
@@ -589,25 +589,11 @@ trait MatchOptimization { self: PatternMatching =>
}
}
-
-
-
trait MatchOptimizations extends CommonSubconditionElimination
with DeadCodeElimination
with SwitchEmission
- with OptimizedCodegen
- with SymbolicMatchAnalysis
- with DPLLSolver { self: TreeMakers =>
- override def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): (List[List[TreeMaker]], List[Tree]) = {
- unreachableCase(prevBinder, cases, pt) foreach { caseIndex =>
- reportUnreachable(cases(caseIndex).last.pos)
- }
- if (!unchecked) {
- val counterExamples = exhaustive(prevBinder, cases, pt)
- if (counterExamples.nonEmpty)
- reportMissingCases(prevBinder.pos, counterExamples)
- }
-
+ with OptimizedCodegen {
+ override def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): (List[List[TreeMaker]], List[Tree]) = {
val optCases = doCSE(prevBinder, doDCE(prevBinder, cases, pt), pt)
val toHoist = (
for (treeMakers <- optCases)
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
index 3ee9009116..23b33e9be6 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala
@@ -24,7 +24,7 @@ trait MatchTranslation { self: PatternMatching =>
repeatedToSeq, isRepeatedParamType, getProductArgs}
import global.analyzer.{ErrorUtils, formalTypes}
- trait MatchTranslator extends MatchMonadInterface { self: TreeMakers with CodegenCore =>
+ trait MatchTranslator extends TreeMakers {
import typer.context
// Why is it so difficult to say "here's a name and a context, give me any
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
index c9285f9229..51f21780b5 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala
@@ -18,7 +18,7 @@ import scala.reflect.internal.util.NoPosition
* The IR is mostly concerned with sequencing, substitution, and rendering all necessary conditions,
* mostly agnostic to whether we're in optimized/pure (virtualized) mode.
*/
-trait MatchTreeMaking { self: PatternMatching =>
+trait MatchTreeMaking extends MatchCodeGen with Debugging {
import PatternMatchingStats._
import global.{Tree, Type, Symbol, CaseDef, atPos, settings,
Select, Block, ThisType, SingleType, NoPrefix, NoType, needsOuterTest,
@@ -30,9 +30,9 @@ trait MatchTreeMaking { self: PatternMatching =>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// the making of the trees
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- trait TreeMakers extends TypedSubstitution { self: CodegenCore =>
- def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): (List[List[TreeMaker]], List[Tree]) =
- (cases, Nil)
+ trait TreeMakers extends TypedSubstitution with CodegenCore {
+ def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type): (List[List[TreeMaker]], List[Tree])
+ def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): Unit
def emitSwitch(scrut: Tree, scrutSym: Symbol, cases: List[List[TreeMaker]], pt: Type, matchFailGenOverride: Option[Tree => Tree], unchecked: Boolean): Option[Tree] =
None
@@ -550,7 +550,9 @@ trait MatchTreeMaking { self: PatternMatching =>
}) None
else matchFailGen
- val (cases, toHoist) = optimizeCases(scrutSym, casesNoSubstOnly, pt, unchecked)
+ analyzeCases(scrutSym, casesNoSubstOnly, pt, unchecked)
+
+ val (cases, toHoist) = optimizeCases(scrutSym, casesNoSubstOnly, pt)
val matchRes = codegen.matcher(scrut, scrutSym, pt)(cases map combineExtractors, synthCatchAll)
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala
index 38d148c915..0e5d3f4ea5 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala
@@ -34,13 +34,14 @@ import scala.reflect.internal.util.Position
* - recover GADT typing by locally inserting implicit witnesses to type equalities derived from the current case, and considering these witnesses during subtyping (?)
* - recover exhaustivity/unreachability of user-defined extractors by partitioning the types they match on using an HList or similar type-level structure
*/
-trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
+trait PatternMatching extends Transform with TypingTransformers
with Debugging
with Interface
with MatchTranslation
with MatchTreeMaking
with MatchCodeGen
with ScalaLogic
+ with SimpleSolver
with MatchAnalysis
with MatchOptimization {
import global._
@@ -76,15 +77,20 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
}
}
- class PureMatchTranslator(val typer: analyzer.Typer, val matchStrategy: Tree) extends MatchTranslator with TreeMakers with PureCodegen
- class OptimizingMatchTranslator(val typer: analyzer.Typer) extends MatchTranslator with TreeMakers with MatchOptimizations
+ class PureMatchTranslator(val typer: analyzer.Typer, val matchStrategy: Tree) extends MatchTranslator with PureCodegen {
+ def optimizeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type) = (cases, Nil)
+ def analyzeCases(prevBinder: Symbol, cases: List[List[TreeMaker]], pt: Type, unchecked: Boolean): Unit = {}
+ }
+
+ class OptimizingMatchTranslator(val typer: analyzer.Typer) extends MatchTranslator
+ with MatchOptimizations
+ with MatchAnalyses
+ with Solver
}
-trait HasGlobal {
+trait Debugging {
val global: Global
-}
-trait Debugging extends HasGlobal {
// TODO: the inliner fails to inline the closures to debug.patmat unless the method is nested in an object
object debug {
val printPatmat = global.settings.Ypatmatdebug.value
@@ -92,7 +98,7 @@ trait Debugging extends HasGlobal {
}
}
-trait Interface { self: ast.TreeDSL with HasGlobal =>
+trait Interface extends ast.TreeDSL {
import global.{newTermName, analyzer, Type, ErrorType, Symbol, Tree}
import analyzer.Typer
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 1781dc1932..5785fa620b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -229,8 +229,13 @@ trait Typers extends Adaptations with Tags {
new SubstWildcardMap(tparams).apply(tp)
case TypeRef(_, sym, _) if sym.isAliasType =>
val tp0 = tp.dealias
- val tp1 = dropExistential(tp0)
- if (tp1 eq tp0) tp else tp1
+ if (tp eq tp0) {
+ debugwarn(s"dropExistential did not progress dealiasing $tp, see SI-7126")
+ tp
+ } else {
+ val tp1 = dropExistential(tp0)
+ if (tp1 eq tp0) tp else tp1
+ }
case _ => tp
}
diff --git a/src/reflect/scala/reflect/internal/TreeInfo.scala b/src/reflect/scala/reflect/internal/TreeInfo.scala
index c7d2fa42d3..e96fcc90df 100644
--- a/src/reflect/scala/reflect/internal/TreeInfo.scala
+++ b/src/reflect/scala/reflect/internal/TreeInfo.scala
@@ -101,7 +101,8 @@ abstract class TreeInfo {
// However, before typing, applications of nullary functional values are also
// Apply(function, Nil) trees. To prevent them from being treated as pure,
// we check that the callee is a method.
- fn.symbol.isMethod && !fn.symbol.isLazy && isExprSafeToInline(fn)
+ // The callee might also be a Block, which has a null symbol, so we guard against that (SI-7185)
+ fn.symbol != null && fn.symbol.isMethod && !fn.symbol.isLazy && isExprSafeToInline(fn)
case Typed(expr, _) =>
isExprSafeToInline(expr)
case Block(stats, expr) =>
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 365e9a1682..f4befb1470 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -3161,12 +3161,19 @@ trait Types extends api.Types { self: SymbolTable =>
* ?TC[?T] <: Any
* }}}
*/
- def unifySimple = (
- (params.isEmpty || tp.typeSymbol == NothingClass || tp.typeSymbol == AnyClass) && {
+ def unifySimple = {
+ val sym = tp.typeSymbol
+ if (sym == NothingClass || sym == AnyClass) { // kind-polymorphic
+ // SI-7126 if we register some type alias `T=Any`, we can later end
+ // with malformed types like `T[T]` during type inference in
+ // `handlePolymorphicCall`. No such problem if we register `Any`.
+ addBound(sym.tpe)
+ true
+ } else if (params.isEmpty) {
addBound(tp)
true
- }
- )
+ } else false
+ }
/** Full case: involving a check of the form
* {{{
@@ -5257,7 +5264,9 @@ trait Types extends api.Types { self: SymbolTable =>
case _ =>
NoType
}
- patType match {
+ // See the test for SI-7214 for motivation for dealias. Later `treeCondStrategy#outerTest`
+ // generates an outer test based on `patType.prefix` with automatically dealises.
+ patType.dealias match {
case TypeRef(pre, sym, args) =>
val pre1 = maybeCreateDummyClone(pre, sym)
(pre1 ne NoType) && isPopulated(copyTypeRef(patType, pre1, sym, args), selType)
diff --git a/test/files/neg/t7185.check b/test/files/neg/t7185.check
new file mode 100644
index 0000000000..46f2cc797e
--- /dev/null
+++ b/test/files/neg/t7185.check
@@ -0,0 +1,7 @@
+t7185.scala:2: error: overloaded method value apply with alternatives:
+ (f: scala.xml.Node => Boolean)scala.xml.NodeSeq <and>
+ (i: Int)scala.xml.Node
+ cannot be applied to ()
+ <e></e>()
+ ^
+one error found
diff --git a/test/files/neg/t7185.scala b/test/files/neg/t7185.scala
new file mode 100644
index 0000000000..2f9284bc5f
--- /dev/null
+++ b/test/files/neg/t7185.scala
@@ -0,0 +1,3 @@
+object Test {
+ <e></e>()
+}
diff --git a/test/files/pos/t7126.scala b/test/files/pos/t7126.scala
new file mode 100644
index 0000000000..6720511e08
--- /dev/null
+++ b/test/files/pos/t7126.scala
@@ -0,0 +1,11 @@
+import language._
+
+object Test {
+ type T = Any
+ boom(???): Option[T] // SOE
+ def boom[CC[U]](t : CC[T]): Option[CC[T]] = None
+
+ // okay
+ foo(???): Option[Any]
+ def foo[CC[U]](t : CC[Any]): Option[CC[Any]] = None
+} \ No newline at end of file
diff --git a/test/files/run/t7185.check b/test/files/run/t7185.check
new file mode 100644
index 0000000000..f95910ba5f
--- /dev/null
+++ b/test/files/run/t7185.check
@@ -0,0 +1,34 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> import scala.tools.reflect.ToolBox
+import scala.tools.reflect.ToolBox
+
+scala> import scala.reflect.runtime.universe._
+import scala.reflect.runtime.universe._
+
+scala> object O { def apply() = 0 }
+defined object O
+
+scala> val ORef = reify { O }.tree
+ORef: reflect.runtime.universe.Tree = $read.O
+
+scala> val tree = Apply(Block(Nil, Block(Nil, ORef)), Nil)
+tree: reflect.runtime.universe.Apply =
+{
+ {
+ $read.O
+ }
+}()
+
+scala> {val tb = reflect.runtime.currentMirror.mkToolBox(); tb.typeCheck(tree): Any}
+res0: Any =
+{
+ {
+ $read.O.apply()
+ }
+}
+
+scala>
diff --git a/test/files/run/t7185.scala b/test/files/run/t7185.scala
new file mode 100644
index 0000000000..d9d913e78a
--- /dev/null
+++ b/test/files/run/t7185.scala
@@ -0,0 +1,12 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ override def code = """
+import scala.tools.reflect.ToolBox
+import scala.reflect.runtime.universe._
+object O { def apply() = 0 }
+val ORef = reify { O }.tree
+val tree = Apply(Block(Nil, Block(Nil, ORef)), Nil)
+{val tb = reflect.runtime.currentMirror.mkToolBox(); tb.typeCheck(tree): Any}
+"""
+}
diff --git a/test/files/run/t7214.scala b/test/files/run/t7214.scala
new file mode 100644
index 0000000000..ff1ea8082d
--- /dev/null
+++ b/test/files/run/t7214.scala
@@ -0,0 +1,57 @@
+// pattern matcher crashes here trying to synthesize an uneeded outer test.
+// no-symbol does not have an owner
+// at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:49)
+// at scala.tools.nsc.Global.abort(Global.scala:253)
+// at scala.reflect.internal.Symbols$NoSymbol.owner(Symbols.scala:3248)
+// at scala.reflect.internal.Symbols$Symbol.effectiveOwner(Symbols.scala:678)
+// at scala.reflect.internal.Symbols$Symbol.isDefinedInPackage(Symbols.scala:664)
+// at scala.reflect.internal.TreeGen.mkAttributedSelect(TreeGen.scala:188)
+// at scala.reflect.internal.TreeGen.mkAttributedRef(TreeGen.scala:124)
+// at scala.tools.nsc.ast.TreeDSL$CODE$.REF(TreeDSL.scala:308)
+// at scala.tools.nsc.typechecker.PatternMatching$TreeMakers$TypeTestTreeMaker$treeCondStrategy$.outerTest(PatternMatching.scala:1209)
+class Crash {
+ type Alias = C#T
+
+ val c = new C
+ val t = new c.T
+
+ // Crash via a Typed Pattern...
+ (t: Any) match {
+ case e: Alias =>
+ }
+
+ // ... or via a Typed Extractor Pattern.
+ object Extractor {
+ def unapply(a: Alias): Option[Any] = None
+ }
+ (t: Any) match {
+ case Extractor() =>
+ case _ =>
+ }
+
+ // checking that correct outer tests are applied when
+ // aliases for path dependent types are involved.
+ val c2 = new C
+ type CdotT = c.T
+ type C2dotT = c2.T
+
+ val outerField = t.getClass.getDeclaredFields.find(_.getName contains ("outer")).get
+ outerField.setAccessible(true)
+
+ (t: Any) match {
+ case _: C2dotT =>
+ println(s"!!! wrong match. t.outer=${outerField.get(t)} / c2 = $c2") // this matches on 2.10.0
+ case _: CdotT =>
+ case _ =>
+ println(s"!!! wrong match. t.outer=${outerField.get(t)} / c = $c")
+ }
+}
+
+class C {
+ class T
+}
+
+object Test extends App {
+ new Crash
+}
+