summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2013-05-16 14:58:09 -0700
committerAdriaan Moors <adriaan.moors@typesafe.com>2013-05-16 15:00:35 -0700
commitfada1ef6b315326ac0329d9e78951cfc95ad0eb0 (patch)
treea29fb94694bb033c33bfe7e8ec3be9534101fb53 /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parent97d5179127e02af39b19076e78e4b2bc099eef94 (diff)
downloadscala-fada1ef6b315326ac0329d9e78951cfc95ad0eb0.tar.gz
scala-fada1ef6b315326ac0329d9e78951cfc95ad0eb0.tar.bz2
scala-fada1ef6b315326ac0329d9e78951cfc95ad0eb0.zip
SI-6815 untangle isStable and hasVolatileType
`Symbol::isStable` is now independent of `Symbol::hasVolatileType`, so that we can allow stable identifiers that are volatile in ident patterns. This split is validated by SI-6815 and the old logic in RefChecks, which seems to assume this independence, and thus I don't think ever worked: ``` if (member.isStable && !otherTp.isVolatile) { if (memberTp.isVolatile) overrideError("has a volatile type; cannot override a member with non-volatile type") ``` Introduces `admitsTypeSelection` and `isStableIdentifierPattern` in treeInfo, and uses them instead of duplicating that logic all over the place. Since volatility only matters in the context of type application, `isStableIdentifierPattern` is used to check patterns (resulting in `==` checks) and imports.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala47
1 files changed, 29 insertions, 18 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 2de59056ef..45f67a4858 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -587,7 +587,7 @@ trait Typers extends Adaptations with Tags {
}
/** Post-process an identifier or selection node, performing the following:
- * 1. Check that non-function pattern expressions are stable
+ * 1. Check that non-function pattern expressions are stable (ignoring volatility concerns -- SI-6815)
* 2. Check that packages and static modules are not used as values
* 3. Turn tree type into stable type if possible and required by context.
* 4. Give getClass calls a more precise type based on the type of the target of the call.
@@ -602,16 +602,18 @@ trait Typers extends Adaptations with Tags {
if (tree.isErrorTyped) tree
else if (mode.inPatternNotFunMode && tree.isTerm) { // (1)
if (sym.isValue) {
- val tree1 = checkStable(tree)
- // A module reference in a pattern has type Foo.type, not "object Foo"
- if (sym.isModuleNotMethod) tree1 setType singleType(pre, sym)
- else tree1
+ if (tree.isErrorTyped) tree
+ else if (treeInfo.isStableIdentifierPattern(tree)) {
+ // A module reference in a pattern has type Foo.type, not "object Foo"
+ if (sym.isModuleNotMethod) tree setType singleType(pre, sym)
+ else tree
+ } else UnstableTreeError(tree)
}
else fail()
} else if ((mode & (EXPRmode | QUALmode)) == EXPRmode && !sym.isValue && !phase.erasedTypes) { // (2)
fail()
} else {
- if (sym.isStable && pre.isStable && !isByNameParamType(tree.tpe) &&
+ if (treeInfo.admitsTypeSelection(tree) &&
(isStableContext(tree, mode, pt) || sym.isModuleNotMethod))
tree.setType(singleType(pre, sym))
// To fully benefit from special casing the return type of
@@ -4442,6 +4444,7 @@ trait Typers extends Adaptations with Tags {
}
def normalTypedApply(tree: Tree, fun: Tree, args: List[Tree]) = {
+ // TODO: replace `fun.symbol.isStable` by `treeInfo.isStableIdentifierPattern(fun)`
val stableApplication = (fun.symbol ne null) && fun.symbol.isMethod && fun.symbol.isStable
val funpt = if (isPatternMode) pt else WildcardType
val appStart = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null
@@ -4744,16 +4747,20 @@ trait Typers extends Adaptations with Tags {
typedSelect(tree, qual1, nme.CONSTRUCTOR)
case _ =>
if (Statistics.canEnable) Statistics.incCounter(typedSelectCount)
- var qual1 = checkDead(typedQualifier(qual, mode))
- if (name.isTypeName) qual1 = checkStable(qual1)
+ val qualTyped = checkDead(typedQualifier(qual, mode))
+ val qualStableOrError =
+ if (qualTyped.isErrorTyped || !name.isTypeName || treeInfo.admitsTypeSelection(qualTyped))
+ qualTyped
+ else
+ UnstableTreeError(qualTyped)
val tree1 = // temporarily use `filter` and an alternative for `withFilter`
if (name == nme.withFilter)
- silent(_ => typedSelect(tree, qual1, name)) orElse { _ =>
- silent(_ => typed1(Select(qual1, nme.filter) setPos tree.pos, mode, pt)) match {
+ silent(_ => typedSelect(tree, qualStableOrError, name)) orElse { _ =>
+ silent(_ => typed1(Select(qualStableOrError, nme.filter) setPos tree.pos, mode, pt)) match {
case SilentResultValue(result2) =>
unit.deprecationWarning(
- tree.pos, "`withFilter' method does not yet exist on " + qual1.tpe.widen +
+ tree.pos, "`withFilter' method does not yet exist on " + qualStableOrError.tpe.widen +
", using `filter' method instead")
result2
case SilentTypeError(err) =>
@@ -4761,14 +4768,14 @@ trait Typers extends Adaptations with Tags {
}
}
else
- typedSelect(tree, qual1, name)
+ typedSelect(tree, qualStableOrError, name)
if (tree.isInstanceOf[PostfixSelect])
checkFeature(tree.pos, PostfixOpsFeature, name.decode)
if (tree1.symbol != null && tree1.symbol.isOnlyRefinementMember)
checkFeature(tree1.pos, ReflectiveCallsFeature, tree1.symbol.toString)
- if (qual1.hasSymbolWhich(_.isRootPackage)) treeCopy.Ident(tree1, name)
+ if (qualStableOrError.hasSymbolWhich(_.isRootPackage)) treeCopy.Ident(tree1, name)
else tree1
}
}
@@ -5161,12 +5168,16 @@ trait Typers extends Adaptations with Tags {
}
def typedSingletonTypeTree(tree: SingletonTypeTree) = {
- val ref1 = checkStable(
- context.withImplicitsDisabled(
+ val refTyped =
+ context.withImplicitsDisabled {
typed(tree.ref, EXPRmode | QUALmode | (mode & TYPEPATmode), AnyRefClass.tpe)
- )
- )
- tree setType ref1.tpe.resultType
+ }
+
+ if (!refTyped.isErrorTyped)
+ tree setType refTyped.tpe.resultType
+
+ if (treeInfo.admitsTypeSelection(refTyped)) tree
+ else UnstableTreeError(refTyped)
}
def typedSelectFromTypeTree(tree: SelectFromTypeTree) = {