diff options
Diffstat (limited to 'src/compiler')
5 files changed, 39 insertions, 22 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala index 61cdb63ac9..e1e26cd8c9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala @@ -141,7 +141,7 @@ trait ContextErrors { } issueNormalTypeError(tree, "stable identifier required, but "+tree+" found." + ( - if (isStableExceptVolatile(tree)) addendum else "")) + if (treeInfo.hasVolatileType(tree)) addendum else "")) setError(tree) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 541d60c16d..55f144da13 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1342,13 +1342,16 @@ trait Namers extends MethodSynthesis { private def importSig(imp: Import) = { val Import(expr, selectors) = imp val expr1 = typer.typedQualifier(expr) - typer checkStable expr1 + if (expr1.symbol != null && expr1.symbol.isRootPackage) RootImportError(imp) if (expr1.isErrorTyped) ErrorType else { + if (!treeInfo.isStableIdentifierPattern(expr1)) + typer.TyperErrorGen.UnstableTreeError(expr1) + val newImport = treeCopy.Import(imp, expr1, selectors).asInstanceOf[Import] checkSelectors(newImport) transformed(imp) = newImport diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index c08aa7e39f..ecbc471fbe 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -202,7 +202,7 @@ trait NamesDefaults { self: Analyzer => if (module == NoSymbol) None else { val ref = atPos(pos.focus)(gen.mkAttributedRef(pre, module)) - if (module.isStable && pre.isStable) // fixes #4524. the type checker does the same for + if (treeInfo.admitsTypeSelection(ref)) // fixes #4524. the type checker does the same for ref.setType(singleType(pre, module)) // typedSelect, it calls "stabilize" on the result. Some(ref) } diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 290ad76a1d..bbba786c0c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -511,7 +511,10 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } if (member.isStable && !otherTp.isVolatile) { - if (memberTp.isVolatile) + // (1.4), pt 2 -- member.isStable && memberTp.isVolatile started being possible after SI-6815 + // (before SI-6815, !symbol.tpe.isVolatile was implied by symbol.isStable) + // TODO: allow overriding when @uncheckedStable? + if (memberTp.isVolatile) overrideError("has a volatile type; cannot override a member with non-volatile type") else memberTp.dealiasWiden.resultType match { case rt: RefinedType if !(rt =:= otherTp) && !(checkedCombinations contains rt.parents) => 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) = { |