summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker
diff options
context:
space:
mode:
authorHubert Plociniczak <hubert.plociniczak@epfl.ch>2011-09-23 14:22:13 +0000
committerHubert Plociniczak <hubert.plociniczak@epfl.ch>2011-09-23 14:22:13 +0000
commit1111b27d0eb95d69d7507291d242817a2dbe7e64 (patch)
treea93f609f79877a503d501e9278479a695dbca859 /src/compiler/scala/tools/nsc/typechecker
parent7dc4723db3b8d435a5596db9de3e0378e023c8df (diff)
downloadscala-1111b27d0eb95d69d7507291d242817a2dbe7e64.tar.gz
scala-1111b27d0eb95d69d7507291d242817a2dbe7e64.tar.bz2
scala-1111b27d0eb95d69d7507291d242817a2dbe7e64.zip
Back to square one.
Current design of error trees complicates the design of reflection library, and introduces sometimes unnecessary boilerplate and since I do not want to stall that work I am reverting all the changes related to error trees. A different design is currently under consideration but work will be done on separate branch on github. Revisions that got reverted: r25705, r25704 (partially), r25673, r25669, r25649, r25644, r25621, r25620, r25619 Review by odersky and extempore.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ErrorTrees.scala930
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala303
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala55
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala72
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala26
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala73
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala1462
12 files changed, 830 insertions, 2130 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 60e1a6c747..e3786c154f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -22,7 +22,6 @@ trait Analyzer extends AnyRef
with Unapplies
with NamesDefaults
with TypeDiagnostics
- with ErrorTrees
{
val global : Global
import global._
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 1764161866..c5304ca103 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -193,7 +193,7 @@ trait Contexts { self: Analyzer =>
c.retyping = this.retyping
c.openImplicits = this.openImplicits
registerContext(c.asInstanceOf[analyzer.Context])
- // debuglog("Created context: " + this + " ==> " + c)
+ debuglog("Created context: " + this + " ==> " + c)
c
}
@@ -283,12 +283,6 @@ trait Contexts { self: Analyzer =>
else throw new TypeError(pos, msg1)
}
-/*!!! def errorTree(pos: Position, msg: String): ErrorTree = {
- error(pos, msg)
- ErrorTree(msg) setPos pos
- }
- */
-
def warning(pos: Position, msg: String) = {
if (reportGeneralErrors) unit.warning(pos, msg)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/ErrorTrees.scala b/src/compiler/scala/tools/nsc/typechecker/ErrorTrees.scala
deleted file mode 100644
index 39d9d6b2ae..0000000000
--- a/src/compiler/scala/tools/nsc/typechecker/ErrorTrees.scala
+++ /dev/null
@@ -1,930 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package typechecker
-
-/**
- * @author Hubert Plociniczak
- * @version 1.0
- */
-
-import scala.collection.{ mutable, immutable }
-import scala.tools.util.StringOps.{ countElementsAsString, countAsString }
-
-trait ErrorTrees {
- self: Analyzer =>
-
- import global._
-
- trait ErrorTree extends AbsErrorTree {
- override def containsError() = true
- def emit(context: Context): Unit
- def emit(): Unit = emit(typer.context.asInstanceOf[Context])
- def exception: TypeError = null // Once we get rid of all thrown type errors (apart from cyclic), remove
- var reported = false
- override def tpe = ErrorType
-
- // Debugging option
- if (settings.errortrees.value)
- println("[ErrorTree instance] " + this.getClass)
- }
-
- trait ErrorPosAndMsg {
- def errMsg: String
- def errPos: Position
- def shouldEmit: Boolean
- def emit(context: Context): Unit
- }
- protected trait ContextError extends ErrorPosAndMsg { }
-
- trait ErrorTreeWithContext extends ErrorTree with ContextError {
- def shouldEmit = true
- def emit(context: Context) = if (shouldEmit) context.error(errPos, errMsg)
- }
-
- /** Traverses a tree, collecting subtrees for which the first argument is
- * defined. A given tree's children are traversed only if the keepTraversing
- * predicate returns true for that tree.
- */
- def pruningCollect[T](pf: PartialFunction[Tree, T])(keepTraversing: Tree => Boolean): Tree => List[T] = {
- class Collector extends Traverser {
- val trees = mutable.ListBuffer[T]()
- override def traverse(t: Tree) {
- if (pf.isDefinedAt(t))
- trees += pf(t)
- if (keepTraversing(t))
- super.traverse(t)
- }
- }
- tree => {
- val c = new Collector
- c traverse tree
- c.trees.toList
- }
- }
-
- def errorTreesFinder(tree: Tree): List[ErrorTree] =
- pruningCollect({ case e: ErrorTree if !e.reported => e })(!_.isInstanceOf[ErrorTree])(tree)
-
- def quickErrorTreeFinder(tree: Tree): ErrorTree = tree find (_.isInstanceOf[ErrorTree]) match {
- case Some(x: ErrorTree) => x
- case _ => NullErrorTree
- }
-
- protected abstract class TreeForwarder(forwardTo: Tree) extends Tree {
- override def pos = forwardTo.pos
- override def hasSymbol = forwardTo.hasSymbol
- override def symbol = forwardTo.symbol
- override def symbol_=(x: Symbol) = forwardTo.symbol = x
- }
- abstract class PositionedErrorTree(tree: Tree) extends ErrorTree with ErrorPosAndMsg {
- def errPos = tree.pos
- def shouldEmit = !tree.isErroneous
- def emit(context: Context) = if (shouldEmit) context.error(errPos, errMsg)
- }
- abstract class ContextErrorTree(tree: Tree) extends PositionedErrorTree(tree) with ContextError { }
- abstract class ErrorTreeForwarder(tree: Tree) extends TreeForwarder(tree) with ErrorTree with ErrorPosAndMsg {
- def errPos = tree.pos
- def shouldEmit = !tree.isErroneous
- def emit(context: Context) = if (shouldEmit) context.error(errPos, errMsg)
- }
- abstract class ContextErrorTreeForwarder(tree: Tree) extends ErrorTreeForwarder(tree) with ContextError { }
-
- // create trees for specific error trees
-
- trait TyperErrorTrees {
- self: Typer =>
-
- trait TypeErrorTrait extends ErrorTree with ErrorPosAndMsg {
- def errMsg = "type error" // not used
- def emit(context: Context) {
- reportTypeError(context, errPos, exception)
- }
- }
- abstract class TypeErrorTreeForwarder(tree: Tree) extends ErrorTreeForwarder(tree) with TypeErrorTrait {
- override def emit(context: Context) {
- super[TypeErrorTrait].emit(context)
- }
- }
-
- import infer.setError
-
- case class UnstableTreeError(tree: Tree) extends ErrorTreeForwarder(tree) {
- private def addendum = {
- // !!! unused
- // val tpe = tree.symbol.tpe match {
- // case PolyType(_, rtpe) => rtpe
- // case t => t
- // }
- "\n Note that "+tree.symbol+" is not stable because its type, "+tree.tpe+", is volatile."
- }
- def errMsg = (
- "stable identifier required, but "+tree+" found." + (
- if (isStableExceptVolatile(tree)) addendum else ""
- )
- )
- }
-
- case class NoImplicitFoundError(tree: Tree, param: Symbol) extends ContextErrorTreeForwarder(tree) {
- def errMsg = {
- val paramName = param.name
- val paramTp = param.tpe
- paramTp.typeSymbol match {
- case ImplicitNotFoundMsg(msg) => msg.format(paramName, paramTp)
- case _ =>
- "could not find implicit value for "+
- (if (paramName startsWith nme.EVIDENCE_PARAM_PREFIX) "evidence parameter of type "
- else "parameter "+paramName+": ")+paramTp
- }
- }
- }
-
- case class TypeErrorTree(tree: Tree, pt: Type, override val exception: TypeError) extends TypeErrorTreeForwarder(tree) { }
-
- case class AdaptToMemberWithArgsError(tree: Tree, override val exception: TypeError) extends TypeErrorTreeForwarder(tree) { }
-
- case class WithFilterError(tree: Tree, override val exception: TypeError) extends TypeErrorTreeForwarder(tree) {
- override def emit(context: Context) {
- super.emit(context)
- setError(tree)
- }
- }
-
- case class ParentTypesError(templ: Template, override val exception: TypeError) extends TypeErrorTrait {
- def errPos = templ.pos
- def shouldEmit = !templ.isErroneous
- override def emit(context: Context) {
- templ.tpe = null
- super.emit(context)
- }
- }
-
- // additional parentTypes errors
- case class ConstrArgsInTraitParentTpeError(arg: Tree, parent: Symbol) extends ContextErrorTree(arg) {
- def errMsg = parent + " is a trait; does not take constructor arguments"
- }
-
- case class MissingTypeArgumentsParentTpeError(supertpt: Tree) extends ContextErrorTree(supertpt) {
- def errMsg = "missing type arguments"
- }
-
- case class SilentTypeError(tree: Tree, override val exception: TypeError) extends TypeErrorTrait {
- def shouldEmit = false // !!! correct?
- def errPos = tree.pos
- }
-
- case class TypedApplyError(tree: Tree, override val exception: TypeError) extends TypeErrorTreeForwarder(tree) {
- override def pos = exception.pos
- }
-
- case class AssignmentTypedApplyError(tree: Tree) extends ContextErrorTreeForwarder(tree) {
- def errMsg = "reassignment to val"
- }
-
- // typedIdent
- case class AmbiguousIdentError(tree: Tree, name: Name, msg: String) extends ContextErrorTreeForwarder(tree) {
- def errMsg = "reference to " + name + " is ambiguous;\n" + msg
- }
-
- case class SymbolNotFound(tree: Tree, name: Name, owner: Symbol) extends ContextErrorTreeForwarder(tree) {
- def errMsg = "not found: "+decodeWithKind(name, owner)
- }
-
- // typedAppliedTypeTree
- case class AppliedTypeNoParametersError(tree: Tree, errTpe: Type) extends ErrorTreeForwarder(tree) {
- def errMsg = errTpe + " does not take type parameters"
- }
-
- case class AppliedTypeWrongNumberOfArgsError(tree: Tree, errMsg: String) extends ErrorTreeForwarder(tree) { }
-
- // packagedef
- case class RefTreeError(tree: Tree, name: Name) extends ErrorTree with RefTree {
- // Error was already reported
- def emit(context: Context) { }
- }
-
- // typedTypeDef
- case class LowerBoundError(tree: TypeDef, lowB: Type, highB: Type) extends ContextErrorTree(tree) {
- def errMsg = "lower bound "+lowB+" does not conform to upper bound "+highB
- }
-
- // check privates
- case class HiddenSymbolWithError(tree: Tree) extends ErrorTree {
- def emit(context: Context) { }
- }
-
- case class SymbolEscapesScopeError(tree: Tree, badSymbol: Symbol) extends ErrorTreeWithContext {
- private val treeTpe = tree.tpe
- def errPos = tree.pos
- def errMsg = modifierString + badSymbol + " escapes its defining scope as part of type "+treeTpe
- private def modifierString = if (badSymbol.isPrivate) "private " else ""
- }
-
- // typedDefDef
- case class StarParamNotLastError(param: Tree) extends ContextErrorTree(param) {
- def errMsg = "*-parameter must come last"
- }
-
- case class StarWithDefaultError(meth: Symbol) extends ErrorTreeWithContext {
- def errMsg = "a parameter section with a `*'-parameter is not allowed to have default arguments"
- def errPos = meth.pos
- }
-
- case class InvalidConstructorDefError(ddef: Tree) extends ContextErrorTree(ddef) {
- def errMsg = "constructor definition not allowed here"
- }
-
- case class DeprecatedParamNameError(param: Symbol, name: Name) extends ErrorTreeWithContext {
- def errMsg = "deprecated parameter name "+ name +" has to be distinct from any other parameter name (deprecated or not)."
- def errPos = param.pos
- }
-
- // computeParamAliases
- case class SuperConstrReferenceError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "super constructor cannot be passed a self reference unless parameter is declared by-name"
- }
-
- case class SuperConstrArgsThisReferenceError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "super constructor arguments cannot reference unconstructed `this`"
- }
-
- // typedValDef
- case class VolatileValueError(vdef: Tree) extends ContextErrorTree(vdef) {
- def errMsg = "values cannot be volatile"
- }
-
- case class FinalVolatileVarError(vdef: Tree) extends ContextErrorTree(vdef) {
- def errMsg = "final vars cannot be volatile"
- }
-
- case class LocalVarUninitializedError(vdef: Tree) extends ContextErrorTree(vdef) {
- def errMsg = "local variables must be initialized"
- }
-
- //typedAssign
- case class AssignmentError(tree: Tree, varSym: Symbol) extends ContextErrorTreeForwarder(tree) {
- def errMsg =
- if (varSym != null && varSym.isValue) "reassignment to val"
- else "assignment to non variable"
- }
-
- case class UnexpectedTreeAssignmentConversionError(tree: Tree) extends ContextErrorTreeForwarder(tree) {
- def errMsg = "Unexpected tree during assignment conversion."
- }
-
- case class MultiDimensionalArrayError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "cannot create a generic multi-dimensional array of more than "+ definitions.MaxArrayDims+" dimensions"
- }
-
- //typedSuper
- case class MixinMissingParentClassNameError(tree: Tree, mix: Name, clazz: Symbol) extends ContextErrorTree(tree) {
- def errMsg = mix+" does not name a parent class of "+clazz
- }
-
- case class AmbiguousParentClassError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "ambiguous parent class qualifier"
- }
-
- //typedSelect
- case class NotAMemberErroneous(tree: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = ""
- override def emit(context: Context) { }
- }
-
- case class NotAMemberError(sel: Tree, qual: Tree, name: Name) extends ContextErrorTreeForwarder(sel) {
- def errMsg = {
- val owner = qual.tpe.typeSymbol
- val target = qual.tpe.widen
- def targetKindString = if (owner.isTypeParameterOrSkolem) "type parameter " else ""
- def nameString = decodeWithKind(name, owner)
- /** Illuminating some common situations and errors a bit further. */
- def addendum = {
- val companion = {
- if (name.isTermName && owner.isPackageClass) {
- target.member(name.toTypeName) match {
- case NoSymbol => ""
- case sym => "\nNote: %s exists, but it has no companion object.".format(sym)
- }
- }
- else ""
- }
- val semicolon = (
- if (linePrecedes(qual, sel))
- "\npossible cause: maybe a semicolon is missing before `"+nameString+"'?"
- else
- ""
- )
- companion + semicolon
- }
- withAddendum(qual.pos)(
- if (name == nme.CONSTRUCTOR) target + " does not have a constructor"
- else nameString + " is not a member of " + targetKindString + target + addendum
- )
- }
- }
-
- //typedNew
- case class IsAbstractError(tree: Tree, sym: Symbol) extends ContextErrorTree(tree) {
- def errMsg = sym + " is abstract; cannot be instantiated"
- }
-
- case class DoesNotConformToSelfTypeError(tree: Tree, sym: Symbol, tpe0: Type) extends ContextErrorTree(tree) {
- def errMsg = sym + " cannot be instantiated because it does not conform to its self-type " + tpe0
- }
-
- //typedEta
- case class UnderscoreEtaError(tree: Tree) extends PositionedErrorTree(tree) {
- def errMsg = "_ must follow method; cannot follow " + tree.tpe
- }
-
- //typedReturn
- case class ReturnOutsideOfDefError(tree: Tree) extends PositionedErrorTree(tree) {
- def errMsg = "return outside method definition"
- }
-
- case class ReturnWithoutTypeError(tree: Tree, owner: Symbol) extends PositionedErrorTree(tree) {
- def errMsg = owner + " has return statement; needs result type"
- }
-
- //typedBind
- case class VariableInPatternAlternativeError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "illegal variable in pattern alternative"
- }
-
- //typedCase
- case class StarPositionInPatternError(errPos: Position) extends ErrorTreeWithContext {
- def errMsg = "_* may only come last"
- }
-
- //typedFunction
- case class MaxFunctionArityError(fun: Tree) extends ErrorTreeForwarder(fun) {
- def errMsg = "implementation restricts functions to " + definitions.MaxFunctionArity + " parameters"
- }
-
- case class WrongNumberOfParametersError(tree: Tree, argpts: List[Type]) extends ErrorTreeForwarder(tree) {
- def errMsg = "wrong number of parameters; expected = " + argpts.length
- }
-
- case class MissingParameterTypeError(fun: Tree, vparam: ValDef, pt: Type) extends ContextErrorTree(vparam) {
- def anonMessage = (
- "\nThe argument types of an anonymous function must be fully known. (SLS 8.5)" +
- "\nExpected type was: " + pt.toLongString
- )
-
- private val suffix =
- if (!vparam.mods.isSynthetic) ""
- else " for expanded function" + (fun match {
- case Function(_, Match(_, _)) => anonMessage
- case _ => " " + fun
- })
-
- def errMsg = "missing parameter type" + suffix
- }
-
- case class ConstructorsOrderError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "called constructor's definition must precede calling constructor's definition"
- }
-
- case class OnlyDeclarationsError(tree: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = "only declarations allowed here"
- }
-
- // typedAnnotation
- case class AnnotationNotAConstantError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "annotation argument needs to be a constant; found: " + tree
- }
-
- case class AnnotationArgNullError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "annotation argument cannot be null"
- }
-
- case class ArrayConstantsError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "Array constants have to be specified using the `Array(...)' factory method"
- }
-
- case class ArrayConstantsTypeMismatchError(tree: Tree, pt: Type) extends ContextErrorTree(tree) {
- def errMsg = "found array constant, expected argument of type " + pt
- }
-
- case class UnexpectedTreeAnnotation(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "unexpected tree in annotation: "+ tree
- }
-
- case class AnnotationTypeMismatchError(tree: Tree, expected: Type, found: Type) extends ContextErrorTree(tree) {
- def errMsg = "expected annotation of type " + expected + ", found " + found
- }
-
- case class MultipleArgumentListForAnnotationError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "multiple argument lists on classfile annotation"
- }
-
- case class UnknownAnnotationNameError(tree: Tree, name: Name) extends ContextErrorTree(tree) {
- def errMsg = "unknown annotation argument name: " + name
- }
-
- case class DuplicateValueAnnotationError(tree: Tree, name: Name) extends ContextErrorTree(tree) {
- def errMsg = "duplicate value for annotation argument " + name
- }
-
- case class ClassfileAnnotationsAsNamedArgsError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "classfile annotation arguments have to be supplied as named arguments"
- }
-
- case class AnnotationMissingArgError(tree: Tree, annType: Type, name: Symbol) extends ContextErrorTree(tree) {
- def errMsg = "annotation " + annType.typeSymbol.fullName + " is missing argument " + name.name
- }
-
- case class NestedAnnotationError(tree: Tree, annType: Type) extends ContextErrorTree(tree) {
- def errMsg = "nested classfile annotations must be defined in java; found: "+ annType
- }
-
- case class UnexpectedTreeAnnotationError(tree: Tree, unexpected: Tree) extends ContextErrorTree(tree) {
- def errMsg = "unexpected tree after typing annotation: "+ unexpected
- }
-
- // TODO no test case
- //typedExistentialTypeTree
- case class AbstractionFromVolatileTypeError(vd: ValDef) extends ContextErrorTree(vd) {
- def errMsg = "illegal abstraction from value with volatile type "+vd.symbol.tpe
- }
-
- case class TypedApplyWrongNumberOfTpeParametersError(tree: Tree, fun: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = "wrong number of type parameters for "+treeSymTypeMsg(fun)
- }
-
- case class TypedApplyDoesNotTakeTpeParametersError(tree: Tree, fun: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = treeSymTypeMsg(fun)+" does not take type parameters."
- }
-
- // doTypeApply
- //tryNamesDefaults
- case class WrongNumberOfArgsError(tree: Tree, fun: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = "wrong number of arguments for "+ treeSymTypeMsg(fun)
- }
-
- case class TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = "too many arguments for "+treeSymTypeMsg(fun)
- }
-
- case class MultipleVarargError(tree: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = "when using named arguments, the vararg parameter has to be specified exactly once"
- }
-
- case class ModuleUsingCompanionClassDefaultArgsErrror(tree: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = "module extending its companion class cannot use default constructor arguments"
- }
-
- case class NotEnoughArgsError(tree: Tree, fun0: Tree, missing0: List[Symbol]) extends ErrorTreeForwarder(tree) {
- def errMsg = notEnoughArgumentsMsg(fun0, missing0)
- def notEnoughArgumentsMsg(fun: Tree, missing: List[Symbol]) = {
- val suffix = {
- if (missing.isEmpty) ""
- else {
- val keep = missing take 3 map (_.name)
- ".\nUnspecified value parameter%s %s".format(
- if (missing.tail.isEmpty) "" else "s",
- if (missing drop 3 nonEmpty) (keep :+ "...").mkString(", ")
- else keep.mkString("", ", ", ".")
- )
- }
- }
-
- "not enough arguments for " + treeSymTypeMsg(fun) + suffix
- }
- }
-
- //doTypedApply - ErrorType
- case class ErroneousFunInTypeApplyError(fun: Tree, args: List[Tree]) extends TreeForwarder(fun) with ErrorTree {
- private lazy val errorCache = errorTreesFinder(fun) ++ (args flatMap errorTreesFinder)
-
- def emit(context: Context) {
- errorCache foreach (_ emit context)
- }
- }
-
- //doTypedApply - patternMode
- // TODO: missing test case
- case class TooManyArgsPatternError(fun: Tree) extends ContextErrorTreeForwarder(fun) {
- def errMsg = "too many arguments for unapply pattern, maximum = "+definitions.MaxTupleArity
- }
-
- case class WrongNumberArgsPatternError(tree: Tree, fun: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = "wrong number of arguments for "+treeSymTypeMsg(fun)
- }
-
- // Extends ErrorTreeWithPrettyPrinter to pass presentation/ping-pong test case
- case class ApplyWithoutArgsError(tree: Tree, fun: Tree) extends ErrorTreeForwarder(tree) with ErrorTreeWithPrettyPrinter {
- def errMsg = fun.tpe+" does not take parameters"
- override def toString = "" + tree
- }
-
- //checkClassType
- // When validating parents we sometimes should continue to
- // type the body of the template and sometimes not.
- // trait BlockingError allows us to distinguish it
- trait BlockingError
-
- case class TypeNotAStablePrefixError(pre: Type, errPos: Position) extends ErrorTreeWithContext with BlockingError {
- def errMsg = "type "+pre+" is not a stable prefix"
- }
-
- case class ClassTypeRequiredError(tree: Tree, found: AnyRef) extends ContextErrorTree(tree) with BlockingError {
- def errMsg = "class type required but "+found+" found"
- }
-
- // validateParentClasses
- case class ParentSuperSubclassError(errPos: Position, superclazz: Symbol,
- parentSym: Symbol, mixin: Symbol)
- extends ErrorTreeWithContext {
-
- def errMsg = "illegal inheritance; super"+superclazz+
- "\n is not a subclass of the super"+parentSym+
- "\n of the mixin " + mixin
- }
-
- case class ParentNotATraitMixinError(errPos: Position, mixin: Symbol) extends ErrorTreeWithContext with BlockingError {
- def errMsg = mixin+" needs to be a trait to be mixed in"
- }
-
- case class ParentFinalInheritanceError(errPos: Position, mixin: Symbol) extends ErrorTreeWithContext with BlockingError {
- def errMsg = "illegal inheritance from final "+mixin
- }
-
- case class ParentSealedInheritanceError(errPos: Position, mixin: Symbol) extends ErrorTreeWithContext with BlockingError {
- def errMsg = "illegal inheritance from sealed "+mixin
- }
-
- case class ParentSelfTypeConformanceError(errPos: Position, selfType: Type, parent: Tree) extends ErrorTreeWithContext {
- def errMsg = (
- "illegal inheritance;\n self-type "+selfType+" does not conform to "+
- parent +"'s selftype "+parent.tpe.typeOfThis
- )
- }
-
- case class ParentInheritedTwiceError(errPos: Position, parent: Symbol) extends ErrorTreeWithContext with BlockingError {
- def errMsg = parent+" is inherited twice"
- }
-
- //adapt
- case class MissingArgsForMethodTpeError(tree: Tree, meth: Symbol) extends PositionedErrorTree(tree) {
- def errMsg = (
- "missing arguments for " + meth.fullLocationString + (
- if (meth.isConstructor) ""
- else ";\nfollow this method with `_' if you want to treat it as a partially applied function"
- )
- )
- }
-
- // This is really a workaround for a compiler bug
- case class Bug4425Error(tree: Tree) extends ContextErrorTreeForwarder(tree) {
- def errMsg = "erroneous or inaccessible type"
- }
-
- case class MissingTypeParametersError(tree: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = tree.symbol+" takes type parameters"
-
- // !!! Necessary?
- // override def emit(context: Context) {
- // super.emit(context)
- // setError(tree)
- // }
- }
-
- case class KindArityMismatchError(tree: Tree, pt: Type) extends ErrorTreeForwarder(tree) {
- def errMsg = (
- tree.tpe+" takes "+countElementsAsString(tree.tpe.typeParams.length, "type parameter")+
- ", expected: "+countAsString(pt.typeParams.length)
- )
- }
- //case class ParamsNotConvertible
-
- case class CaseClassConstructorError(tree: Tree) extends ErrorTreeForwarder(tree) {
- def errMsg = tree.symbol + " is not a case class constructor, nor does it have an unapply/unapplySeq method"
- }
-
- //TODO Needs test case
- case class ConstructorPrefixError(tree: Tree, restpe: Type) extends ContextErrorTree(tree) {
- def errMsg = restpe.prefix+" is not a legal prefix for a constructor"
- }
-
- // SelectFromTypeTree
- case class TypeSelectionFromVolatileTypeError(tree: Tree, qual: Tree) extends ContextErrorTree(tree) {
- def errMsg = "illegal type selection from volatile type "+qual.tpe
- }
-
- // packedType
- case class InferTypeWithVolatileTypeSelectionError(tree: Tree, pre: Type) extends ContextErrorTree(tree) {
- def errMsg = "Inferred type "+tree.tpe+" contains type selection from volatile type "+pre
- }
-
- case class AbstractExistentiallyOverParamerizedTpeError(tree: Tree, tp: Type) extends ContextErrorTree(tree) {
- def errMsg = "can't existentially abstract over parameterized type " + tp
- }
-
- //manifestTreee
- case class MissingManifestError(errPos: Position, full: Boolean, tp: Type) extends ErrorTreeWithContext {
- def errMsg = "cannot find "+(if (full) "" else "class ")+"manifest for element type "+tp
- }
-
- // TODO needs test case
- // cases where we do not necessairly return trees
- case class DependentMethodTpeConversionToFunctionError(errPos: Position, tp: Type) extends ErrorTreeWithContext {
- def errMsg = "method with dependent type "+tpe+" cannot be converted to function value"
- override def pos = errPos
- }
-
- //checkStarPatOK
- case class StarPatternWithVarargParametersError(errPos: Position) extends ErrorTreeWithContext {
- def errMsg = "star patterns must correspond with varargs parameters"
- }
-
- case class GetterDefinedTwiceError(getter: Symbol) extends ErrorTreeWithContext {
- def errMsg = getter+" is defined twice"
- def errPos = getter.pos
- }
-
- case class BeanPropertyAnnotationLimitationError(tree: Tree) extends ContextErrorTree(tree) {
- def errMsg = "implementation limitation: the BeanProperty annotation cannot be used in a type alias or renamed import"
- }
-
- // TODO missing test case
- case class FinitaryError(tparam: Symbol) extends ErrorTreeWithContext {
- def errMsg = "class graph is not finitary because type parameter "+tparam.name+" is expansively recursive"
- def errPos = tparam.pos
- }
-
- // TODO missing test case for a second case
- case class QualifyingClassError(tree: Tree, qual: Name) extends ContextErrorTree(tree) {
- def errMsg =
- if (qual.isEmpty) tree + " can be used only in a class, object, or template"
- else qual + " is not an enclosing class"
- }
-
- // def stabilize
- case class NotAValueError(tree: Tree, sym: Symbol) extends ErrorTreeForwarder(tree) {
- def errMsg = sym.kindString + " " + sym.fullName + " is not a value"
- }
-
- // checkNoDoubleDefs...
- case class DefDefinedTwiceError(sym0: Symbol, sym1: Symbol) extends ErrorTreeWithContext {
- def errMsg = sym1+" is defined twice"+{if(!settings.debug.value) "" else " in "+context.unit}
- def errPos = sym0.pos
- override def pos = sym0.pos
- }
-
- // cyclic errors
- case class CyclicAliasingOrSubtypingError(errPos: Position, sym0: Symbol) extends ErrorTreeWithContext {
- def errMsg = "cyclic aliasing or subtyping involving "+sym0
- override def pos = errPos
- }
-
- case class CyclicReferenceError(errPos: Position, lockedSym: Symbol) extends ErrorTreeWithContext {
- def errMsg = "illegal cyclic reference involving " + lockedSym
- override def pos = errPos
- }
- }
-
- trait InferencerErrorTrees {
- self: Inferencer =>
-
- private def applyErrorMsg(tree: Tree, msg: String, argtpes: List[Type], pt: Type) = {
- def asParams(xs: List[Any]) = xs.mkString("(", ", ", ")")
-
- def resType = if (pt isWildcard) "" else " with expected result type " + pt
- def allTypes = (alternatives(tree) flatMap (_.paramTypes)) ++ argtpes :+ pt
- def locals = alternatives(tree) flatMap (_.typeParams)
-
- withDisambiguation(locals, allTypes: _*) {
- treeSymTypeMsg(tree) + msg + asParams(argtpes) + resType
- }
- }
-
- case class AccessError(tree: Tree, sym: Symbol, pre: Type, owner0: Symbol, explanation: String) extends ContextErrorTreeForwarder(tree) {
- def errMsg = {
- val realsym = underlying(sym)
- val location = if (sym.isClassConstructor) owner0 else pre.widen
-
- realsym.fullLocationString + " cannot be accessed in " +
- location + explanation
- }
- }
-
- case class NoMethodInstanceError(fn: Tree, args: List[Tree], msg: String) extends ErrorTreeForwarder(fn) {
- def errMsg = (
- "no type parameters for " +
- applyErrorMsg(fn, " exist so that it can be applied to arguments ", args map (_.tpe.widen), WildcardType) +
- "\n --- because ---\n" + msg
- )
- }
-
- // TODO: no test case
- case class NoConstructorInstanceError(tree: Tree, restpe: Type, pt: Type, msg: String) extends ErrorTreeForwarder(tree) {
- def errMsg = (
- "constructor of type " + restpe +
- " cannot be uniquely instantiated to expected type " + pt +
- "\n --- because ---\n" + msg
- )
- }
-
- case class ConstrInstantiationError(tree: Tree, restpe: Type, pt: Type) extends ErrorTreeForwarder(tree) {
- def errMsg = "constructor cannot be instantiated to expected type" + foundReqMsg(restpe, pt)
- }
-
- case class NoBestMethodAlternativeError(tree: Tree, argtpes: List[Type], pt: Type) extends ErrorTreeForwarder(tree) {
- def errMsg = applyErrorMsg(tree, " cannot be applied to ", argtpes, pt)
- }
-
- case class AmbiguousMethodAlternativeError(tree: Tree, pre: Type, best: Symbol,
- firstCompeting: Symbol, argtpes: List[Type], pt: Type)
- extends ErrorTreeForwarder(tree) {
-
- def errMsg = (
- "argument types " + argtpes.mkString("(", ",", ")") +
- (if (pt == WildcardType) "" else " and expected result type " + pt)
- )
- override def emit(context: Context) {
- context.ambiguousError(tree.pos, pre, best, firstCompeting, errMsg)
- }
- }
-
- case class NoBestExprAlternativeError(tree: Tree, pt: Type) extends ContextErrorTreeForwarder(tree) {
- def errMsg = withAddendum(tree.pos)(typeErrorMsg(tree.symbol.tpe, pt))
- }
-
- case class AmbiguousExprAlternativeError(tree: Tree, pre: Type, best: Symbol, firstCompeting: Symbol, pt: Type)
- extends ErrorTreeForwarder(tree) {
-
- def errMsg = "expected type " + pt
- override def emit(context: Context) {
- context.ambiguousError(tree.pos, pre, best, firstCompeting, errMsg)
- }
- }
-
- // checkBounds
- case class KindBoundErrors(errPos: Position, prefix: String, targs: List[Type],
- tparams: List[Symbol], kindErrors: List[String])
- extends ErrorTreeWithContext {
-
- def errMsg = (
- prefix + "kinds of the type arguments " + targs.mkString("(", ",", ")") +
- " do not conform to the expected kinds of the type parameters "+
- tparams.mkString("(", ",", ")") + tparams.head.locationString+ "." +
- kindErrors.toList.mkString("\n", ", ", "")
- )
- override def pos = errPos
- }
-
- case class NotWithinBounds(pos0: Position, prefix: String, targs: List[Type],
- tparams: List[Symbol], kindErrors: List[String])
- extends ErrorTree {
-
- val savedContext = getContext
- def emit(context: Context) {
- val validContext = if (context.unit == NoCompilationUnit) savedContext else context
- validContext.error(pos0,
- prefix + "type arguments " + targs.mkString("[", ",", "]") +
- " do not conform to " + tparams.head.owner + "'s type parameter bounds " +
- (tparams map (_.defString)).mkString("[", ",", "]"))
- if (settings.explaintypes.value) {
- val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, targs).bounds)
- (targs, bounds).zipped foreach ((targ, bound) => explainTypes(bound.lo, targ))
- (targs, bounds).zipped foreach ((targ, bound) => explainTypes(targ, bound.hi))
- ()
- }
- }
-
- override def pos = pos0
- }
-
- //substExpr
- case class PolymorphicExpressionInstantiationError(tree: Tree, undetparams: List[Symbol], pt: Type) extends ContextErrorTreeForwarder(tree) {
- def errMsg = (
- "polymorphic expression cannot be instantiated to expected type" +
- foundReqMsg(polyType(undetparams, skipImplicit(tree.tpe)), pt)
- )
- }
-
- //checkCheckable
- case class TypePatternOrIsInstanceTestError(errPos: Position, tp: Type) extends ErrorTreeWithContext {
- def errMsg = "type "+tp+" cannot be used in a type pattern or isInstanceOf test"
- override def pos = errPos
- }
-
- case class IncompletePatternTypeError(errPos: Position, pattp: Type, pt: Type) extends ErrorTreeWithContext {
- def errMsg = "pattern type is incompatible with expected type" + foundReqMsg(pattp, pt)
- override def pos = errPos
- }
-
- case class IncompatibleScrutineeTypeError(errPos: Position, pattp: Type, pt: Type) extends ErrorTreeWithContext {
- def errMsg = "scrutinee is incompatible with pattern type" + foundReqMsg(pattp, pt)
- override def pos = errPos
- }
-
- case class PatternTypeIncompatibleWithPtError(pat: Tree, pt1: Type, pt: Type) extends ContextErrorTreeForwarder(pat) {
- def errMsg = {
- val sym = pat.tpe.typeSymbol
- val clazz = sym.companionClass
- val addendum = (
- if (sym.isModuleClass && clazz.isCaseClass && (clazz isSubClass pt1.typeSymbol)) {
- // TODO: move these somewhere reusable.
- val typeString = clazz.typeParams match {
- case Nil => "" + clazz.name
- case xs => xs map (_ => "_") mkString (clazz.name + "[", ",", "]")
- }
- val caseString = (
- clazz.caseFieldAccessors
- map (_ => "_") // could use the actual param names here
- mkString (clazz.name + "(", ",", ")")
- )
- (
- "\nNote: if you intended to match against the class, try `case _: " +
- typeString + "` or `case " + caseString + "`"
- )
- }
- else ""
- )
- "pattern type is incompatible with expected type"+foundReqMsg(pat.tpe, pt) + addendum
- }
- }
-
- case class PolyAlternativeError(tree: Tree, errMsg: String) extends ContextErrorTreeForwarder(tree) { }
- }
-
- trait NamerErrorTrees {
- self: Namer =>
-
- // Currently too general
- case class TypeSigError(tree: Tree, override val exception: TypeError) extends ErrorTree {
- def emit(context: Context) {
- typer.reportTypeError(context, tree.pos, exception)
- }
- }
- }
-
- // General errors
- case class PendingErrors(pending0: List[ErrorTree])
- extends ErrorTree {
- assert(pending0.nonEmpty, "pending exceptions cannot be empty")
-
- def emit(context: Context) {
- // Try to report each, here we dont' care
- // if any of those throws TypeError
- // this is handled in the actual application code
- pending0.foreach(_.emit(context))
- }
-
- override def pos = pending0.head.pos
- override def exception: TypeError = pending0.head.exception
- }
-
- case object NullErrorTree extends ErrorTree {
- def emit(context: Context) {}
- }
-
- case class SetErrorTree(tree: Tree) extends ErrorTree {
- def emit(context: Context) {
- typer.infer.setError(tree)
- }
- }
-
- //NamesDefaults errors, refactor to their own trait
- case class NameClashError(sym: Symbol, arg: Tree) extends ErrorTreeWithContext {
- def errMsg =
- "%s definition needs %s because '%s' is used as a named argument in its body.".format(
- "variable", // "method"
- "type", // "result type"
- sym.name)
-
- override def emit(context: Context) = {
- super.emit(context)
- // This is ugly hack to avoid reporting double errors
- // when dealing with AmbiguousReferences problem (error tree below) in names defaults.
- typer.infer.setError(arg)
- }
-
- def errPos = sym.pos
- override def pos = sym.pos
- }
-
- case class AmbiguousReferenceInNamesDefaultError(arg: Tree, name: Name) extends ErrorTreeForwarder(arg) {
- def errMsg = (
- "reference to "+ name +" is ambiguous; it is both, a parameter\n"+
- "name of the method and the name of a variable currently in scope."
- )
- }
-
- case class UnknownParameterNameNamesDefaultError(arg: Tree, name: Name) extends ErrorTreeForwarder(arg) {
- def errMsg = "unknown parameter name: " + name
- }
-
- case class DoubleParamNamesDefaultError(arg: Tree, name: Name) extends ErrorTreeForwarder(arg) {
- def errMsg = "parameter specified twice: "+ name
- }
-
- case class PositionalAfterNamedNamesDefaultError(arg: Tree) extends ErrorTreeForwarder(arg) {
- def errMsg = "positional after named argument."
- }
-}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 0ab619e875..169295e5c9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -522,9 +522,6 @@ trait Implicits {
else
typed1(itree, EXPRmode, wildPt)
- if (itree1.containsError())
- return SearchFailure
-
incCounter(typedImplicits)
printTyping("typed implicit %s:%s, pt=%s".format(itree1, itree1.tpe, wildPt))
@@ -544,7 +541,7 @@ trait Implicits {
}
}
- if (itree2.containsErrorOrIsErrorTyped())
+ if (itree2.tpe.isError)
SearchFailure
else if (!hasMatchingSymbol(itree1))
fail("candidate implicit %s is shadowed by other implicit %s".format(
@@ -568,11 +565,7 @@ trait Implicits {
false, lubDepth(List(itree2.tpe, pt)))
// #2421: check that we correctly instantiated type parameters outside of the implicit tree:
- // TODO: refactoring needed, shouldn't emit it here
- checkBounds(itree2.pos, NoPrefix, NoSymbol, undetParams, targs, "inferred ") match {
- case Some(err) => err.emit(context)
- case _ =>
- }
+ checkBounds(itree2.pos, NoPrefix, NoSymbol, undetParams, targs, "inferred ")
// filter out failures from type inference, don't want to remove them from undetParams!
// we must be conservative in leaving type params in undetparams
@@ -597,18 +590,12 @@ trait Implicits {
// re-typecheck)
// TODO: the return tree is ignored. This seems to make
// no difference, but it's bad practice regardless.
-
- // we call typedTypeApply which can return an error tree,
- // so we cannot ignore the tree
- // TODO check if that is enough
- val checked = itree2 match {
+ itree2 match {
case TypeApply(fun, args) => typedTypeApply(itree2, EXPRmode, fun, args)
case Apply(TypeApply(fun, args), _) => typedTypeApply(itree2, EXPRmode, fun, args) // t2421c
case t => t
}
- if (checked.containsError())
- return SearchFailure
- val result = new SearchResult(checked, subst)
+ val result = new SearchResult(itree2, subst)
incCounter(foundImplicits)
printInference("[typedImplicit1] SearchResult: " + result)
result
@@ -618,8 +605,6 @@ trait Implicits {
}
}
catch {
- // TODO: once refactoring of type errors is done we should only
- // catch here cyclic references.
case ex: TypeError => fail(ex.getMessage())
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 26e4da5d79..354eb52913 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -189,7 +189,7 @@ trait Infer {
private val stdErrorValue = stdErrorClass.newErrorValue(nme.ERROR)
/** The context-dependent inferencer part */
- class Inferencer(context: Context) extends InferencerErrorTrees {
+ class Inferencer(context: Context) {
/* -- Error Messages --------------------------------------------------- */
def setError[T <: Tree](tree: T): T = {
def name = newTermName("<error: " + tree.symbol + ">")
@@ -203,20 +203,19 @@ trait Infer {
tree setType ErrorType
}
- protected def getContext = context
-
def error(pos: Position, msg: String) {
context.error(pos, msg)
}
-/* def makeErrorTree(tree: Tree, msg: String): Tree = {
+ def errorTree(tree: Tree, msg: String): Tree = {
if (!tree.isErroneous) error(tree.pos, msg)
setError(tree)
- }*/
+ }
def typeError(pos: Position, found: Type, req: Type) {
if (!found.isErroneous && !req.isErroneous) {
error(pos, withAddendum(pos)(typeErrorMsg(found, req)))
+
if (settings.explaintypes.value)
explainTypes(found, req)
}
@@ -229,8 +228,6 @@ trait Infer {
"type mismatch" + foundReqMsg(found, req) + missingArgsMsg
}
- // TODO: replace with standard Error tree
- // currently only used in adapt in Typers
def typeErrorTree(tree: Tree, found: Type, req: Type): Tree = {
// If the expected type is a refinement type, and the found type is a refinement or an anon
// class, we can greatly improve the error message by retyping the tree to recover the actual
@@ -290,7 +287,7 @@ trait Infer {
Console.println(tree)
Console.println("" + pre + " " + sym.owner + " " + context.owner + " " + context.outer.enclClass.owner + " " + sym.owner.thisType + (pre =:= sym.owner.thisType))
}
- AccessError(tree, sym, pre, context.enclClass.owner,
+ new AccessError(tree, sym, pre,
if (settings.check.isDefault)
analyzer.lastAccessCheckDetails
else
@@ -317,17 +314,11 @@ trait Infer {
if (settings.debug.value) ex.printStackTrace
val sym2 = underlying(sym1)
val itype = pre.memberType(sym2)
- return AccessError(tree, sym, pre, context.enclClass.owner,
+ new AccessError(tree, sym, pre,
"\n because its instance type "+itype+
(if ("malformed type: "+itype.toString==ex.msg) " is malformed"
- else " contains a "+ex.msg))
-
-// enabling the following TypeError case
-// crashes a few examples because there are situations (like in NamesDefaults)
-// where CyclicReference is expected
-// case ex: TypeError =>
-// return TypeErrorTree(tree, ex)(context)
-
+ else " contains a "+ex.msg)).emit()
+ ErrorType
}
if (pre.isInstanceOf[SuperType])
owntype = owntype.substSuper(pre, site.symbol.thisType)
@@ -920,9 +911,7 @@ trait Infer {
false
}
- /**
- * Todo: Try to make isApplicable always safe (i.e. not cause TypeErrors).
- * The chance of TypeErrors should be reduced through error trees
+ /** Todo: Try to make isApplicable always safe (i.e. not cause TypeErrors).
*/
private[typechecker] def isApplicableSafe(undetparams: List[Symbol], ftpe: Type,
argtpes0: List[Type], pt: Type): Boolean = {
@@ -1103,20 +1092,37 @@ trait Infer {
*/
/** error if arguments not within bounds. */
def checkBounds(pos: Position, pre: Type, owner: Symbol,
- tparams: List[Symbol], targs: List[Type], prefix: String): Option[ErrorTree] = {
+ tparams: List[Symbol], targs: List[Type], prefix: String) = {
//@M validate variances & bounds of targs wrt variances & bounds of tparams
//@M TODO: better place to check this?
//@M TODO: errors for getters & setters are reported separately
val kindErrors = checkKindBounds(tparams, targs, pre, owner)
- if(!kindErrors.isEmpty) {
- if (targs contains WildcardType) None
- else Some(KindBoundErrors(pos, prefix, targs, tparams, kindErrors))
- } else if (!isWithinBounds(pre, owner, tparams, targs)) {
- if (!(targs exists (_.isErroneous)) && !(tparams exists (_.isErroneous)))
- Some(NotWithinBounds(pos, prefix, targs, tparams, kindErrors))
- else None
- } else None
+ if (!kindErrors.isEmpty) {
+ if (targs contains WildcardType) ()
+ else error(pos,
+ prefix + "kinds of the type arguments " + targs.mkString("(", ",", ")") +
+ " do not conform to the expected kinds of the type parameters "+
+ tparams.mkString("(", ",", ")") + tparams.head.locationString+ "." +
+ kindErrors.toList.mkString("\n", ", ", ""))
+ }
+ else if (!isWithinBounds(pre, owner, tparams, targs)) {
+ if (!(targs exists (_.isErroneous)) && !(tparams exists (_.isErroneous))) {
+ //val bounds = instantiatedBounds(pre, owner, tparams, targs)//DEBUG
+ //println("bounds = "+bounds+", targs = "+targs+", targclasses = "+(targs map (_.getClass))+", parents = "+(targs map (_.parents)))
+ //println(List.map2(bounds, targs)((bound, targ) => bound containsType targ))
+ error(pos,
+ prefix + "type arguments " + targs.mkString("[", ",", "]") +
+ " do not conform to " + tparams.head.owner + "'s type parameter bounds " +
+ (tparams map (_.defString)).mkString("[", ",", "]"))
+ if (settings.explaintypes.value) {
+ val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, targs).bounds)
+ (targs, bounds).zipped foreach ((targ, bound) => explainTypes(bound.lo, targ))
+ (targs, bounds).zipped foreach ((targ, bound) => explainTypes(targ, bound.hi))
+ ()
+ }
+ }
+ }
}
@@ -1160,7 +1166,7 @@ trait Infer {
* first to `strictPt` and then, if this fails, to `lenientPt`. If both
* attempts fail, an error is produced.
*/
- def inferArgumentInstance(tree: Tree, undetparams: List[Symbol], strictPt: Type, lenientPt: Type) = {
+ def inferArgumentInstance(tree: Tree, undetparams: List[Symbol], strictPt: Type, lenientPt: Type) {
printInference(
ptBlock("inferArgumentInstance",
"tree" -> tree,
@@ -1174,8 +1180,8 @@ trait Infer {
if ((targs eq null) || !(tree.tpe.subst(undetparams, targs) <:< strictPt)) {
targs = exprTypeArgs(undetparams, tree.tpe, lenientPt)
}
- printInference("[inferArgumentInstance] finished, targs = " + targs)
substExpr(tree, undetparams, targs, lenientPt)
+ printInference("[inferArgumentInstance] finished, targs = " + targs)
}
/** Infer type arguments `targs` for `tparams` of polymorphic expression in `tree`, given prototype `pt`.
@@ -1183,7 +1189,7 @@ trait Infer {
* Substitute `tparams` to `targs` in `tree`, after adjustment by `adjustTypeArgs`, returning the type parameters that were not determined
* If passed, infers against specified type `treeTp` instead of `tree.tp`.
*/
- def inferExprInstance(tree: Tree, tparams: List[Symbol], pt: Type = WildcardType, treeTp0: Type = null, keepNothings: Boolean = true, useWeaklyCompatible: Boolean = false): (Option[ErrorTree], List[Symbol]) = {
+ def inferExprInstance(tree: Tree, tparams: List[Symbol], pt: Type = WildcardType, treeTp0: Type = null, keepNothings: Boolean = true, useWeaklyCompatible: Boolean = false): List[Symbol] = {
val treeTp = if(treeTp0 eq null) tree.tpe else treeTp0 // can't refer to tree in default for treeTp0
printInference(
ptBlock("inferExprInstance",
@@ -1196,7 +1202,8 @@ trait Infer {
val targs = exprTypeArgs(tparams, treeTp, pt, useWeaklyCompatible)
if (keepNothings || (targs eq null)) { //@M: adjustTypeArgs fails if targs==null, neg/t0226
- (substExpr(tree, tparams, targs, pt), List())
+ substExpr(tree, tparams, targs, pt)
+ List()
} else {
val AdjustedTypeArgs.Undets(okParams, okArgs, leftUndet) = adjustTypeArgs(tparams, targs)
printInference(
@@ -1206,7 +1213,8 @@ trait Infer {
"leftUndet" -> leftUndet
)
)
- (substExpr(tree, okParams, okArgs, pt), leftUndet)
+ substExpr(tree, okParams, okArgs, pt)
+ leftUndet
}
}
@@ -1219,15 +1227,13 @@ trait Infer {
* @param pt ...
*/
private def substExpr(tree: Tree, undetparams: List[Symbol],
- targs: List[Type], pt: Type): Option[ErrorTree] = {
+ targs: List[Type], pt: Type) {
if (targs eq null) {
if (!tree.tpe.isErroneous && !pt.isErroneous)
- Some(PolymorphicExpressionInstantiationError(tree, undetparams, pt))
- else
- None
+ error(tree.pos, "polymorphic expression cannot be instantiated to expected type" +
+ foundReqMsg(polyType(undetparams, skipImplicit(tree.tpe)), pt))
} else {
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
- None
}
}
@@ -1242,7 +1248,7 @@ trait Infer {
* and that thus have not been substituted.
*/
def inferMethodInstance(fn: Tree, undetparams: List[Symbol],
- args: List[Tree], pt0: Type): Either[ErrorTree, List[Symbol]] = fn.tpe match {
+ args: List[Tree], pt0: Type): List[Symbol] = fn.tpe match {
case MethodType(params0, _) =>
printInference(
ptBlock("inferMethodInstance",
@@ -1262,32 +1268,31 @@ trait Infer {
val AdjustedTypeArgs.AllArgsAndUndets(okparams, okargs, allargs, leftUndet) =
methTypeArgs(undetparams, formals, restpe, argtpes, pt)
- checkBounds(fn.pos, NoPrefix, NoSymbol, undetparams, allargs, "inferred ") match {
- case Some(err) =>
- Left(err)
- case _ =>
- // bounds are ok
- val treeSubst = new TreeTypeSubstituter(okparams, okargs)
- treeSubst traverseTrees fn :: args
-
- val result = leftUndet match {
- case Nil => Nil
- case xs =>
- // #3890
- val xs1 = treeSubst.typeSubst mapOver xs
- if (xs ne xs1)
- new TreeSymSubstTraverser(xs, xs1) traverseTrees fn :: args
-
- xs1
- }
- if (result.nonEmpty)
- printInference("inferMethodInstance, still undetermined: " + result)
+ checkBounds(fn.pos, NoPrefix, NoSymbol, undetparams, allargs, "inferred ")
+ val treeSubst = new TreeTypeSubstituter(okparams, okargs)
+ treeSubst traverseTrees fn :: args
- Right(result)
+ val result = leftUndet match {
+ case Nil => Nil
+ case xs =>
+ // #3890
+ val xs1 = treeSubst.typeSubst mapOver xs
+ if (xs ne xs1)
+ new TreeSymSubstTraverser(xs, xs1) traverseTrees fn :: args
+
+ xs1
}
+ if (result.nonEmpty)
+ printInference("inferMethodInstance, still undetermined: " + result)
+
+ result
}
catch ifNoInstance { msg =>
- Left(NoMethodInstanceError(fn, args, msg))
+ errorTree(fn, "no type parameters for " +
+ applyErrorMsg(fn, " exist so that it can be applied to arguments ", args map (_.tpe.widen), WildcardType) +
+ "\n --- because ---\n" + msg
+ )
+ Nil
}
}
@@ -1312,7 +1317,7 @@ trait Infer {
* @param undetparams the undetermined type parameters
* @param pt the expected result type of the instance
*/
- def inferConstructorInstance(tree: Tree, undetparams: List[Symbol], pt0: Type): Option[ErrorTree] = {
+ def inferConstructorInstance(tree: Tree, undetparams: List[Symbol], pt0: Type) {
val pt = widen(pt0)
//println("infer constr inst "+tree+"/"+undetparams+"/"+pt0)
var restpe = tree.tpe.finalResultType
@@ -1327,14 +1332,17 @@ trait Infer {
// checkBounds(tree.pos, NoPrefix, NoSymbol, undetparams, targs, "inferred ")
// no checkBounds here. If we enable it, test bug602 fails.
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
- None
- } catch ifNoInstance{ msg =>
- Some(NoConstructorInstanceError(tree, restpe, pt, msg))
+ } catch {
+ case ex: NoInstance =>
+ errorTree(tree, "constructor of type " + restpe +
+ " cannot be uniquely instantiated to expected type " + pt +
+ "\n --- because ---\n" + ex.getMessage())
}
def instError = {
if (settings.debug.value) Console.println("ici " + tree + " " + undetparams + " " + pt)
if (settings.explaintypes.value) explainTypes(restpe.instantiateTypeParams(undetparams, tvars), pt)
- Some(ConstrInstantiationError(tree, restpe, pt))
+ errorTree(tree, "constructor cannot be instantiated to expected type" +
+ foundReqMsg(restpe, pt))
}
if (restpe.instantiateTypeParams(undetparams, tvars) <:< pt) {
computeArgs
@@ -1352,7 +1360,6 @@ trait Infer {
val pt1 = pt.instantiateTypeParams(ptparams, ptvars)
if (isPopulated(restpe, pt1)) {
ptvars foreach instantiateTypeVar
- None
} else { if (settings.debug.value) Console.println("no instance: "); instError }
} else { if (settings.debug.value) Console.println("not a subtype " + restpe.instantiateTypeParams(undetparams, tvars) + " of " + ptWithWildcards); instError }
} else { if (settings.debug.value) Console.println("not fully defined: " + pt); instError }
@@ -1405,12 +1412,11 @@ trait Infer {
}
}
- def checkCheckable(pos: Position, tp: Type, kind: String): Option[ErrorTree] = {
+ def checkCheckable(pos: Position, tp: Type, kind: String) {
def patternWarning(tp0: Type, prefix: String) = {
context.unit.uncheckedWarning(pos, prefix+tp0+" in type "+kind+tp+" is unchecked since it is eliminated by erasure")
}
- def check(tp: Type, bound: List[Symbol]): Option[ErrorTree] = {
- implicit def listErrorsToPending(l: List[ErrorTree]): Option[ErrorTree] = if (l.isEmpty) None else Some(PendingErrors(l))
+ def check(tp: Type, bound: List[Symbol]) {
def isLocalBinding(sym: Symbol) =
sym.isAbstractType &&
((bound contains sym) ||
@@ -1422,38 +1428,36 @@ trait Infer {
case SingleType(pre, _) =>
check(pre, bound)
case TypeRef(pre, sym, args) =>
- val checkForSymAndArgs: Option[ErrorTree] = if (sym.isAbstractType) {
+ if (sym.isAbstractType) {
if (!isLocalBinding(sym)) patternWarning(tp, "abstract type ")
- None
} else if (sym.isAliasType) {
check(tp.normalize, bound)
} else if (sym == NothingClass || sym == NullClass || sym == AnyValClass) {
- Some(TypePatternOrIsInstanceTestError(pos, tp))
+ error(pos, "type "+tp+" cannot be used in a type pattern or isInstanceOf test")
} else {
- args.map( arg => {
+ for (arg <- args) {
if (sym == ArrayClass) check(arg, bound)
- else if (arg.typeArgs.nonEmpty) None // avoid spurious warnings with higher-kinded types
- else {arg match {
+ else if (arg.typeArgs.nonEmpty) () // avoid spurious warnings with higher-kinded types
+ else arg match {
case TypeRef(_, sym, _) if isLocalBinding(sym) =>
-
+ ;
case _ =>
patternWarning(arg, "non variable type-argument ")
- }; None}
- }).flatten
+ }
+ }
}
- List(checkForSymAndArgs, check(pre, bound)).flatten
+ check(pre, bound)
case RefinedType(parents, decls) =>
- if (decls.isEmpty) parents.map(p => check(p, bound)).flatten
- else { patternWarning(tp, "refinement "); None }
+ if (decls.isEmpty) for (p <- parents) check(p, bound)
+ else patternWarning(tp, "refinement ")
case ExistentialType(quantified, tp1) =>
check(tp1, bound ::: quantified)
case ThisType(_) =>
- None
+ ;
case NoPrefix =>
- None
+ ;
case _ =>
patternWarning(tp, "type ")
- None
}
}
check(tp, List())
@@ -1476,7 +1480,7 @@ trait Infer {
}
}
- def inferTypedPattern(pos: Position, pattp: Type, pt0: Type): Either[ErrorTree, Type] = {
+ def inferTypedPattern(pos: Position, pattp: Type, pt0: Type): Type = {
val pt = widen(pt0)
val ptparams = freeTypeParamsOfTerms.collect(pt)
val tpparams = freeTypeParamsOfTerms.collect(pattp)
@@ -1489,13 +1493,9 @@ trait Infer {
* and is a "final type", meaning final + invariant in all type parameters.
*/
if (pt.isFinalType && ptparams.isEmpty && !ptMatchesPattp)
- return Left(IncompatibleScrutineeTypeError(pos, pattp, pt))
+ error(pos, "scrutinee is incompatible with pattern type" + foundReqMsg(pattp, pt))
- checkCheckable(pos, pattp, "pattern ") match {
- case Some(err) =>
- return Left(err)
- case _ => ()
- }
+ checkCheckable(pos, pattp, "pattern ")
if (pattp <:< pt) ()
else {
debuglog("free type params (1) = " + tpparams)
@@ -1517,8 +1517,10 @@ trait Infer {
// fail if we didn't allow for pattpMatchesPt.
if (isPopulated(tp, pt1) && isInstantiatable(tvars ++ ptvars) || pattpMatchesPt)
ptvars foreach instantiateTypeVar
- else
- return Left(IncompletePatternTypeError(pos, pattp, pt))
+ else {
+ error(pos, "pattern type is incompatible with expected type" + foundReqMsg(pattp, pt))
+ return pattp
+ }
}
tvars foreach instantiateTypeVar
}
@@ -1526,22 +1528,43 @@ trait Infer {
* we have to flip the arguments so the expected type is treated as more
* general when calculating the intersection. See run/bug2755.scala.
*/
- if (tpparams.isEmpty && ptparams.nonEmpty) Right(intersect(pattp, pt))
- else Right(intersect(pt, pattp))
+ if (tpparams.isEmpty && ptparams.nonEmpty) intersect(pattp, pt)
+ else intersect(pt, pattp)
}
- def inferModulePattern(pat: Tree, pt: Type): Option[ErrorTree] =
+ def inferModulePattern(pat: Tree, pt: Type) =
if (!(pat.tpe <:< pt)) {
val ptparams = freeTypeParamsOfTerms.collect(pt)
debuglog("free type params (2) = " + ptparams)
val ptvars = ptparams map freshVar
val pt1 = pt.instantiateTypeParams(ptparams, ptvars)
- if (pat.tpe <:< pt1) {
+ if (pat.tpe <:< pt1)
ptvars foreach instantiateTypeVar
- None
- } else
- Some(PatternTypeIncompatibleWithPtError(pat, pt1, pt))
- } else None
+ else {
+ val sym = pat.tpe.typeSymbol
+ val clazz = sym.companionClass
+ val addendum = (
+ if (sym.isModuleClass && clazz.isCaseClass && (clazz isSubClass pt1.typeSymbol)) {
+ // TODO: move these somewhere reusable.
+ val typeString = clazz.typeParams match {
+ case Nil => "" + clazz.name
+ case xs => xs map (_ => "_") mkString (clazz.name + "[", ",", "]")
+ }
+ val caseString = (
+ clazz.caseFieldAccessors
+ map (_ => "_") // could use the actual param names here
+ mkString (clazz.name + "(", ",", ")")
+ )
+ (
+ "\nNote: if you intended to match against the class, try `case _: " +
+ typeString + "` or `case " + caseString + "`"
+ )
+ }
+ else ""
+ )
+ error(pat.pos, "pattern type is incompatible with expected type"+foundReqMsg(pat.tpe, pt) + addendum)
+ }
+ }
object toOrigin extends TypeMap {
def apply(tp: Type): Type = tp match {
@@ -1608,7 +1631,7 @@ trait Infer {
* If several alternatives match `pt`, take parameterless one.
* If no alternative matches `pt`, take the parameterless one anyway.
*/
- def inferExprAlternative(tree: Tree, pt: Type): Option[ErrorTree] = tree.tpe match {
+ def inferExprAlternative(tree: Tree, pt: Type): Unit = tree.tpe match {
case OverloadedType(pre, alts) => tryTwice {
val alts0 = alts filter (alt => isWeaklyCompatible(pre.memberType(alt), pt))
val secondTry = alts0.isEmpty
@@ -1639,27 +1662,24 @@ trait Infer {
case _ =>
}
}
- Some(NoBestExprAlternativeError(tree, pt))
+ typeErrorTree(tree, tree.symbol.tpe, pt)
} else if (!competing.isEmpty) {
if (secondTry) {
- Some(NoBestExprAlternativeError(tree, pt))
+ typeErrorTree(tree, tree.symbol.tpe, pt)
} else {
if (!pt.isErroneous)
- Some(AmbiguousExprAlternativeError(tree, pre, best, competing.head, pt))
- else
- Some(NullErrorTree) // already reported
+ context.ambiguousError(tree.pos, pre, best, competing.head, "expected type " + pt)
+ setError(tree)
}
} else {
// val applicable = alts1 filter (alt =>
// global.typer.infer.isWeaklyCompatible(pre.memberType(alt), pt))
// checkNotShadowed(tree.pos, pre, best, applicable)
tree.setSymbol(best).setType(pre.memberType(best))
- None
}
}
}
- // TODO: remove once error tree refactoring is done
@inline private def wrapTypeError(expr: => Boolean): Boolean =
try expr
catch { case _: TypeError => false }
@@ -1723,7 +1743,7 @@ trait Infer {
* assignment expression.
*/
def inferMethodAlternative(tree: Tree, undetparams: List[Symbol],
- argtpes: List[Type], pt0: Type, varArgsOnly: Boolean = false): Option[ErrorTree] = tree.tpe match {
+ argtpes: List[Type], pt0: Type, varArgsOnly: Boolean = false): Unit = tree.tpe match {
case OverloadedType(pre, alts) =>
val pt = if (pt0.typeSymbol == UnitClass) WildcardType else pt0
tryTwice {
@@ -1750,22 +1770,24 @@ trait Infer {
if (improves(alt, best)) alt else best)
val competing = applicable.dropWhile(alt => best == alt || improves(best, alt))
if (best == NoSymbol) {
- if (pt == WildcardType)
- Some(NoBestMethodAlternativeError(tree, argtpes, pt))
- else
+ if (pt == WildcardType) {
+ errorTree(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt))
+ } else {
inferMethodAlternative(tree, undetparams, argtpes, WildcardType)
+ }
} else if (!competing.isEmpty) {
if (!(argtpes exists (_.isErroneous)) && !pt.isErroneous)
- Some(AmbiguousMethodAlternativeError(tree, pre, best, competing.head, argtpes, pt))
- else
- Some(NullErrorTree)
+ context.ambiguousError(tree.pos, pre, best, competing.head,
+ "argument types " + argtpes.mkString("(", ",", ")") +
+ (if (pt == WildcardType) "" else " and expected result type " + pt))
+ setError(tree)
+ ()
} else {
// checkNotShadowed(tree.pos, pre, best, applicable)
tree.setSymbol(best).setType(pre.memberType(best))
- None
}
}
- case _ => None
+ case _ =>
}
/** Try inference twice, once without views and once with views,
@@ -1773,25 +1795,18 @@ trait Infer {
*
* @param infer ...
*/
- def tryTwice(infer: => Option[ErrorTree]): Option[ErrorTree] = {
+ def tryTwice(infer: => Unit) {
if (context.implicitsEnabled) {
val reportGeneralErrors = context.reportGeneralErrors
context.reportGeneralErrors = false
- val res = try {
- context.withImplicitsDisabled(infer) match {
- case Some(err) =>
- context.reportGeneralErrors = reportGeneralErrors
- infer
- case ok => ok
- }
- } catch {
+ try context.withImplicitsDisabled(infer)
+ catch {
case ex: CyclicReference => throw ex
case ex: TypeError =>
context.reportGeneralErrors = reportGeneralErrors
infer
}
context.reportGeneralErrors = reportGeneralErrors
- res
}
else infer
}
@@ -1803,10 +1818,10 @@ trait Infer {
* @param tree ...
* @param nparams ...
*/
- def inferPolyAlternatives(tree: Tree, argtypes: List[Type]): Option[ErrorTree] = {
+ def inferPolyAlternatives(tree: Tree, argtypes: List[Type]): Unit = {
val OverloadedType(pre, alts) = tree.tpe
val sym0 = tree.symbol filter (alt => sameLength(alt.typeParams, argtypes))
- def fail(msg: String) = Some(PolyAlternativeError(tree, msg))
+ def fail(msg: String): Unit = error(tree.pos, msg)
if (sym0 == NoSymbol) return fail(
if (alts exists (_.typeParams.nonEmpty))
@@ -1820,13 +1835,12 @@ trait Infer {
else {
val sym = sym0 filter (alt => isWithinBounds(pre, alt.owner, alt.typeParams, argtypes))
if (sym == NoSymbol) {
- if (argtypes forall (x => !x.isErroneous))
- return fail(
+ if (argtypes forall (x => !x.isErroneous)) fail(
"type arguments " + argtypes.mkString("[", ",", "]") +
" conform to the bounds of none of the overloaded alternatives of\n "+sym0+
": "+sym0.info
)
- return None
+ return
}
else if (sym.isOverloaded) {
val xs = sym.alternatives
@@ -1841,7 +1855,24 @@ trait Infer {
}
// Side effects tree with symbol and type
tree setSymbol resSym setType resTpe
- None
+ }
+
+ abstract class TreeForwarder(forwardTo: Tree) extends Tree {
+ override def pos = forwardTo.pos
+ override def hasSymbol = forwardTo.hasSymbol
+ override def symbol = forwardTo.symbol
+ override def symbol_=(x: Symbol) = forwardTo.symbol = x
+ }
+
+ case class AccessError(tree: Tree, sym: Symbol, pre: Type, explanation: String) extends TreeForwarder(tree) {
+ setError(this)
+
+ // @PP: It is improbable this logic shouldn't be in use elsewhere as well.
+ private def location = if (sym.isClassConstructor) context.enclClass.owner else pre.widen
+ def emit(): Tree = {
+ val realsym = underlying(sym)
+ errorTree(tree, realsym.fullLocationString + " cannot be accessed in " + location + explanation)
+ }
}
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index e41bb737f2..d0f1722b1c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -65,26 +65,13 @@ trait Namers { self: Analyzer =>
classAndNamerOfModule.clear
}
- abstract class Namer(val context: Context) extends NamerErrorTrees {
+ abstract class Namer(val context: Context) {
val typer = newTyper(context)
def setPrivateWithin[Sym <: Symbol](tree: Tree, sym: Sym, mods: Modifiers): Sym = {
- if (mods.hasAccessBoundary) {
- val symOrError = typer.qualifyingClass(tree, mods.privateWithin, true) match {
- case Left(err) =>
- try {
- err.emit(context)
- } catch {
- case _: TypeError =>
- assert(false, "qualifying class info can fail but cannot throw type errors")
- }
- NoSymbol
- case Right(sym) =>
- sym
- }
- sym.privateWithin = symOrError
- }
+ if (mods.hasAccessBoundary)
+ sym.privateWithin = typer.qualifyingClass(tree, mods.privateWithin, true)
sym
}
@@ -161,7 +148,6 @@ trait Namers { self: Analyzer =>
private def setInfo[Sym <: Symbol](sym : Sym)(tpe : LazyType) : Sym = sym.setInfo(tpe)
- // TODO: make it into error trees
private def doubleDefError(pos: Position, sym: Symbol) {
val s1 = if (sym.isModule) "case class companion " else ""
val s2 = if (sym.isSynthetic) "(compiler-generated) " + s1 else ""
@@ -674,18 +660,10 @@ trait Namers { self: Analyzer =>
case _ =>
}
sym.setInfo(if (sym.isJavaDefined) RestrictJavaArraysMap(tp) else tp)
- if ((sym.isAliasType || sym.isAbstractType) && !sym.isParameter) {
- val check = typer.checkNonCyclic(tree.pos, tp)
- if (check.isDefined) {
- sym.setInfo(ErrorType) // this early test is there to avoid infinite baseTypes when
- // adding setters and getters --> bug798
- try {
- check.get.emit(context)
- } catch {
- case _: TypeError => assert(false, "Type errors cannot be thrown in type completers")
- }
- }
- }
+ if ((sym.isAliasType || sym.isAbstractType) && !sym.isParameter &&
+ !typer.checkNonCyclic(tree.pos, tp))
+ sym.setInfo(ErrorType) // this early test is there to avoid infinite baseTypes when
+ // adding setters and getters --> bug798
debuglog("defined " + sym);
validate(sym)
}
@@ -851,14 +829,7 @@ trait Namers { self: Analyzer =>
}
*/
- var parents0 = typer.parentTypes(templ)
- try {
- parents0.foreach(p => if (p.containsError()) typer.emitAllErrorTrees(p, context))
- } catch {
- case _: TypeError =>
- assert(false, "parent types cannot throw type errors")
- }
- val parents = parents0 map checkParent
+ var parents = typer.parentTypes(templ) map checkParent
enterSelf(templ.self)
val decls = new Scope
// for (etdef <- earlyTypes) decls enter etdef.symbol
@@ -1342,10 +1313,7 @@ trait Namers { self: Analyzer =>
case Import(expr, selectors) =>
val expr1 = typer.typedQualifier(expr)
- val stable = typer.checkStable(expr1)
- if (stable.containsError())
- typer.emitAllErrorTrees(stable, context)
-
+ typer checkStable expr1
if (expr1.symbol != null && expr1.symbol.isRootPackage)
context.error(tree.pos, "_root_ cannot be imported")
@@ -1361,10 +1329,7 @@ trait Namers { self: Analyzer =>
} catch {
case ex: TypeError =>
//Console.println("caught " + ex + " in typeSig")
- // TODO: once ErrorTrees are implemented we should be able
- // to get rid of this catch and simply report the error
- // (maybe apart from cyclic errors)
- TypeSigError(tree, ex).emit(context)
+ typer.reportTypeError(tree.pos, ex)
ErrorType
}
result match {
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index 729bbf4557..bf7cc72fab 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -304,9 +304,7 @@ trait NamesDefaults { self: Analyzer =>
// `fun` is typed. `namelessArgs` might be typed or not, if they are types are kept.
case Apply(fun, namelessArgs) =>
val transformedFun = transformNamedApplication(typer, mode, pt)(fun, x => x)
- // Is it safe to replace containsError() with containsErrorOrIsErrorTyped()?
- if (transformedFun.containsError()) transformedFun
- else if (transformedFun.isErroneous) NullErrorTree
+ if (transformedFun.isErroneous) setError(tree)
else {
assert(isNamedApplyBlock(transformedFun), transformedFun)
val NamedApplyInfo(qual, targs, vargss, blockTyper) =
@@ -315,7 +313,8 @@ trait NamesDefaults { self: Analyzer =>
// type the application without names; put the arguments in definition-site order
val typedApp = doTypedApply(tree, funOnly, reorderArgs(namelessArgs, argPos), mode, pt)
- if (typedApp.containsErrorOrIsErrorTyped()) typedApp
+
+ if (typedApp.tpe.isError) setError(tree)
else typedApp match {
// Extract the typed arguments, restore the call-site evaluation order (using
// ValDef's in the block), change the arguments to these local values.
@@ -440,6 +439,7 @@ trait NamesDefaults { self: Analyzer =>
* after named ones.
*/
def removeNames(typer: Typer)(args: List[Tree], params: List[Symbol]): (List[Tree], Array[Int]) = {
+ import typer.infer.errorTree
// maps indicies from (order written by user) to (order of definition)
val argPos = (new Array[Int](args.length)) map (x => -1)
@@ -457,10 +457,10 @@ trait NamesDefaults { self: Analyzer =>
// treat the arg as an assignment of type Unit
Assign(a.lhs, rhs).setPos(arg.pos)
} else {
- UnknownParameterNameNamesDefaultError(arg, name)
+ errorTree(arg, "unknown parameter name: "+ name)
}
} else if (argPos contains pos) {
- DoubleParamNamesDefaultError(arg, name)
+ errorTree(arg, "parameter specified twice: "+ name)
} else {
// for named arguments, check whether the assignment expression would
// typecheck. if it does, report an ambiguous error.
@@ -481,20 +481,26 @@ trait NamesDefaults { self: Analyzer =>
val reportAmbiguousErrors = typer.context.reportAmbiguousErrors
typer.context.reportAmbiguousErrors = false
+ var variableNameClash = false
val typedAssign = try {
typer.silent(_.typed(arg, subst(paramtpe)))
} catch {
// `silent` only catches and returns TypeErrors which are not
// CyclicReferences. Fix for #3685
-
- // Returning CyclicReference error trees is problematic
- // so we stay with throwing exceptions
case cr @ CyclicReference(sym, info) if sym.name == param.name =>
if (sym.isVariable || sym.isGetter && sym.accessed.isVariable) {
// named arg not allowed
- NameClashError(sym, arg)
+ variableNameClash = true
+ typer.context.error(sym.pos,
+ "%s definition needs %s because '%s' is used as a named argument in its body.".format(
+ "variable", // "method"
+ "type", // "result type"
+ sym.name
+ )
+ )
+ typer.infer.setError(arg)
}
- else NullErrorTree
+ else cr
}
def applyNamedArg = {
@@ -507,27 +513,28 @@ trait NamesDefaults { self: Analyzer =>
}
val res = typedAssign match {
- case err: NameClashError =>
- err
- case _: TypeError =>
- // TODO: is should be safe to remove this case after error trees are fully implemented
- applyNamedArg
- case t: Tree if t.containsErrorOrIsErrorTyped() =>
- // containsErrorOrIsErrorTyped() needed because of for instance #4041
- applyNamedArg
+ case _: TypeError => applyNamedArg
+
case t: Tree =>
- // This throws an exception which is caught in `tryTypedApply` (as it
- // uses `silent`) - unfortunately, tryTypedApply recovers from the
- // exception if you use errorTree(arg, ...) and conforms is allowed as
- // a view (see tryImplicit in Implicits) because it tries to produce a
- // new qualifier (if the old one was P, the new one will be
- // conforms.apply(P)), and if that works, it pretends nothing happened.
- //
- // To make sure tryTypedApply fails, we would like to pass EmptyTree
- // instead of arg, but can't do that because eventually setType(ErrorType)
- // is called, and EmptyTree can only be typed NoType. Thus we need to
- // disable conforms as a view...
- AmbiguousReferenceInNamesDefaultError(arg, name)
+ if (t.isErroneous && !variableNameClash) {
+ applyNamedArg
+ } else if (t.isErroneous) {
+ t // name clash with variable. error was already reported above.
+ } else {
+ // This throws an exception which is caught in `tryTypedApply` (as it
+ // uses `silent`) - unfortunately, tryTypedApply recovers from the
+ // exception if you use errorTree(arg, ...) and conforms is allowed as
+ // a view (see tryImplicit in Implicits) because it tries to produce a
+ // new qualifier (if the old one was P, the new one will be
+ // conforms.apply(P)), and if that works, it pretends nothing happened.
+ //
+ // To make sure tryTypedApply fails, we would like to pass EmptyTree
+ // instead of arg, but can't do that because eventually setType(ErrorType)
+ // is called, and EmptyTree can only be typed NoType. Thus we need to
+ // disable conforms as a view...
+ errorTree(arg, "reference to "+ name +" is ambiguous; it is both, a parameter\n"+
+ "name of the method and the name of a variable currently in scope.")
+ }
}
typer.context.reportAmbiguousErrors = reportAmbiguousErrors
@@ -539,9 +546,8 @@ trait NamesDefaults { self: Analyzer =>
case _ =>
argPos(index) = index
if (positionalAllowed) arg
- else PositionalAfterNamedNamesDefaultError(arg)
+ else errorTree(arg, "positional after named argument.")
}
-
(namelessArgs, argPos)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index fda6a6f12e..d4565c8e0c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1190,15 +1190,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
/* Check whether argument types conform to bounds of type parameters */
private def checkBounds(pre: Type, owner: Symbol, tparams: List[Symbol], argtps: List[Type], pos: Position): Unit =
- try typer.infer.checkBounds(pos, pre, owner, tparams, argtps, "") match {
- case Some(err) => err.emit(typer.context)
- case _ => ()
- }
+ try typer.infer.checkBounds(pos, pre, owner, tparams, argtps, "")
catch {
case ex: TypeError =>
- // checkBounds no longer throws errors (apart from Cyclic ones)
- // so maybe it is safe to remove/simplify this catch?
- unit.error(pos, ex.getMessage())
+ unit.error(pos, ex.getMessage());
if (settings.explaintypes.value) {
val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, argtps).bounds)
(argtps, bounds).zipped map ((targ, bound) => explainTypes(bound.lo, targ))
@@ -1356,13 +1351,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
case tpt@TypeTree() =>
if(tpt.original != null) {
tpt.original foreach {
- case dc@TypeTreeWithDeferredRefCheck() =>
- dc.check() match {
- case Left(err) =>
- err.emit()
- case Right(t) =>
- applyRefchecksToAnnotations(t) // #2416
- }
+ case dc@TypeTreeWithDeferredRefCheck() => applyRefchecksToAnnotations(dc.check()) // #2416
case _ =>
}
}
@@ -1526,11 +1515,8 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
if(tpt.original != null) {
tpt.original foreach {
case dc@TypeTreeWithDeferredRefCheck() =>
- dc.check() match {
- case Left(err) => err.emit()
- case Right(tree) => transform(tree) // #2416 -- only call transform to do refchecks, but discard results
- // tpt has the right type if the deferred checks are ok
- }
+ transform(dc.check()) // #2416 -- only call transform to do refchecks, but discard results
+ // tpt has the right type if the deferred checks are ok
case _ =>
}
}
@@ -1606,7 +1592,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
result
} catch {
case ex: TypeError =>
- if (settings.debug.value) ex.printStackTrace()
+ if (settings.debug.value) ex.printStackTrace();
unit.error(tree.pos, ex.getMessage())
tree
} finally {
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index db6d1445a9..8c06dbe0bf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -52,11 +52,10 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
private def checkPackedConforms(tree: Tree, pt: Type): Tree = {
if (tree.tpe exists (_.typeSymbol.isExistentialSkolem)) {
val packed = localTyper.packedType(tree, NoSymbol)
- packed._2.foreach(_.emit())
- if (!(packed._1 <:< pt)) {
+ if (!(packed <:< pt)) {
val errorContext = localTyper.context.make(localTyper.context.tree)
errorContext.reportGeneralErrors = true
- analyzer.newTyper(errorContext).infer.typeError(tree.pos, packed._1, pt)
+ analyzer.newTyper(errorContext).infer.typeError(tree.pos, packed, pt)
}
}
tree
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 6eaa65ce9b..9a8bcca2ba 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -41,7 +41,7 @@ trait SyntheticMethods extends ast.TreeDSL {
import CODE._
val localTyper = newTyper(
- if (reporter.hasErrors || templ.containsError()) context makeSilent false else context
+ if (reporter.hasErrors) context makeSilent false else context
)
def accessorTypes = clazz.caseFieldAccessors map (_.tpe.finalResultType)
def accessorLub = global.weakLub(accessorTypes)._1
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index 0b84e67447..6e0e78e8e2 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -135,6 +135,21 @@ trait TypeDiagnostics {
def alternativesString(tree: Tree) =
alternatives(tree) map (x => " " + methodTypeErrorString(x)) mkString ("", " <and>\n", "\n")
+ def missingParameterTypeMsg(fun: Tree, vparam: ValDef, pt: Type) = {
+ def anonMessage = (
+ "\nThe argument types of an anonymous function must be fully known. (SLS 8.5)" +
+ "\nExpected type was: " + pt.toLongString
+ )
+ val suffix =
+ if (!vparam.mods.isSynthetic) ""
+ else " for expanded function" + (fun match {
+ case Function(_, Match(_, _)) => anonMessage
+ case _ => " " + fun
+ })
+
+ "missing parameter type" + suffix
+ }
+
def treeSymTypeMsg(tree: Tree): String = {
val sym = tree.symbol
def hasParams = tree.tpe.paramSectionCount > 0
@@ -153,6 +168,34 @@ trait TypeDiagnostics {
else defaultMessage
}
+ def notEnoughArgumentsMsg(fun: Tree, missing: List[Symbol]): String = {
+ val suffix = {
+ if (missing.isEmpty) ""
+ else {
+ val keep = missing take 3 map (_.name)
+ ".\nUnspecified value parameter%s %s".format(
+ if (missing.tail.isEmpty) "" else "s",
+ if (missing drop 3 nonEmpty) (keep :+ "...").mkString(", ")
+ else keep.mkString("", ", ", ".")
+ )
+ }
+ }
+
+ "not enough arguments for " + treeSymTypeMsg(fun) + suffix
+ }
+
+ def applyErrorMsg(tree: Tree, msg: String, argtpes: List[Type], pt: Type) = {
+ def asParams(xs: List[Any]) = xs.mkString("(", ", ", ")")
+
+ def resType = if (pt isWildcard) "" else " with expected result type " + pt
+ def allTypes = (alternatives(tree) flatMap (_.paramTypes)) ++ argtpes :+ pt
+ def locals = alternatives(tree) flatMap (_.typeParams)
+
+ withDisambiguation(locals, allTypes: _*) {
+ treeSymTypeMsg(tree) + msg + asParams(argtpes) + resType
+ }
+ }
+
def disambiguate(ss: List[String]) = ss match {
case Nil => Nil
case s :: ss => s :: (ss map { case `s` => "(some other)"+s ; case x => x })
@@ -362,10 +405,8 @@ trait TypeDiagnostics {
trait TyperDiagnostics {
self: Typer =>
- private def contextError(pos: Position, msg: String) { contextError(context, pos, msg) }
- private def contextError(context0: Analyzer#Context, pos: Position, msg: String) { context0.error(pos, msg) }
- private def contextError(pos: Position, err: Throwable) { contextError(context, pos, err) }
- private def contextError(context0: Analyzer#Context, pos: Position, err: Throwable) { context0.error(pos, err) }
+ private def contextError(pos: Position, msg: String) = context.error(pos, msg)
+ private def contextError(pos: Position, err: Throwable) = context.error(pos, err)
object checkDead {
private var expr: Symbol = NoSymbol
@@ -399,46 +440,36 @@ trait TypeDiagnostics {
}
}
- private def symWasOverloaded(sym: Symbol) = sym.owner.isClass && sym.owner.info.member(sym.name).isOverloaded
- private def cyclicAdjective(sym: Symbol) = if (symWasOverloaded(sym)) "overloaded" else "recursive"
+ def symWasOverloaded(sym: Symbol) = sym.owner.isClass && sym.owner.info.member(sym.name).isOverloaded
+ def cyclicAdjective(sym: Symbol) = if (symWasOverloaded(sym)) "overloaded" else "recursive"
/** Returns Some(msg) if the given tree is untyped apparently due
* to a cyclic reference, and None otherwise.
*/
- private def cyclicReferenceMessage(sym: Symbol, tree: Tree) = condOpt(tree) {
+ def cyclicReferenceMessage(sym: Symbol, tree: Tree) = condOpt(tree) {
case ValDef(_, _, tpt, _) if tpt.tpe == null => "recursive "+sym+" needs type"
case DefDef(_, _, _, _, tpt, _) if tpt.tpe == null => List(cyclicAdjective(sym), sym, "needs result type") mkString " "
}
- def reportTypeError(pos: Position, ex: TypeError) {
- reportTypeError(context, pos, ex)
- }
-
/** Report a type error.
*
* @param pos0 The position where to report the error
* @param ex The exception that caused the error
*/
- def reportTypeError(context0: Analyzer#Context, pos: Position, ex: TypeError) {
+ def reportTypeError(pos: Position, ex: TypeError) {
if (ex.pos == NoPosition) ex.pos = pos
- if (!context0.reportGeneralErrors) throw ex
+ if (!context.reportGeneralErrors) throw ex
if (settings.debug.value) ex.printStackTrace()
ex match {
case CyclicReference(sym, info: TypeCompleter) =>
- contextError(context0, ex.pos, cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage())
+ contextError(ex.pos, cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage())
if (sym == ObjectClass)
throw new FatalError("cannot redefine root "+sym)
case _ =>
- contextError(context0, ex.pos, ex)
+ contextError(ex.pos, ex)
}
}
-
- def emitAllErrorTrees(tree: Tree, context: Context) =
- errorTreesFinder(tree).foreach(_.emit(context))
-
- def findAllNestedErrors(trees: List[Tree]): List[ErrorTree] =
- trees.map(errorTreesFinder(_)).flatten
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 893384ece3..a1343fb7d7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -12,13 +12,13 @@
package scala.tools.nsc
package typechecker
-import scala.collection.mutable
-import mutable.ListBuffer
-
+import scala.collection.{ mutable, immutable }
import scala.tools.nsc.util.BatchSourceFile
+import mutable.ListBuffer
import symtab.Flags._
-import util.Statistics._
import util.Statistics
+import util.Statistics._
+import scala.tools.util.StringOps.{ countAsString, countElementsAsString }
// Suggestion check whether we can do without priming scopes with symbols of outer scopes,
// like the IDE does.
@@ -59,7 +59,7 @@ trait Typers extends Modes with Adaptations {
super.traverse(tree)
}
}
-/* needed for experimental version where early types can be type arguments
+/* needed for experimental version where eraly types can be type arguments
class EarlyMap(clazz: Symbol) extends TypeMap {
def apply(tp: Type): Type = tp match {
case TypeRef(NoPrefix, sym, List()) if (sym hasFlag PRESUPER) =>
@@ -77,7 +77,7 @@ trait Typers extends Modes with Adaptations {
// that are turned private by typedBlock
private final val SYNTHETIC_PRIVATE = TRANS_FLAG
- abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with TyperErrorTrees {
+ abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation {
import context0.unit
import typeDebug.{ ptTree, ptBlock, ptLine }
@@ -99,6 +99,15 @@ trait Typers extends Modes with Adaptations {
def mkNamedArg(argTree: Tree, paramName: Name) = atPos(argTree.pos)(new AssignOrNamedArg(Ident(paramName), (argTree)))
var mkArg: (Tree, Name) => Tree = mkPositionalArg
+ def errorMessage(paramName: Name, paramTp: Type) =
+ paramTp.typeSymbol match {
+ case ImplicitNotFoundMsg(msg) => msg.format(paramName, paramTp)
+ case _ =>
+ "could not find implicit value for "+
+ (if (paramName startsWith nme.EVIDENCE_PARAM_PREFIX) "evidence parameter of type "
+ else "parameter "+paramName+": ")+paramTp
+ }
+
// DEPMETTODO: instantiate type vars that depend on earlier implicit args (see adapt (4.1))
//
// apply the substitutions (undet type param -> type) that were determined
@@ -115,9 +124,8 @@ trait Typers extends Modes with Adaptations {
argBuff += mkArg(res.tree, param.name)
} else {
mkArg = mkNamedArg // don't pass the default argument (if any) here, but start emitting named arguments for the following args
- if (!param.hasDefault) {
- argBuff += NoImplicitFoundError(fun, param)
- }
+ if (!param.hasDefault)
+ context.error(fun.pos, errorMessage(param.name, param.tpe))
/* else {
TODO: alternative (to expose implicit search failure more) -->
resolve argument, do type inference, keep emitting positional args, infer type params based on default value for arg
@@ -178,10 +186,6 @@ trait Typers extends Modes with Adaptations {
var context = context0
def context1 = context
- @inline
- private def wrapInBlock(errTree: Tree, original: Tree): Tree = Block(errTree, original) setType ErrorType
-
-
def dropExistential(tp: Type): Type = tp match {
case ExistentialType(tparams, tpe) =>
new SubstWildcardMap(tparams).apply(tp)
@@ -198,12 +202,22 @@ trait Typers extends Modes with Adaptations {
* @return ...
*/
def checkStable(tree: Tree): Tree =
- if (treeInfo.isPureExpr(tree)) tree else UnstableTreeError(tree)
+ if (treeInfo.isPureExpr(tree)) tree
+ else errorTree(
+ tree,
+ "stable identifier required, but "+tree+" found."+
+ (if (isStableExceptVolatile(tree)) {
+ val tpe = tree.symbol.tpe match {
+ case PolyType(_, rtpe) => rtpe
+ case t => t
+ }
+ "\n Note that "+tree.symbol+" is not stable because its type, "+tree.tpe+", is volatile."
+ } else ""))
/** Would tree be a stable (i.e. a pure expression) if the type
* of its symbol was not volatile?
*/
- protected def isStableExceptVolatile(tree: Tree) = {
+ private def isStableExceptVolatile(tree: Tree) = {
tree.hasSymbol && tree.symbol != NoSymbol && tree.tpe.isVolatile &&
{ val savedTpe = tree.symbol.info
val savedSTABLE = tree.symbol getFlag STABLE
@@ -217,21 +231,21 @@ trait Typers extends Modes with Adaptations {
}
/** Check that `tpt` refers to a non-refinement class type */
- def checkClassType(tpt: Tree, existentialOK: Boolean, stablePrefix: Boolean) = {
- def errorNotClass(found: AnyRef) = Some(ClassTypeRequiredError(tpt, found))
- def check(tpe: Type): Option[ErrorTree] = tpe.normalize match {
+ def checkClassType(tpt: Tree, existentialOK: Boolean, stablePrefix: Boolean) {
+ def errorNotClass(found: AnyRef) = error(tpt.pos, "class type required but "+found+" found")
+ def check(tpe: Type): Unit = tpe.normalize match {
case TypeRef(pre, sym, _) if sym.isClass && !sym.isRefinementClass =>
- if (stablePrefix && phase.id <= currentRun.typerPhase.id)
+ if (stablePrefix && phase.id <= currentRun.typerPhase.id) {
if (!pre.isStable)
- Some(TypeNotAStablePrefixError(pre, tpt.pos))
- else
- tpt match {
+ error(tpt.pos, "type "+pre+" is not a stable prefix")
+ // A type projection like X#Y can get by the stable check if the
+ // prefix is singleton-bounded, so peek at the tree too.
+ else tpt match {
case SelectFromTypeTree(qual, _) if !isSingleType(qual.tpe) => errorNotClass(tpt)
- case _ => None
- }
- else
- None
- case ErrorType => None
+ case _ => ;
+ }
+ }
+ case ErrorType => ;
case PolyType(_, restpe) => check(restpe)
case ExistentialType(_, restpe) if existentialOK => check(restpe)
case AnnotatedType(_, underlying, _) => check(underlying)
@@ -246,19 +260,18 @@ trait Typers extends Modes with Adaptations {
* @param tp ...
* @return <code>true</code> if <code>tp</code> is not a subtype of itself.
*/
- def checkNonCyclic(pos: Position, tp: Type): Option[ErrorTree] = {
- def checkNotLocked(sym: Symbol): Option[ErrorTree] = {
+ def checkNonCyclic(pos: Position, tp: Type): Boolean = {
+ def checkNotLocked(sym: Symbol): Boolean = {
sym.initialize
- if (sym.lockOK) None
- else Some(CyclicAliasingOrSubtypingError(pos, sym))
+ sym.lockOK || {error(pos, "cyclic aliasing or subtyping involving "+sym); false}
}
tp match {
case TypeRef(pre, sym, args) =>
- val check = checkNotLocked(sym)
- if (check.isDefined) check
- else if (!sym.isNonClassType) None
- else checkNonCyclic(pos, appliedType(pre.memberInfo(sym), args), sym)
-
+ (checkNotLocked(sym)) && (
+ !sym.isNonClassType ||
+ checkNonCyclic(pos, appliedType(pre.memberInfo(sym), args), sym) // @M! info for a type ref to a type parameter now returns a polytype
+ // @M was: checkNonCyclic(pos, pre.memberInfo(sym).subst(sym.typeParams, args), sym)
+ )
case SingleType(pre, sym) =>
checkNotLocked(sym)
/*
@@ -270,70 +283,51 @@ trait Typers extends Modes with Adaptations {
case st: SubType =>
checkNonCyclic(pos, st.supertype)
case ct: CompoundType =>
- val checkRes = ct.parents map (x => checkNonCyclic(pos, x)) flatten
-
- if (checkRes.isEmpty) None
- else Some(PendingErrors(checkRes))
+ ct.parents forall (x => checkNonCyclic(pos, x))
case _ =>
- None
+ true
}
}
- // TODO in order to return CyclicReferenceError we need to change the signature of lock
- // let's leave it for now
- def checkNonCyclic(pos: Position, tp: Type, lockedSym: Symbol): Option[ErrorTree] = try {
+ def checkNonCyclic(pos: Position, tp: Type, lockedSym: Symbol): Boolean = try {
lockedSym.lock {
throw new TypeError("illegal cyclic reference involving " + lockedSym)
}
checkNonCyclic(pos, tp)
- } catch {
- case _ :TypeError =>
- Some(CyclicReferenceError(pos, lockedSym))
} finally {
lockedSym.unlock()
}
- def checkNonCyclic(sym: Symbol): Option[ErrorTree] = {
- val check = checkNonCyclic(sym.pos, sym.tpe)
- if (check.isDefined)
- sym.setInfo(ErrorType)
- check
+ def checkNonCyclic(sym: Symbol) {
+ if (!checkNonCyclic(sym.pos, sym.tpe)) sym.setInfo(ErrorType)
}
- def checkNonCyclic(defn: Tree, tpt: Tree): Option[ErrorTree] = {
- val check = checkNonCyclic(defn.pos, tpt.tpe, defn.symbol)
- if (check.isDefined) {
+ def checkNonCyclic(defn: Tree, tpt: Tree) {
+ if (!checkNonCyclic(defn.pos, tpt.tpe, defn.symbol)) {
tpt.tpe = ErrorType
defn.symbol.setInfo(ErrorType)
}
- check
}
- def checkParamsConvertible(pos: Position, tpe0: Type): List[ErrorTree] = {
- var pending: List[ErrorTree] = List()
- def checkParamsConvertible0(tpe: Type) =
- tpe match {
- case MethodType(formals, restpe) =>
- /*
- if (formals.exists(_.typeSymbol == ByNameParamClass) && formals.length != 1)
- error(pos, "methods with `=>`-parameter can be converted to function values only if they take no other parameters")
- if (formals exists (isRepeatedParamType(_)))
- error(pos, "methods with `*`-parameters cannot be converted to function values");
- */
- if (restpe.isDependent)
- pending = DependentMethodTpeConversionToFunctionError(pos, tpe)::pending
- checkParamsConvertible(pos, restpe)
- case _ =>
- }
- checkParamsConvertible0(tpe0)
- pending
+ def checkParamsConvertible(pos: Position, tpe: Type) {
+ tpe match {
+ case MethodType(formals, restpe) =>
+ /*
+ if (formals.exists(_.typeSymbol == ByNameParamClass) && formals.length != 1)
+ error(pos, "methods with `=>`-parameter can be converted to function values only if they take no other parameters")
+ if (formals exists (isRepeatedParamType(_)))
+ error(pos, "methods with `*`-parameters cannot be converted to function values");
+ */
+ if (restpe.isDependent)
+ error(pos, "method with dependent type "+tpe+" cannot be converted to function value")
+ checkParamsConvertible(pos, restpe)
+ case _ =>
+ }
}
- @inline
- private def checkStarPatOK(pos: Position, mode: Int):Option[ErrorTree] =
+ def checkStarPatOK(pos: Position, mode: Int) =
if ((mode & STARmode) == 0 && phase.id <= currentRun.typerPhase.id)
- Some(StarPatternWithVarargParametersError(pos))
- else None
+ error(pos, "star patterns must correspond with varargs parameters")
/** Check that type of given tree does not contain local or private
* components.
@@ -351,7 +345,7 @@ trait Typers extends Modes with Adaptations {
* @param tree ...
* @return ...
*/
- def privates(owner: Symbol, tree: Tree): Tree =
+ def privates[T <: Tree](owner: Symbol, tree: T): T =
check(owner, EmptyScope, WildcardType, tree)
/** Check that type <code>tree</code> does not refer to entities
@@ -362,16 +356,16 @@ trait Typers extends Modes with Adaptations {
* @param tree ...
* @return ...
*/
- def locals(scope: Scope, pt: Type, tree: Tree): Tree =
+ def locals[T <: Tree](scope: Scope, pt: Type, tree: T): T =
check(NoSymbol, scope, pt, tree)
- private def check(owner: Symbol, scope: Scope, pt: Type, tree: Tree): Tree = {
+ def check[T <: Tree](owner: Symbol, scope: Scope, pt: Type, tree: T): T = {
this.owner = owner
this.scope = scope
hiddenSymbols = List()
val tp1 = apply(tree.tpe)
if (hiddenSymbols.isEmpty) tree setType tp1
- else if (hiddenSymbols exists (_.isErroneous)) HiddenSymbolWithError(tree)
+ else if (hiddenSymbols exists (_.isErroneous)) setError(tree)
else if (isFullyDefined(pt)) tree setType pt //todo: eliminate
else if (tp1.typeSymbol.isAnonymousClass) // todo: eliminate
check(owner, scope, pt, tree setType tp1.typeSymbol.classBound)
@@ -379,7 +373,10 @@ trait Typers extends Modes with Adaptations {
tree setType packSymbols(hiddenSymbols.reverse, tp1)
else if (!phase.erasedTypes) { // privates
val badSymbol = hiddenSymbols.head
- SymbolEscapesScopeError(tree, badSymbol)
+ error(tree.pos,
+ (if (badSymbol.isPrivate) "private " else "") + badSymbol +
+ " escapes its defining scope as part of type "+tree.tpe)
+ setError(tree)
} else tree
}
@@ -442,12 +439,16 @@ trait Typers extends Modes with Adaptations {
/** The qualifying class
* of a this or super with prefix <code>qual</code>.
*/
- def qualifyingClass(tree: Tree, qual: Name, packageOK: Boolean): Either[ErrorTree, Symbol] =
+ def qualifyingClass(tree: Tree, qual: Name, packageOK: Boolean): Symbol =
context.enclClass.owner.ownerChain.find(o => qual.isEmpty || o.isClass && o.name == qual) match {
case Some(c) if packageOK || !c.isPackageClass =>
- Right(c)
+ c
case _ =>
- Left(QualifyingClassError(tree, qual))
+ error(
+ tree.pos,
+ if (qual.isEmpty) tree+" can be used only in a class, object, or template"
+ else qual+" is not an enclosing class")
+ NoSymbol
}
/** The typer for an expression, depending on where we are. If we are before a superclass
@@ -564,19 +565,14 @@ trait Typers extends Modes with Adaptations {
* 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.
*/
- private def stabilize(tree0: Tree, pre: Type, mode: Int, pt: Type): Tree = {
- val tree =
- if (tree0.symbol.isOverloaded && !inFunMode(mode))
- inferExprAlternative(tree0, pt) match {
- case Some(err) => err
- case _ => tree0
- }
- else tree0
+ private def stabilize(tree: Tree, pre: Type, mode: Int, pt: Type): Tree = {
+ if (tree.symbol.isOverloaded && !inFunMode(mode))
+ inferExprAlternative(tree, pt)
val sym = tree.symbol
- def fail() = NotAValueError(tree, sym)
+ def fail() = errorTree(tree, sym.kindString + " " + sym.fullName + " is not a value")
- if (tree.containsErrorOrIsErrorTyped()) tree
+ if (tree.tpe.isError) tree
else if ((mode & (PATTERNmode | FUNmode)) == PATTERNmode && tree.isTerm) { // (1)
if (sym.isValue) checkStable(tree)
else fail()
@@ -656,8 +652,6 @@ trait Typers extends Modes with Adaptations {
} catch {
case ex: CyclicReference => throw ex
case ex: TypeError =>
- // TODO: when move to error trees is complete we should
- // be able to just drop this case
stopCounter(rawTypeFailed, rawTypeStart)
stopCounter(findMemberFailed, findMemberStart)
stopCounter(subtypeFailed, subtypeStart)
@@ -666,6 +660,23 @@ trait Typers extends Modes with Adaptations {
}
}
+ /** Utility method: Try op1 on tree. If that gives an error try op2 instead.
+ */
+ def tryBoth(tree: Tree)(op1: (Typer, Tree) => Tree)(op2: (Typer, Tree) => Tree): Tree =
+ silent(op1(_, tree)) match {
+ case result1: Tree =>
+ result1
+ case ex1: TypeError =>
+ silent(op2(_, resetAllAttrs(tree))) match {
+ case result2: Tree =>
+// println("snd succeeded: "+result2)
+ result2
+ case ex2: TypeError =>
+ reportTypeError(tree.pos, ex1)
+ setError(tree)
+ }
+ }
+
def isCodeType(tpe: Type) = tpe.typeSymbol isNonBottomSubClass CodeClass
/** Perform the following adaptations of expression, pattern or type `tree` wrt to
@@ -711,6 +722,7 @@ trait Typers extends Modes with Adaptations {
if (context.undetparams nonEmpty) { // (9) -- should revisit dropped condition `(mode & POLYmode) == 0`
// dropped so that type args of implicit method are inferred even if polymorphic expressions are allowed
// needed for implicits in 2.8 collection library -- maybe once #3346 is fixed, we can reinstate the condition?
+ context.undetparams =
inferExprInstance(tree, context.extractUndetparams(), pt,
// approximate types that depend on arguments since dependency on implicit argument is like dependency on type parameter
if (settings.YdepMethTpes.value) mt.approximate else mt,
@@ -719,21 +731,14 @@ trait Typers extends Modes with Adaptations {
// Looking for a manifest of Nil: This has many potential types,
// so we need to instantiate to minimal type List[Nothing].
keepNothings = false, // retract Nothing's that indicate failure, ambiguities in manifests are dealt with in manifestOfType
- useWeaklyCompatible = true) match {// #3808
- case (Some(err), undetparams1) =>
- context.undetparams = undetparams1
- return err
- case (_, undetparams1) =>
- context.undetparams = undetparams1
- }
+ useWeaklyCompatible = true) // #3808
}
val typer1 = constrTyperIf(treeInfo.isSelfOrSuperConstrCall(tree))
if (original != EmptyTree && pt != WildcardType)
typer1.silent(tpr => tpr.typed(tpr.applyImplicitArgs(tree), mode, pt)) match {
- case result: Tree if !result.containsError() =>
- result
- case _ =>
+ case result: Tree => result
+ case ex: TypeError =>
debuglog("fallback on implicits: " + tree + "/" + resetAllAttrs(original))
val tree1 = typed(resetAllAttrs(original), mode, WildcardType)
tree1.tpe = addAnnotations(tree1, tree1.tpe)
@@ -751,10 +756,7 @@ trait Typers extends Modes with Adaptations {
}
if (!meth.isConstructor && isFunctionType(pt)) { // (4.2)
debuglog("eta-expanding " + tree + ":" + tree.tpe + " to " + pt)
- val errs = checkParamsConvertible(tree.pos, tree.tpe)
- if (!errs.isEmpty) {
- return PendingErrors(errs.reverse)
- }
+ checkParamsConvertible(tree.pos, tree.tpe)
val tree0 = etaExpand(context.unit, tree)
// println("eta "+tree+" ---> "+tree0+":"+tree0.tpe+" undet: "+context.undetparams+ " mode: "+Integer.toHexString(mode))
@@ -771,10 +773,11 @@ trait Typers extends Modes with Adaptations {
} else if (!meth.isConstructor && mt.params.isEmpty) { // (4.3)
adapt(typed(Apply(tree, List()) setPos tree.pos), mode, pt, original)
} else if (context.implicitsEnabled) {
- MissingArgsForMethodTpeError(tree, meth)
+ errorTree(tree, "missing arguments for " + meth + meth.locationString +
+ (if (meth.isConstructor) ""
+ else ";\nfollow this method with `_' if you want to treat it as a partially applied function"))
} else {
- // Relevant only for #4425 ?
- Bug4425Error(tree)
+ setError(tree)
}
}
@@ -787,7 +790,8 @@ trait Typers extends Modes with Adaptations {
// or raw type (tree.symbol.isJavaDefined && context.unit.isJava), types must be of kind *,
// and thus parameterized types must be applied to their type arguments
// @M TODO: why do kind-* tree's have symbols, while higher-kinded ones don't?
- MissingTypeParametersError(tree)
+ errorTree(tree, tree.symbol + " takes type parameters")
+ tree setType tree.tpe
} else if ( // (7.1) @M: check kind-arity
// @M: removed check for tree.hasSymbol and replace tree.symbol by tree.tpe.symbol (TypeTree's must also be checked here, and they don't directly have a symbol)
(inHKMode(mode)) &&
@@ -802,7 +806,9 @@ trait Typers extends Modes with Adaptations {
// Note that we treat Any and Nothing as kind-polymorphic.
// We can't perform this check when typing type arguments to an overloaded method before the overload is resolved
// (or in the case of an error type) -- this is indicated by pt == WildcardType (see case TypeApply in typed1).
- KindArityMismatchError(tree, pt)
+ errorTree(tree, tree.tpe + " takes " + countElementsAsString(tree.tpe.typeParams.length, "type parameter") +
+ ", expected: " + countAsString(pt.typeParams.length))
+ tree setType tree.tpe
} else tree match { // (6)
case TypeTree() => tree
case _ => TypeTree(tree.tpe) setOriginal (tree)
@@ -822,18 +828,13 @@ trait Typers extends Modes with Adaptations {
val tree1 = TypeTree(clazz.primaryConstructor.tpe.asSeenFrom(prefix, clazz.owner))
.setOriginal(tree)
- inferConstructorInstance(tree1, clazz.typeParams, pt) match {
- case Some(err) =>
- if (tree1.containsError())
- Block(List(err), tree1)
- else err
- case _ => tree1
- }
+ inferConstructorInstance(tree1, clazz.typeParams, pt)
+ tree1
} else {
tree
}
} else {
- CaseClassConstructorError(tree)
+ errorTree(tree, tree.symbol + " is not a case class constructor, nor does it have an unapply/unapplySeq method")
}
}
@@ -851,8 +852,7 @@ trait Typers extends Modes with Adaptations {
case other =>
other
}
- if (qual.containsError()) qual // Fail quickly
- else typed(atPos(tree.pos)(Select(qual, nme.apply)), mode, pt)
+ typed(atPos(tree.pos)(Select(qual, nme.apply)), mode, pt)
}
// begin adapt
@@ -867,10 +867,8 @@ trait Typers extends Modes with Adaptations {
}
treeCopy.Literal(tree, value)
case OverloadedType(pre, alts) if !inFunMode(mode) => // (1)
- inferExprAlternative(tree, pt) match {
- case Some(err) => err
- case _ => adapt(tree, mode, pt, original)
- }
+ inferExprAlternative(tree, pt)
+ adapt(tree, mode, pt, original)
case NullaryMethodType(restpe) => // (2)
adapt(tree setType restpe, mode, pt, original)
case TypeRef(_, ByNameParamClass, List(arg)) if ((mode & EXPRmode) != 0) => // (2)
@@ -929,10 +927,7 @@ trait Typers extends Modes with Adaptations {
} else {
if (inPatternMode(mode)) {
if ((tree.symbol ne null) && tree.symbol.isModule)
- inferModulePattern(tree, pt) match {
- case Some(err) => return err
- case _ =>
- }
+ inferModulePattern(tree, pt)
if (isPopulated(tree.tpe, approximateAbstracts(pt)))
return tree
}
@@ -960,8 +955,7 @@ trait Typers extends Modes with Adaptations {
if (!context.undetparams.isEmpty) {
return instantiate(tree, mode, pt)
}
- val validTree = !tree.containsErrorOrIsErrorTyped()
- if (context.implicitsEnabled && !pt.isError && validTree) {
+ if (context.implicitsEnabled && !tree.tpe.isError && !pt.isError) {
// (14); the condition prevents chains of views
debuglog("inferring view from " + tree.tpe + " to " + pt)
val coercion = inferView(tree, tree.tpe, pt, true)
@@ -978,7 +972,7 @@ trait Typers extends Modes with Adaptations {
new ApplyImplicitView(coercion, List(tree)) setPos tree.pos, mode, pt)
}
}
- if (isCodeType(pt) && !isCodeType(tree.tpe) && validTree)
+ if (isCodeType(pt) && !isCodeType(tree.tpe) && !tree.tpe.isError)
return adapt(lifted(tree), mode, pt, original)
}
if (settings.debug.value) {
@@ -1009,7 +1003,7 @@ trait Typers extends Modes with Adaptations {
context.unit.warning(tree.pos, "recovering from existential Skolem type error in tree \n" + tree + "\nwith type " + tree.tpe + "\n expected type = " + pt + "\n context = " + context.tree)
adapt(tree, mode, pt.subst(pt.existentialSkolems, pt.existentialSkolems map (_ => WildcardType)))
} else
- TypeErrorTree(tree, pt, ex)
+ throw ex
}
}
}
@@ -1017,10 +1011,8 @@ trait Typers extends Modes with Adaptations {
}
def instantiate(tree: Tree, mode: Int, pt: Type): Tree = {
- inferExprInstance(tree, context.extractUndetparams(), pt) match {
- case (Some(err), _) => err
- case _ => adapt(tree, mode, pt)
- }
+ inferExprInstance(tree, context.extractUndetparams(), pt)
+ adapt(tree, mode, pt)
}
/** If the expected type is Unit: try instantiating type arguments
* with expected type Unit, but if that fails, try again with pt = WildcardType
@@ -1028,8 +1020,8 @@ trait Typers extends Modes with Adaptations {
*/
def instantiateExpectingUnit(tree: Tree, mode: Int): Tree = {
val savedUndetparams = context.undetparams
- instantiate(tree, mode, UnitClass.tpe) match {
- case t: Tree if !t.containsError() => t
+ silent(_.instantiate(tree, mode, UnitClass.tpe)) match {
+ case t: Tree => t
case _ =>
context.undetparams = savedUndetparams
val valueDiscard = atPos(tree.pos)(Block(List(instantiate(tree, mode, WildcardType)), Literal(Constant())))
@@ -1077,48 +1069,40 @@ trait Typers extends Modes with Adaptations {
adaptToMember(qual, HasMethodMatching(name, args map (_.tpe), restpe))
if (pt != WildcardType) {
silent(_ => doAdapt(pt)) match {
- case result: Tree if result != qual && !result.containsError() =>
+ case result: Tree if result != qual =>
result
case _ =>
debuglog("fallback on implicits in adaptToArguments: "+qual+" . "+name)
doAdapt(WildcardType)
}
- } else {
+ } else
doAdapt(pt)
- }
}
- /** Try to apply an implicit conversion to `qual` so that it contains
- * a method `name`. If that's ambiguous try taking arguments into
- * account using `adaptToArguments`.
+ /** Try o apply an implicit conversion to `qual` to that it contains
+ * a method `name`. If that's ambiguous try taking arguments into account using `adaptToArguments`.
*/
def adaptToMemberWithArgs(tree: Tree, qual: Tree, name: Name, mode: Int): Tree = {
- def onError(reportError: => Tree): Tree = {
- // last ditch effort
+ try {
+ adaptToMember(qual, HasMember(name))
+ } catch {
+ case ex: TypeError =>
+ // this happens if implicits are ambiguous; try again with more context info.
+ // println("last ditch effort: "+qual+" . "+name)
context.tree match {
case Apply(tree1, args) if (tree1 eq tree) && args.nonEmpty => // try handling the arguments
// println("typing args: "+args)
silent(_.typedArgs(args, mode)) match {
- case xs: List[_] =>
- val args = xs.asInstanceOf[List[Tree]]
- if (args exists (_.containsError()))
- reportError
- else
- adaptToArguments(qual, name, args, WildcardType)
- case _ =>
- reportError
+ case args: List[_] =>
+ adaptToArguments(qual, name, args.asInstanceOf[List[Tree]], WildcardType)
+ case _ =>
+ throw ex
}
case _ =>
- reportError
+ // println("not in an apply: "+context.tree+"/"+tree)
+ throw ex
}
}
- try {
- val res = adaptToMember(qual, HasMember(name))
- if (res.containsError()) onError(res) else res
- } catch {
- case ex: TypeError =>
- onError(AdaptToMemberWithArgsError(tree, ex))
- }
}
/** Try to apply an implicit conversion to `qual` to that it contains a
@@ -1151,7 +1135,6 @@ trait Typers extends Modes with Adaptations {
if (templ.parents.isEmpty) List()
else try {
val clazz = context.owner
- var pending: List[ErrorTree] = List()
// Normalize supertype and mixins so that supertype is always a class, not a trait.
var supertpt = typedTypeConstructor(templ.parents.head)
@@ -1160,13 +1143,7 @@ trait Typers extends Modes with Adaptations {
// If first parent is a trait, make it first mixin and add its superclass as first parent
while ((supertpt.tpe.typeSymbol ne null) && supertpt.tpe.typeSymbol.initialize.isTrait) {
val supertpt1 = typedType(supertpt)
- if (supertpt1.containsError()) {
- // we assume here that all errors in supertpt1 have already been reported
- supertpt setType ErrorType
- } else if (supertpt1.tpe.isError) {
- // Should not happen with ErrorTree
- assert(false, "Erroneous SuperType contains Error tree")
- } else {
+ if (!supertpt1.tpe.isError) {
mixins = supertpt1 :: mixins
supertpt = TypeTree(supertpt1.tpe.parents.head) setPos supertpt.pos.focus
}
@@ -1210,20 +1187,14 @@ trait Typers extends Modes with Adaptations {
val cbody2 = newTyper(cscope) // called both during completion AND typing.
.typePrimaryConstrBody(clazz,
cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (_.map(_.duplicate)))
-
- if (cbody2.containsError())
- pending = errorTreesFinder(cbody2).toList ::: pending
-
superCall match {
case Apply(_, _) =>
val sarg = treeInfo.firstArgument(superCall)
if (sarg != EmptyTree && supertpe.typeSymbol != firstParent)
- pending ::= ConstrArgsInTraitParentTpeError(sarg, firstParent)
- if (!supertparams.isEmpty)
- supertpt = TypeTree(cbody2.tpe) setPos supertpt.pos.focus
+ error(sarg.pos, firstParent+" is a trait; does not take constructor arguments")
+ if (!supertparams.isEmpty) supertpt = TypeTree(cbody2.tpe) setPos supertpt.pos.focus
case _ =>
- if (!supertparams.isEmpty)
- pending ::= MissingTypeArgumentsParentTpeError(supertpt)
+ if (!supertparams.isEmpty) error(supertpt.pos, "missing type arguments")
}
val preSuperVals = treeInfo.preSuperFields(templ.body)
@@ -1233,8 +1204,7 @@ trait Typers extends Modes with Adaptations {
(preSuperStats, preSuperVals).zipped map { case (ldef, gdef) => gdef.tpt.tpe = ldef.symbol.tpe }
case _ =>
- if (!supertparams.isEmpty)
- pending ::= MissingTypeArgumentsParentTpeError(supertpt)
+ if (!supertparams.isEmpty) error(supertpt.pos, "missing type arguments")
}
/* experimental: early types as type arguments
val hasEarlyTypes = templ.body exists (treeInfo.isEarlyTypeDef)
@@ -1246,11 +1216,12 @@ trait Typers extends Modes with Adaptations {
*/
//Console.println("parents("+clazz") = "+supertpt :: mixins);//DEBUG
- supertpt :: pending ::: mixins mapConserve (tpt => checkNoEscaping.privates(clazz, tpt))
+ supertpt :: mixins mapConserve (tpt => checkNoEscaping.privates(clazz, tpt))
} catch {
case ex: TypeError =>
- // TODO: remove once error trees refactoring is done
- List(ParentTypesError(templ, ex))
+ templ.tpe = null
+ reportTypeError(templ.pos, ex)
+ List(TypeTree(AnyRefClass.tpe))
}
/** <p>Check that</p>
@@ -1267,35 +1238,32 @@ trait Typers extends Modes with Adaptations {
* <li>no two parents define same symbol.</li>
* </ul>
*/
- def validateParentClasses(parents: List[Tree], selfType: Type): Option[PendingErrors] = {
- var pending: List[ErrorTree] = List()
+ def validateParentClasses(parents: List[Tree], selfType: Type) {
def validateParentClass(parent: Tree, superclazz: Symbol) {
- if (!parent.containsErrorOrIsErrorTyped()) {
+ if (!parent.tpe.isError) {
val psym = parent.tpe.typeSymbol.initialize
- checkClassType(parent, false, true) match {
- case t@Some(err) =>
- pending = err::pending
- case _ =>
- }
+ checkClassType(parent, false, true)
if (psym != superclazz) {
if (psym.isTrait) {
val ps = psym.info.parents
if (!ps.isEmpty && !superclazz.isSubClass(ps.head.typeSymbol))
- pending = ParentSuperSubclassError(parent.pos, superclazz, ps.head.typeSymbol, psym)::pending
+ error(parent.pos, "illegal inheritance; super"+superclazz+
+ "\n is not a subclass of the super"+ps.head.typeSymbol+
+ "\n of the mixin " + psym)
} else {
- pending = ParentNotATraitMixinError(parent.pos, psym)::pending
+ error(parent.pos, psym+" needs to be a trait to be mixed in")
}
}
- if (psym.isFinal)
- pending = ParentFinalInheritanceError(parent.pos, psym)::pending
-
+ if (psym.isFinal) {
+ error(parent.pos, "illegal inheritance from final "+psym)
+ }
if (psym.isSealed && !phase.erasedTypes) {
// AnyVal is sealed, but we have to let the value classes through manually
if (context.unit.source.file == psym.sourceFile || isValueClass(context.owner))
psym addChild context.owner
else
- pending = ParentSealedInheritanceError(parent.pos, psym)::pending
+ error(parent.pos, "illegal inheritance from sealed "+psym)
}
if (!(selfType <:< parent.tpe.typeOfThis) &&
!phase.erasedTypes &&
@@ -1307,19 +1275,18 @@ trait Typers extends Modes with Adaptations {
//Console.println(context.owner);//DEBUG
//Console.println(context.owner.unsafeTypeParams);//DEBUG
//Console.println(List.fromArray(context.owner.info.closure));//DEBUG
- pending = ParentSelfTypeConformanceError(parent.pos, selfType, parent)::pending
+ error(parent.pos, "illegal inheritance;\n self-type "+
+ selfType+" does not conform to "+parent +
+ "'s selftype "+parent.tpe.typeOfThis)
if (settings.explaintypes.value) explainTypes(selfType, parent.tpe.typeOfThis)
}
if (parents exists (p => p != parent && p.tpe.typeSymbol == psym && !psym.isError))
- pending = ParentInheritedTwiceError(parent.pos, psym)::pending
+ error(parent.pos, psym+" is inherited twice")
}
}
- if (parents.forall(!_.containsError())) {
- // proceed as normal, we know that head.tpe is not error?
- if (!parents.isEmpty && !parents.head.tpe.isError)
- for (p <- parents) validateParentClass(p, parents.head.tpe.typeSymbol)
- }
- if (pending.isEmpty) None else Some(PendingErrors(pending.reverse))
+
+ if (!parents.isEmpty && !parents.head.tpe.isError)
+ for (p <- parents) validateParentClass(p, parents.head.tpe.typeSymbol)
/*
if (settings.Xshowcls.value != "" &&
@@ -1330,11 +1297,11 @@ trait Typers extends Modes with Adaptations {
*/
}
- def checkFinitary(classinfo: ClassInfoType): List[ErrorTree] = {
+ def checkFinitary(classinfo: ClassInfoType) {
val clazz = classinfo.typeSymbol
-
- clazz.typeParams.map(tparam =>
+ for (tparam <- clazz.typeParams) {
if (classinfo.expansiveRefs(tparam) contains tparam) {
+ error(tparam.pos, "class graph is not finitary because type parameter "+tparam.name+" is expansively recursive")
val newinfo = ClassInfoType(
classinfo.parents map (_.instantiateTypeParams(List(tparam), List(AnyRefClass.tpe))),
classinfo.decls,
@@ -1345,9 +1312,8 @@ trait Typers extends Modes with Adaptations {
case _ => newinfo
}
}
- Some(FinitaryError(tparam))
- } else None
- ).flatten
+ }
+ }
}
/**
@@ -1434,16 +1400,15 @@ trait Typers extends Modes with Adaptations {
val getter = if (isDeferred) value else value.getter(value.owner)
assert(getter != NoSymbol, stat)
- val gs = new ListBuffer[Tree]
if (getter.isOverloaded)
- gs.append(GetterDefinedTwiceError(getter))
+ error(getter.pos, getter+" is defined twice")
getter.setAnnotations(memberAnnots(allAnnots, GetterTargetClass))
if (value.isLazy) List(stat)
else {
- val vdef = treeCopy.ValDef(stat, mods | PrivateLocal, nme.getterToLocal(name), tpt, rhs)
- val getterDef = atPos(vdef.pos.focus) {
+ val vdef = treeCopy.ValDef(stat, mods | PRIVATE | LOCAL, nme.getterToLocal(name), tpt, rhs)
+ val getterDef: DefDef = atPos(vdef.pos.focus) {
if (isDeferred) {
val r = DefDef(getter, EmptyTree)
r.tpt.asInstanceOf[TypeTree].setOriginal(tpt) // keep type tree of original abstract field
@@ -1459,21 +1424,18 @@ trait Typers extends Modes with Adaptations {
r
}
}
-
- def setterDef(setter: Symbol, isBean: Boolean = false): Tree = {
+ checkNoEscaping.privates(getter, getterDef.tpt)
+ def setterDef(setter: Symbol, isBean: Boolean = false): DefDef = {
setter setAnnotations memberAnnots(allAnnots, if (isBean) BeanSetterTargetClass else SetterTargetClass)
val defTree =
if ((mods hasFlag DEFERRED) || (setter hasFlag OVERLOADED)) EmptyTree
else Assign(Select(This(value.owner), value), Ident(setter.paramss.head.head))
- typedPos(vdef.pos.focus)(DefDef(setter, defTree))
+ typedPos(vdef.pos.focus)(DefDef(setter, defTree)).asInstanceOf[DefDef]
}
- val privateErrors = checkNoEscaping.privates(getter, getterDef.tpt)
- if (privateErrors.containsError())
- privateErrors.foreach(err => gs.append(err))
-
+ val gs = new ListBuffer[DefDef]
gs.append(getterDef)
if (mods.isMutable) {
val setter = getter.setter(value.owner)
@@ -1489,7 +1451,7 @@ trait Typers extends Modes with Adaptations {
if (beanGetter == NoSymbol) {
// the namer decides wether to generate these symbols or not. at that point, we don't
// have symbolic information yet, so we only look for annotations named "BeanProperty".
- gs.append(BeanPropertyAnnotationLimitationError(stat))
+ unit.error(stat.pos, "implementation limitation: the BeanProperty annotation cannot be used in a type alias or renamed import")
}
beanGetter.setAnnotations(memberAnnots(allAnnots, BeanGetterTargetClass))
if (mods.isMutable && beanGetter != NoSymbol) {
@@ -1588,32 +1550,20 @@ trait Typers extends Modes with Adaptations {
// the following is necessary for templates generated later
assert(clazz.info.decls != EmptyScope)
enterSyms(context.outer.make(templ, clazz, clazz.info.decls), templ.body)
-
- var doNotTypeBody = false
- val parents2 = validateParentClasses(parents1, selfType) match {
- case Some(err) =>
- doNotTypeBody = err.pending0.exists(_.isInstanceOf[BlockingError])
- List(err)
- case _ => parents1
- }
+ validateParentClasses(parents1, selfType)
if (clazz.isCase)
validateNoCaseAncestor(clazz)
if ((clazz isSubClass ClassfileAnnotationClass) && !clazz.owner.isPackageClass)
unit.error(clazz.pos, "inner classes cannot be classfile annotations")
-
- val finitiaryErrs =
- if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members
- checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType])
- else List()
+ if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members
+ checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType])
val body =
- if (phase.id <= currentRun.typerPhase.id && !reporter.hasErrors && !doNotTypeBody)
+ if (phase.id <= currentRun.typerPhase.id && !reporter.hasErrors)
templ.body flatMap addGetterSetter
else templ.body
-
- val body1 = if (doNotTypeBody) body else typedStats(body, templ.symbol)
- val body2 = finitiaryErrs ++ body1
- treeCopy.Template(templ, parents2, self1, body2) setType clazz.tpe
+ val body1 = typedStats(body, templ.symbol)
+ treeCopy.Template(templ, parents1, self1, body1) setType clazz.tpe
}
/** Remove definition annotations from modifiers (they have been saved
@@ -1631,29 +1581,22 @@ trait Typers extends Modes with Adaptations {
val sym = vdef.symbol
val typer1 = constrTyperIf(sym.isParameter && sym.owner.isConstructor)
val typedMods = removeAnnotations(vdef.mods)
- var pending: List[ErrorTree] = List()
// complete lazy annotations
val annots = sym.annotations
var tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt))
- checkNonCyclic(vdef, tpt1) match {
- case Some(cyclic) =>
- pending = cyclic::pending
- case _ =>
- }
+ checkNonCyclic(vdef, tpt1)
if (sym.hasAnnotation(definitions.VolatileAttr)) {
if (!sym.isMutable)
- pending = VolatileValueError(vdef)::pending
+ error(vdef.pos, "values cannot be volatile")
else if (sym.isFinal)
- pending = FinalVolatileVarError(vdef)::pending
+ error(vdef.pos, "final vars cannot be volatile")
}
val rhs1 =
- if (tpt1.containsError()) {
- vdef.rhs
- } else if (vdef.rhs.isEmpty) {
+ if (vdef.rhs.isEmpty) {
if (sym.isVariable && sym.owner.isTerm && phase.id <= currentRun.typerPhase.id)
- pending = LocalVarUninitializedError(vdef)::pending
+ error(vdef.pos, "local variables must be initialized")
vdef.rhs
} else {
val tpt2 = if (sym.hasDefault) {
@@ -1676,10 +1619,7 @@ trait Typers extends Modes with Adaptations {
} else tpt1.tpe
newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(vdef.rhs, EXPRmode | BYVALmode, tpt2)
}
- val rhs2 = if (pending.nonEmpty) {
- PendingErrors(pending.reverse)
- } else rhs1
- treeCopy.ValDef(vdef, typedMods, vdef.name, tpt1, checkDead(rhs2)) setType NoType
+ treeCopy.ValDef(vdef, typedMods, vdef.name, tpt1, checkDead(rhs1)) setType NoType
}
/** Enter all aliases of local parameter accessors.
@@ -1688,7 +1628,7 @@ trait Typers extends Modes with Adaptations {
* @param vparamss ...
* @param rhs ...
*/
- def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree): List[ErrorTree] = {
+ def computeParamAliases(clazz: Symbol, vparamss: List[List[ValDef]], rhs: Tree) {
debuglog("computing param aliases for "+clazz+":"+clazz.primaryConstructor.tpe+":"+rhs)//debug
def decompose(call: Tree): (Tree, List[Tree]) = call match {
case Apply(fn, args) =>
@@ -1706,17 +1646,16 @@ trait Typers extends Modes with Adaptations {
val (superConstr, superArgs) = decompose(rhs)
assert(superConstr.symbol ne null)//debug
- var pending: List[ErrorTree] = List()
// an object cannot be allowed to pass a reference to itself to a superconstructor
// because of initialization issues; bug #473
for (arg <- superArgs ; tree <- arg) {
val sym = tree.symbol
if (sym != null && (sym.info.baseClasses contains clazz)) {
if (sym.isModule)
- pending = SuperConstrReferenceError(tree)::pending
+ error(tree.pos, "super constructor cannot be passed a self reference unless parameter is declared by-name")
tree match {
case This(qual) =>
- pending = SuperConstrArgsThisReferenceError(tree)::pending
+ error(tree.pos, "super constructor arguments cannot reference unconstructed `this`")
case _ => ()
}
}
@@ -1754,8 +1693,6 @@ trait Typers extends Modes with Adaptations {
}
}
}
-
- pending
}
/** Check if a structurally defined method violates implementation restrictions.
@@ -1804,7 +1741,7 @@ trait Typers extends Modes with Adaptations {
lookupVariable(name.toString.substring(1), enclClass) match {
case Some(repl) =>
silent(_.typedTypeConstructor(stringParser(repl).typ())) match {
- case tpt: Tree if !tpt.containsError()=>
+ case tpt: Tree =>
val alias = enclClass.newAliasType(useCase.pos, name.toTypeName)
val tparams = cloneSymbols(tpt.tpe.typeSymbol.typeParams, alias)
alias setInfo typeFun(tparams, appliedType(tpt.tpe, tparams map (_.tpe)))
@@ -1832,14 +1769,7 @@ trait Typers extends Modes with Adaptations {
* @return ...
*/
def typedDefDef(ddef: DefDef): DefDef = {
- def logErrorTree(t: Tree, errs: List[ErrorTree]) =
- t match {
- case errTree: ErrorTree => errTree::errs
- case _ => errs
- }
-
val meth = ddef.symbol
- var pending: List[ErrorTree] = List()
reenterTypeParams(ddef.tparams)
reenterValueParams(ddef.vparamss)
@@ -1861,22 +1791,17 @@ trait Typers extends Modes with Adaptations {
val annots = meth.annotations
for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1)
- if (isRepeatedParamType(vparam1.symbol.tpe)) {
- pending = StarParamNotLastError(vparam1)::pending
- }
+ if (isRepeatedParamType(vparam1.symbol.tpe))
+ error(vparam1.pos, "*-parameter must come last")
var tpt1 = checkNoEscaping.privates(meth, typedType(ddef.tpt))
if (!settings.YdepMethTpes.value) {
for (vparams <- vparamss1; vparam <- vparams) {
- pending = logErrorTree(checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt), pending)
+ checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); ()
}
- pending = logErrorTree(checkNoEscaping.locals(context.scope, WildcardType, tpt1), pending)
- }
- checkNonCyclic(ddef, tpt1) match {
- case Some(cylic) =>
- pending = cylic::pending
- case _ =>
+ checkNoEscaping.locals(context.scope, WildcardType, tpt1)
}
+ checkNonCyclic(ddef, tpt1)
ddef.tpt.setType(tpt1.tpe)
val typedMods = removeAnnotations(ddef.mods)
var rhs1 =
@@ -1885,41 +1810,35 @@ trait Typers extends Modes with Adaptations {
(!meth.owner.isClass ||
meth.owner.isModuleClass ||
meth.owner.isAnonOrRefinementClass))
- pending = InvalidConstructorDefError(ddef)::pending
+ error(ddef.pos, "constructor definition not allowed here")
typed(ddef.rhs)
} else {
transformedOrTyped(ddef.rhs, EXPRmode, tpt1.tpe)
}
if (meth.isPrimaryConstructor && meth.isClassConstructor &&
- phase.id <= currentRun.typerPhase.id && !reporter.hasErrors) {
- computeParamAliases(meth.owner, vparamss1, rhs1) match {
- case Nil => ()
- case pending0 =>
- pending = pending0 ::: pending
- }
- }
+ phase.id <= currentRun.typerPhase.id && !reporter.hasErrors)
+ computeParamAliases(meth.owner, vparamss1, rhs1)
if (tpt1.tpe.typeSymbol != NothingClass && !context.returnsSeen && rhs1.tpe.typeSymbol != NothingClass)
rhs1 = checkDead(rhs1)
if (phase.id <= currentRun.typerPhase.id && meth.owner.isClass &&
meth.paramss.exists(ps => ps.exists(_.hasDefaultFlag) && isRepeatedParamType(ps.last.tpe)))
- pending = StarWithDefaultError(meth)::pending
+ error(meth.pos, "a parameter section with a `*'-parameter is not allowed to have default arguments")
if (phase.id <= currentRun.typerPhase.id) {
val allParams = meth.paramss.flatten
for (p <- allParams) {
for (n <- p.deprecatedParamName) {
if (allParams.exists(p1 => p1.name == n || (p != p1 && p1.deprecatedParamName.exists(_ == n))))
- pending = DeprecatedParamNameError(p, n)::pending
+ error(p.pos, "deprecated parameter name "+ n +" has to be distinct from any other parameter name (deprecated or not).")
}
}
}
if (meth.isStructuralRefinementMember)
checkMethodStructuralCompatible(meth)
- if (pending.nonEmpty)
- rhs1 = wrapInBlock(PendingErrors(pending.reverse), rhs1)
+
treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
@@ -1948,22 +1867,15 @@ trait Typers extends Modes with Adaptations {
}
val rhs1 = checkNoEscaping.privates(tdef.symbol, typedType(tdef.rhs))
- val rhs2 = checkNonCyclic(tdef.symbol) match {
- case Some(cyclic) =>
- wrapInBlock(cyclic, rhs1)
- case None =>
- if (tdef.symbol.owner.isType)
- rhs1.tpe match {
- case TypeBounds(lo1, hi1) if (!(lo1 <:< hi1)) =>
- wrapInBlock(
- LowerBoundError(tdef, lo1, hi1),
- rhs1)
- case _ =>
- rhs1
- }
- else rhs1
- }
- treeCopy.TypeDef(tdef, typedMods, tdef.name, tparams1, rhs2) setType NoType
+ checkNonCyclic(tdef.symbol)
+ if (tdef.symbol.owner.isType)
+ rhs1.tpe match {
+ case TypeBounds(lo1, hi1) =>
+ if (!(lo1 <:< hi1))
+ error(tdef.pos, "lower bound "+lo1+" does not conform to upper bound "+hi1)
+ case _ =>
+ }
+ treeCopy.TypeDef(tdef, typedMods, tdef.name, tparams1, rhs1) setType NoType
}
private def enterLabelDef(stat: Tree) {
@@ -2080,17 +1992,10 @@ trait Typers extends Modes with Adaptations {
*/
def typedCase(cdef: CaseDef, pattpe: Type, pt: Type): CaseDef = {
// verify no _* except in last position
- var pending: List[ErrorTree] = List()
for (Apply(_, xs) <- cdef.pat ; x <- xs dropRight 1 ; if treeInfo isStar x)
- pending = StarPositionInPatternError(x.pos)::pending
+ error(x.pos, "_* may only come last")
- val pat0 = typedPattern(cdef.pat, pattpe)
- val pat1: Tree = pending match {
- case List() =>
- pat0
- case _ =>
- wrapInBlock(PendingErrors(pending.reverse), pat0)
- }
+ val pat1: Tree = typedPattern(cdef.pat, pattpe)
// When case classes have more than two parameter lists, the pattern ends
// up typed as a method. We only pattern match on the first parameter
// list, so substitute the final result type of the method, i.e. the type
@@ -2106,17 +2011,16 @@ trait Typers extends Modes with Adaptations {
val guard1: Tree = if (cdef.guard == EmptyTree) EmptyTree
else typed(cdef.guard, BooleanClass.tpe)
-
var body1: Tree = typed(cdef.body, pt)
if (!context.savedTypeBounds.isEmpty) {
body1.tpe = context.restoreTypeBounds(body1.tpe)
if (isFullyDefined(pt) && !(body1.tpe <:< pt)) {
- body1 = typed {
- atPos(body1.pos) {
- // @M no need for pt.normalize here, is done in erasure
- TypeApply(Select(body1, Any_asInstanceOf), List(TypeTree(pt)))
+ body1 =
+ typed {
+ atPos(body1.pos) {
+ TypeApply(Select(body1, Any_asInstanceOf), List(TypeTree(pt))) // @M no need for pt.normalize here, is done in erasure
+ }
}
- }
}
}
// body1 = checkNoEscaping.locals(context.scope, pt, body1)
@@ -2139,7 +2043,7 @@ trait Typers extends Modes with Adaptations {
val codeExpected = !forMSIL && (pt.typeSymbol isNonBottomSubClass CodeClass)
if (numVparams > definitions.MaxFunctionArity)
- return MaxFunctionArityError(fun)
+ return errorTree(fun, "implementation restricts functions to " + definitions.MaxFunctionArity + " parameters")
def decompose(pt: Type): (Symbol, List[Type], Type) =
if ((isFunctionType(pt)
@@ -2155,10 +2059,9 @@ trait Typers extends Modes with Adaptations {
(FunctionClass(numVparams), fun.vparams map (x => NoType), WildcardType)
val (clazz, argpts, respt) = decompose(if (codeExpected) pt.normalize.typeArgs.head else pt)
- val vparamErrors = new mutable.HashMap[ValDef, ErrorTree]()
if (argpts.lengthCompare(numVparams) != 0)
- WrongNumberOfParametersError(fun, argpts)
+ errorTree(fun, "wrong number of parameters; expected = " + argpts.length)
else {
val vparamSyms = (fun.vparams, argpts).zipped map { (vparam, argpt) =>
if (vparam.tpt.isEmpty) {
@@ -2168,7 +2071,7 @@ trait Typers extends Modes with Adaptations {
fun match {
case etaExpansion(vparams, fn, args) if !codeExpected =>
silent(_.typed(fn, forFunMode(mode), pt)) match {
- case fn1: Tree if context.undetparams.isEmpty && !fn1.containsError() =>
+ case fn1: Tree if context.undetparams.isEmpty =>
// if context,undetparams is not empty, the function was polymorphic,
// so we need the missing arguments to infer its type. See #871
//println("typing eta "+fun+":"+fn1.tpe+"/"+context.undetparams)
@@ -2179,7 +2082,7 @@ trait Typers extends Modes with Adaptations {
}
case _ =>
}
- vparamErrors += ((vparam, MissingParameterTypeError(fun, vparam, pt)))
+ error(vparam.pos, missingParameterTypeMsg(fun, vparam, pt))
ErrorType
}
if (!vparam.tpt.pos.isDefined) vparam.tpt setPos vparam.pos.focus
@@ -2189,21 +2092,14 @@ trait Typers extends Modes with Adaptations {
vparam.symbol
}
- val vparams = fun.vparams mapConserve (p =>
- { val p0 = typedValDef(p)
- if (vparamErrors.contains(p)) {
- treeCopy.ValDef(p0, p0.mods, p0.name, vparamErrors(p), p0.rhs)
- }
- else p0
- })
+ val vparams = fun.vparams mapConserve (typedValDef)
// for (vparam <- vparams) {
// checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); ()
// }
- val body0 = typed(fun.body, respt)
+ var body = typed(fun.body, respt)
val formals = vparamSyms map (_.tpe)
- val (restpe0, errs) = packedType(body0, fun.symbol)//.deconst
- val body = if (errs.isEmpty) body0 else Block(errs, body0)
- val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe0.deconst)
+ val restpe = packedType(body, fun.symbol).deconst
+ val funtpe = typeRef(clazz.tpe.prefix, clazz, formals :+ restpe)
// body = checkNoEscaping.locals(context.scope, restpe, body)
val fun1 = treeCopy.Function(fun, vparams, body).setType(funtpe)
if (codeExpected) lifted(fun1) else fun1
@@ -2236,10 +2132,11 @@ trait Typers extends Modes with Adaptations {
case Some(imp1: Import) => imp1
case None => log("unhandled import: "+imp+" in "+unit); imp
}
+
private def isWarnablePureExpression(tree: Tree) = tree match {
case EmptyTree | Literal(Constant(())) => false
case _ =>
- !tree.containsErrorOrIsErrorTyped() && (treeInfo isPureExpr tree) && {
+ (treeInfo isPureExpr tree) && {
val sym = tree.symbol
(sym == null) || !(sym.isModule || sym.isLazy) || {
debuglog("'Pure' but side-effecting expression in statement position: " + tree)
@@ -2255,7 +2152,7 @@ trait Typers extends Modes with Adaptations {
val localTarget = stats exists includesTargetPos
def typedStat(stat: Tree): Tree = {
if (context.owner.isRefinementClass && !treeInfo.isDeclarationOrTypeDef(stat))
- OnlyDeclarationsError(stat)
+ errorTree(stat, "only declarations allowed here")
else
stat match {
case imp @ Import(_, _) =>
@@ -2273,19 +2170,16 @@ trait Typers extends Modes with Adaptations {
// XXX this creates a spurious dead code warning if an exception is thrown
// in a constructor, even if it is the only thing in the constructor.
val result = checkDead(localTyper.typed(stat, EXPRmode | BYVALmode, WildcardType))
-
- val result1 = if (treeInfo.isSelfOrSuperConstrCall(result)) {
- context.inConstructorSuffix = true
- if (treeInfo.isSelfConstrCall(result) && result.symbol.pos.pointOrElse(0) >= exprOwner.enclMethod.pos.pointOrElse(0))
- wrapInBlock(ConstructorsOrderError(stat), result)
- else result
- } else result
-
- if (isWarnablePureExpression(result1)) context.warning(stat.pos,
+ if (treeInfo.isSelfOrSuperConstrCall(result)) {
+ context.inConstructorSuffix = true
+ if (treeInfo.isSelfConstrCall(result) && result.symbol.pos.pointOrElse(0) >= exprOwner.enclMethod.pos.pointOrElse(0))
+ error(stat.pos, "called constructor's definition must precede calling constructor's definition")
+ }
+ if (isWarnablePureExpression(result)) context.warning(stat.pos,
"a pure expression does nothing in statement position; " +
"you may be omitting necessary parentheses"
)
- result1
+ result
}
}
}
@@ -2317,7 +2211,8 @@ trait Typers extends Modes with Adaptations {
// error for this is issued in RefChecks.checkDefaultsInOverloaded
if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefaultFlag &&
!e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) {
- newStats += DefDefinedTwiceError(e.sym, e1.sym)
+ error(e.sym.pos, e1.sym+" is defined twice"+
+ {if(!settings.debug.value) "" else " in "+unit.toString})
scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779
}
e1 = scope.lookupNextEntry(e1)
@@ -2484,15 +2379,8 @@ trait Typers extends Modes with Adaptations {
arg1
}
context.undetparams = undetparams
-
- inferMethodAlternative(fun, undetparams, argtpes.toList, pt,
- varArgsOnly = treeInfo.isWildcardStarArgList(args)) match {
- case Some(err) =>
- err
- case _ =>
- doTypedApply(tree, adapt(fun, forFunMode(mode), WildcardType), args1, mode, pt)
- }
-
+ inferMethodAlternative(fun, undetparams, argtpes.toList, pt, varArgsOnly = treeInfo.isWildcardStarArgList(args))
+ doTypedApply(tree, adapt(fun, forFunMode(mode), WildcardType), args1, mode, pt)
case mt @ MethodType(params, _) =>
val paramTypes = mt.paramTypes
@@ -2512,7 +2400,7 @@ trait Typers extends Modes with Adaptations {
// the inner "doTypedApply" does "extractUndetparams" => restore when it fails
val savedUndetparams = context.undetparams
silent(_.doTypedApply(tree, fun, tupleArgs, mode, pt)) match {
- case t: Tree if !t.containsError() =>
+ case t: Tree =>
// Depending on user options, may warn or error here if
// a Unit or tuple was inserted.
Some(t) filter (tupledTree =>
@@ -2520,7 +2408,7 @@ trait Typers extends Modes with Adaptations {
|| tupledTree.symbol == null
|| checkValidAdaptation(tupledTree, args)
)
- case _ =>
+ case ex =>
context.undetparams = savedUndetparams
None
}
@@ -2538,24 +2426,19 @@ trait Typers extends Modes with Adaptations {
if (mt.isErroneous) setError(tree)
else if (inPatternMode(mode))
// #2064
- WrongNumberOfArgsError(tree, fun)
+ errorTree(tree, "wrong number of arguments for "+ treeSymTypeMsg(fun))
else if (lencmp > 0) {
- tryTupleApply getOrElse TooManyArgsNamesDefaultsError(tree, fun)
+ tryTupleApply getOrElse errorTree(tree, "too many arguments for "+treeSymTypeMsg(fun))
} else if (lencmp == 0) {
// we don't need defaults. names were used, so this application is transformed
// into a block (@see transformNamedApplication in NamesDefaults)
-
val (namelessArgs, argPos) = removeNames(Typer.this)(args, params)
- if (namelessArgs exists (_.containsError())) {
- // This should maybe be special handled
- val tree1 = treeCopy.Apply(tree, fun, namelessArgs)
- setError(tree1)
- } else if (namelessArgs exists (_.isErroneous)) {
- assert(false, "removeNames for NamesDefaults returns only ErrorTrees in case of error. We got " + namelessArgs)
+ if (namelessArgs exists (_.isErroneous)) {
setError(tree)
} else if (!isIdentity(argPos) && !sameLength(formals, params))
// !isIdentity indicates that named arguments are used to re-order arguments
- MultipleVarargError(tree)
+ errorTree(tree, "when using named arguments, the vararg parameter "+
+ "has to be specified exactly once")
else if (isIdentity(argPos) && !isNamedApplyBlock(fun)) {
// if there's no re-ordering, and fun is not transformed, no need to transform
// more than an optimization, e.g. important in "synchronized { x = update-x }"
@@ -2569,8 +2452,7 @@ trait Typers extends Modes with Adaptations {
// calls to the default getters. Example:
// foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a))
val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x)
- if (fun1.containsError()) fun1
- else if (fun1.isErroneous) setError(tree)
+ if (fun1.isErroneous) setError(tree)
else {
assert(isNamedApplyBlock(fun1), fun1)
val NamedApplyInfo(qual, targs, previousArgss, _) = context.namedApplyBlockInfo.get._2
@@ -2587,20 +2469,17 @@ trait Typers extends Modes with Adaptations {
val lencmp2 = compareLengths(allArgs, formals)
if (!sameLength(allArgs, args) && callToCompanionConstr(context, funSym)) {
- ModuleUsingCompanionClassDefaultArgsErrror(tree)
+ errorTree(tree, "module extending its companion class cannot use default constructor arguments")
} else if (lencmp2 > 0) {
- val errors = removeNames(Typer.this)(allArgs, params)._1.filter(_.containsError()) // #3818
- if (!errors.isEmpty)
- wrapInBlock(PendingErrors(findAllNestedErrors(errors)), tree)
- else
- setError(tree)
+ removeNames(Typer.this)(allArgs, params) // #3818
+ setError(tree)
} else if (lencmp2 == 0) {
// useful when a default doesn't match parameter type, e.g. def f[T](x:T="a"); f[Int]()
val note = "Error occurred in an application involving default arguments."
if (!(context.diagnostic contains note)) context.diagnostic = note :: context.diagnostic
doTypedApply(tree, if (blockIsEmpty) fun else fun1, allArgs, mode, pt)
} else {
- tryTupleApply getOrElse NotEnoughArgsError(tree, fun, missing)
+ tryTupleApply getOrElse errorTree(tree, notEnoughArgumentsMsg(fun, missing))
}
}
}
@@ -2624,7 +2503,6 @@ trait Typers extends Modes with Adaptations {
// instantiate dependent method types, must preserve singleton types where possible (stableTypeFor) -- example use case:
// val foo = "foo"; def precise(x: String)(y: x.type): x.type = {...}; val bar : foo.type = precise(foo)(foo)
// precise(foo) : foo.type => foo.type
-
val restpe = mt.resultType(args1 map (arg => gen.stableTypeFor(arg) getOrElse arg.tpe))
def ifPatternSkipFormals(tp: Type) = tp match {
case MethodType(_, rtp) if (inPatternMode(mode)) => rtp
@@ -2660,12 +2538,11 @@ trait Typers extends Modes with Adaptations {
atPos(tree.pos)(gen.mkNil setType restpe)
else
constfold(treeCopy.Apply(tree, fun, args1) setType ifPatternSkipFormals(restpe))
+
} else if (needsInstantiation(tparams, formals, args)) {
//println("needs inst "+fun+" "+tparams+"/"+(tparams map (_.info)))
- inferExprInstance(fun, tparams) match {
- case (Some(err), _) => err
- case _ => doTypedApply(tree, fun, args, mode, pt)
- }
+ inferExprInstance(fun, tparams)
+ doTypedApply(tree, fun, args, mode, pt)
} else {
assert(!inPatternMode(mode)) // this case cannot arise for patterns
val lenientTargs = protoTypeArgs(tparams, formals, mt.resultApprox, pt)
@@ -2682,31 +2559,20 @@ trait Typers extends Modes with Adaptations {
val argtparams = context.extractUndetparams()
if (!argtparams.isEmpty) {
val strictPt = formal.instantiateTypeParams(tparams, strictTargs)
- inferArgumentInstance(arg1, argtparams, strictPt, lenientPt) match {
- case Some(err) =>
- err
- case _ =>
- arg1
- }
- } else arg1
+ inferArgumentInstance(arg1, argtparams, strictPt, lenientPt)
+ }
+ arg1
}
val args1 = (args, formals).zipped map typedArgToPoly
- if (args1 exists {_.containsErrorOrIsErrorTyped()}) {
- val allNestedErrors = findAllNestedErrors(args1.filter(_.containsError()))
- if (allNestedErrors.isEmpty) SetErrorTree(tree) else PendingErrors(allNestedErrors)
- } else {
+ if (args1 exists (_.tpe.isError)) setError(tree)
+ else {
debuglog("infer method inst "+fun+", tparams = "+tparams+", args = "+args1.map(_.tpe)+", pt = "+pt+", lobounds = "+tparams.map(_.tpe.bounds.lo)+", parambounds = "+tparams.map(_.info)) //debug
// define the undetparams which have been fixed by this param list, replace the corresponding symbols in "fun"
// returns those undetparams which have not been instantiated.
- val undetparamsOrError = inferMethodInstance(fun, tparams, args1, pt)
- if (undetparamsOrError.isLeft) {
- context.undetparams = Nil
- undetparamsOrError.left.get
- } else {
- val result = doTypedApply(tree, fun, args1, mode, pt)
- context.undetparams = undetparamsOrError.right.get
- result
- }
+ val undetparams = inferMethodInstance(fun, tparams, args1, pt)
+ val result = doTypedApply(tree, fun, args1, mode, pt)
+ context.undetparams = undetparams
+ result
}
}
}
@@ -2715,15 +2581,12 @@ trait Typers extends Modes with Adaptations {
doTypedApply(tree, fun setType fun.tpe.widen, args, mode, pt)
case ErrorType =>
- if (tree.containsError())
- tree
- else
- ErroneousFunInTypeApplyError(fun, args)
+ setError(treeCopy.Apply(tree, fun, args))
/* --- begin unapply --- */
case otpe if inPatternMode(mode) && unapplyMember(otpe).exists =>
if (args.length > MaxTupleArity)
- return TooManyArgsPatternError(fun)
+ error(fun.pos, "too many arguments for unapply pattern, maximum = "+MaxTupleArity)
def freshArgType(tp: Type): (Type, List[Symbol]) = (tp: @unchecked) match {
case MethodType(param :: _, _) =>
@@ -2731,10 +2594,9 @@ trait Typers extends Modes with Adaptations {
case PolyType(tparams, restype) =>
val tparams1 = cloneSymbols(tparams)
(freshArgType(restype)._1.substSym(tparams, tparams1), tparams1)
- // No longer used, see test case neg/t960.scala (#960 has nothing to do with it)
-// case OverloadedType(_, _) =>
-// error(fun.pos, "cannot resolve overloaded unapply")
-// (ErrorType, Nil)
+ case OverloadedType(_, _) =>
+ error(fun.pos, "cannot resolve overloaded unapply")
+ (ErrorType, Nil)
}
val unapp = unapplyMember(otpe)
@@ -2749,11 +2611,7 @@ trait Typers extends Modes with Adaptations {
freeVars foreach context1.scope.enter
val typer1 = newTyper(context1)
- val pattp0 = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe)
- val pattp = pattp0 match {
- case Left(err) => return err // Fail quickly
- case Right(tp) => tp
- }
+ val pattp = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe)
// turn any unresolved type variables in freevars into existential skolems
val skolems = freeVars map { fv =>
@@ -2769,14 +2627,7 @@ trait Typers extends Modes with Adaptations {
// setType null is necessary so that ref will be stabilized; see bug 881
val fun1 = typedPos(fun.pos)(Apply(Select(fun setType null, unapp), List(arg)))
- // Set error tree
- if (fun1.containsError())
- ErroneousFunInTypeApplyError(fun1, args)
- else if (fun1.tpe.isErroneous) {
- assert(false, "Bug #4425 workaround is invalid")
- //Bug4425Error(tree)
- setError(tree)
- }
+ if (fun1.tpe.isErroneous) setError(tree)
else {
val formals0 = unapplyTypeList(fun1.symbol, fun1.tpe)
val formals1 = formalTypes(formals0, args.length)
@@ -2791,13 +2642,14 @@ trait Typers extends Modes with Adaptations {
arg.tpe = pt1 // restore type (arg is a dummy tree, just needs to pass typechecking)
UnApply(fun1, args1) setPos tree.pos setType itype
}
- else
- WrongNumberArgsPatternError(tree, fun)
+ else {
+ errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun))
+ }
}
/* --- end unapply --- */
case _ =>
- ApplyWithoutArgsError(tree, fun)
+ errorTree(tree, fun.tpe+" does not take parameters")
}
}
@@ -2809,10 +2661,8 @@ trait Typers extends Modes with Adaptations {
def typedAnnotation(ann: Tree, mode: Int = EXPRmode, selfsym: Symbol = NoSymbol, annClass: Symbol = AnnotationClass, requireJava: Boolean = false): AnnotationInfo = {
lazy val annotationError = AnnotationInfo(ErrorType, Nil, Nil)
var hasError: Boolean = false
- var pending: List[ErrorTree] = List()
-
- def reportAnnotationError(errTree: ErrorTree) = {
- pending = errTree::pending
+ def error(pos: Position, msg: String) = {
+ context.error(pos, msg)
hasError = true
annotationError
}
@@ -2820,7 +2670,7 @@ trait Typers extends Modes with Adaptations {
/** Calling constfold right here is necessary because some trees (negated
* floats and literals in particular) are not yet folded.
*/
- def tryConst(tr: Tree, pt: Type): Either[ErrorTree, LiteralAnnotArg] = {
+ def tryConst(tr: Tree, pt: Type): Option[LiteralAnnotArg] = {
val const: Constant = typed(constfold(tr), EXPRmode, pt) match {
case l @ Literal(c) if !l.isErroneous => c
case tree => tree.tpe match {
@@ -2828,37 +2678,37 @@ trait Typers extends Modes with Adaptations {
case tpe => null
}
}
+ def fail(msg: String) = { error(tr.pos, msg) ; None }
- if (const == null) {
- Left(AnnotationNotAConstantError(tr))
- } else if (const.value == null)
- Left(AnnotationArgNullError(tr))
+ if (const == null)
+ fail("annotation argument needs to be a constant; found: " + tr)
+ else if (const.value == null)
+ fail("annotation argument cannot be null")
else
- Right(LiteralAnnotArg(const))
+ Some(LiteralAnnotArg(const))
}
/** Converts an untyped tree to a ClassfileAnnotArg. If the conversion fails,
* an error message is reported and None is returned.
*/
- def tree2ConstArg(tree: Tree, pt: Type): Either[Tree, ClassfileAnnotArg] = tree match {
+ def tree2ConstArg(tree: Tree, pt: Type): Option[ClassfileAnnotArg] = tree match {
case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) if (pt.typeSymbol == ArrayClass) =>
- Left(ArrayConstantsError(tree))
+ error(tree.pos, "Array constants have to be specified using the `Array(...)' factory method")
+ None
case ann @ Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
val annInfo = typedAnnotation(ann, mode, NoSymbol, pt.typeSymbol, true)
if (annInfo.atp.isErroneous) {
+ // recursive typedAnnotation call already printed an error, so don't call "error"
hasError = true
- Left(NullErrorTree)
- } else
- Right(NestedAnnotArg(annInfo))
+ None
+ } else Some(NestedAnnotArg(annInfo))
// use of Array.apply[T: ClassManifest](xs: T*): Array[T]
// and Array.apply(x: Int, xs: Int*): Array[Int] (and similar)
case Apply(fun, args) =>
val typedFun = typed(fun, forFunMode(mode), WildcardType)
- if (typedFun.containsError()) {
- Left(typedFun)
- } else if (typedFun.symbol.owner == ArrayModule.moduleClass && typedFun.symbol.name == nme.apply)
+ if (typedFun.symbol.owner == ArrayModule.moduleClass && typedFun.symbol.name == nme.apply)
pt match {
case TypeRef(_, ArrayClass, targ :: _) =>
trees2ConstArg(args, targ)
@@ -2867,24 +2717,21 @@ trait Typers extends Modes with Adaptations {
// BT = Int, .., String, Class[_], JavaAnnotClass
// T = BT | Array[BT]
// So an array literal as argument can only be valid if pt is Array[_]
- Left(ArrayConstantsTypeMismatchError(tree, pt))
+ error(tree.pos, "found array constant, expected argument of type "+ pt)
+ None
}
- else tryConst(tree, pt)
+ else
+ tryConst(tree, pt)
- case Typed(t, _) =>
- tree2ConstArg(t, pt)
+ case Typed(t, _) => tree2ConstArg(t, pt)
case tree =>
tryConst(tree, pt)
}
-
- def trees2ConstArg(trees: List[Tree], pt: Type): Either[ErrorTree, ArrayAnnotArg] = {
+ def trees2ConstArg(trees: List[Tree], pt: Type): Option[ArrayAnnotArg] = {
val args = trees.map(tree2ConstArg(_, pt))
- val par = args.filter(_.isLeft)
- if (!par.isEmpty)
- Left(PendingErrors(findAllNestedErrors(par.map(_.left.get))))
- else
- Right(ArrayAnnotArg(args.map(_.right.get).toArray))
+ if (args.exists(_.isEmpty)) None
+ else Some(ArrayAnnotArg(args.flatten.toArray))
}
// begin typedAnnotation
@@ -2896,18 +2743,14 @@ trait Typers extends Modes with Adaptations {
case Select(New(tpt), nme.CONSTRUCTOR) =>
(fun, outerArgss)
case _ =>
- (UnexpectedTreeAnnotation(fun), outerArgss)
+ error(fun.pos, "unexpected tree in annotation: "+ fun)
+ (setError(fun), outerArgss)
}
extract(ann, List())
}
-
- // It seems that fun.isErroneous was used due to check for deep error within fun?
- // We don't need it now because deep error within fun
- // is now detected by containsError()
- val res = if (fun.containsErrorOrIsErrorTyped()) {
- annotationError
- } else {
+ if (fun.isErroneous) annotationError
+ else {
val typedFun @ Select(New(tpt), _) = typed(fun, forFunMode(mode), WildcardType)
val annType = tpt.tpe
@@ -2916,9 +2759,9 @@ trait Typers extends Modes with Adaptations {
// annotation to be saved as java classfile annotation
val isJava = typedFun.symbol.owner.isJavaDefined
if (!annType.typeSymbol.isNonBottomSubClass(annClass)) {
- reportAnnotationError(AnnotationTypeMismatchError(tpt, annClass.tpe, annType))
+ error(tpt.pos, "expected annotation of type "+ annClass.tpe +", found "+ annType)
} else if (argss.length > 1) {
- reportAnnotationError(MultipleArgumentListForAnnotationError(ann))
+ error(ann.pos, "multiple argument lists on classfile annotation")
} else {
val args =
if (argss.head.length == 1 && !isNamed(argss.head.head))
@@ -2934,37 +2777,33 @@ trait Typers extends Modes with Adaptations {
val sym = if (isJava) annScope.lookup(name)
else typedFun.tpe.params.find(p => p.name == name).getOrElse(NoSymbol)
if (sym == NoSymbol) {
- reportAnnotationError(UnknownAnnotationNameError(arg, name))
+ error(arg.pos, "unknown annotation argument name: " + name)
(nme.ERROR, None)
} else if (!names.contains(sym)) {
- reportAnnotationError(DuplicateValueAnnotationError(arg, name))
+ error(arg.pos, "duplicate value for annotation argument " + name)
(nme.ERROR, None)
} else {
names -= sym
if (isJava) sym.cookJavaRawInfo() // #3429
val annArg = tree2ConstArg(rhs, sym.tpe.resultType)
- if (annArg.isLeft) {
- errorTreesFinder(annArg.left.get).foreach(reportAnnotationError)
- (nme.ERROR, None)
- } else
- (sym.name, Some(annArg.right.get))
+ (sym.name, annArg)
}
case arg =>
- reportAnnotationError(ClassfileAnnotationsAsNamedArgsError(arg))
+ error(arg.pos, "classfile annotation arguments have to be supplied as named arguments")
(nme.ERROR, None)
}
for (name <- names) {
if (!name.annotations.contains(AnnotationInfo(AnnotationDefaultAttr.tpe, List(), List())) &&
!name.hasDefaultFlag)
- reportAnnotationError(AnnotationMissingArgError(ann, annType, name))
+ error(ann.pos, "annotation " + annType.typeSymbol.fullName + " is missing argument " + name.name)
}
if (hasError) annotationError
else AnnotationInfo(annType, List(), nvPairs map {p => (p._1, p._2.get)}).setPos(ann.pos)
}
} else if (requireJava) {
- reportAnnotationError(NestedAnnotationError(ann, annType))
+ error(ann.pos, "nested classfile annotations must be defined in java; found: "+ annType)
} else {
val typedAnn = if (selfsym == NoSymbol) {
typed(ann, mode, annClass.tpe)
@@ -2992,9 +2831,6 @@ trait Typers extends Modes with Adaptations {
List(selfsym.info, annClass.tpe))
(typed(func, mode, funcType): @unchecked) match {
- case t if t.containsError() =>
- reportAnnotationError(NullErrorTree)
- t
case t @ Function(List(arg), rhs) =>
val subs =
new TreeSymSubstituter(List(arg.symbol),List(selfsym))
@@ -3019,27 +2855,16 @@ trait Typers extends Modes with Adaptations {
annInfo(fun)
case _ =>
- reportAnnotationError(UnexpectedTreeAnnotationError(t, typedAnn))
+ error(t.pos, "unexpected tree after typing annotation: "+ typedAnn)
}
if (annType.typeSymbol == DeprecatedAttr && argss.flatten.size < 2)
unit.deprecationWarning(ann.pos, "@deprecated now takes two arguments; see the scaladoc.")
- if (typedAnn.containsError() || (typedAnn.tpe == null) || typedAnn.tpe.isErroneous) annotationError
+ if ((typedAnn.tpe == null) || typedAnn.tpe.isErroneous) annotationError
else annInfo(typedAnn)
}
}
-
- if (hasError) {
- // We got errors, so now is the last chance to report them
- try {
- pending.foreach(_.emit(context))
- } catch {
- case _: TypeError =>
- assert(false, "Cannot throw type errors when creating AnnotationInfo")
- }
- annotationError
- } else res
}
def isRawParameter(sym: Symbol) = // is it a type parameter leaked by a raw type?
@@ -3098,8 +2923,7 @@ trait Typers extends Modes with Adaptations {
}
/** convert skolems to existentials */
- def packedType(tree: Tree, owner: Symbol): (Type, List[ErrorTree]) = {
- var pending: List[ErrorTree] = List()
+ def packedType(tree: Tree, owner: Symbol): Type = {
def defines(tree: Tree, sym: Symbol) =
sym.isExistentialSkolem && sym.unpackLocation == tree ||
tree.isDef && tree.symbol == sym
@@ -3125,7 +2949,7 @@ trait Typers extends Modes with Adaptations {
if (sym.isAliasType && containsLocal(tp)) apply(tp.normalize)
else {
if (pre.isVolatile)
- pending = InferTypeWithVolatileTypeSelectionError(tree, tp)::pending
+ context.error(tree.pos, "Inferred type "+tree.tpe+" contains type selection from volatile type "+pre)
mapOver(tp)
}
case _ =>
@@ -3142,7 +2966,8 @@ trait Typers extends Modes with Adaptations {
localSyms += sym
remainingSyms += sym
} else {
- pending = AbstractExistentiallyOverParamerizedTpeError(tree, tp)::pending
+ unit.error(tree.pos,
+ "can't existentially abstract over parameterized type " + tp)
}
}
}
@@ -3171,10 +2996,10 @@ trait Typers extends Modes with Adaptations {
}
for (sym <- remainingSyms) addLocals(sym.existentialBound)
}
+
val normalizedTpe = normalizeLocals(tree.tpe)
addLocals(normalizedTpe)
- val res = packSymbols(localSyms.toList, normalizedTpe)
- (res, pending.reverse)
+ packSymbols(localSyms.toList, normalizedTpe)
}
protected def typedExistentialTypeTree(tree: ExistentialTypeTree, mode: Int): Tree = {
@@ -3182,23 +3007,19 @@ trait Typers extends Modes with Adaptations {
if (wc.symbol == NoSymbol) { namer.enterSym(wc); wc.symbol setFlag EXISTENTIAL }
else context.scope enter wc.symbol
val whereClauses1 = typedStats(tree.whereClauses, context.owner)
- var pending: List[ErrorTree] = List()
for (vd @ ValDef(_, _, _, _) <- tree.whereClauses)
if (vd.symbol.tpe.isVolatile)
- pending = AbstractionFromVolatileTypeError(vd)::pending
+ error(vd.pos, "illegal abstraction from value with volatile type "+vd.symbol.tpe)
val tpt1 = typedType(tree.tpt, mode)
val (typeParams, tpe) = existentialTransform(tree.whereClauses map (_.symbol), tpt1.tpe)
- val tt = TypeTree(ExistentialType(typeParams, tpe)) setOriginal tree
- if (pending.isEmpty) tt else tt.setErrorCause(PendingErrors(pending.reverse))
+ //println(tpe + ": " + tpe.getClass )
+ TypeTree(ExistentialType(typeParams, tpe)) setOriginal tree
}
// lifted out of typed1 because it's needed in typedImplicit0
protected def typedTypeApply(tree: Tree, mode: Int, fun: Tree, args: List[Tree]): Tree = fun.tpe match {
case OverloadedType(pre, alts) =>
- inferPolyAlternatives(fun, args map (_.tpe)) match {
- case Some(err) => return err
- case _ =>
- }
+ inferPolyAlternatives(fun, args map (_.tpe))
val tparams = fun.symbol.typeParams //@M TODO: fun.symbol.info.typeParams ? (as in typedAppliedTypeTree)
val args1 = if (sameLength(args, tparams)) {
//@M: in case TypeApply we can't check the kind-arities of the type arguments,
@@ -3211,7 +3032,7 @@ trait Typers extends Modes with Adaptations {
// Martin, I'm using fake trees, because, if you use args or arg.map(typedType),
// inferPolyAlternatives loops... -- I have no idea why :-(
// ...actually this was looping anyway, see bug #278.
- return TypedApplyWrongNumberOfTpeParametersError(fun, fun)
+ return errorTree(fun, "wrong number of type parameters for "+treeSymTypeMsg(fun))
typedTypeApply(tree, mode, fun, args1)
case SingleType(_, _) =>
@@ -3219,36 +3040,30 @@ trait Typers extends Modes with Adaptations {
case PolyType(tparams, restpe) if tparams.nonEmpty =>
if (sameLength(tparams, args)) {
val targs = args map (_.tpe)
- checkBounds(tree.pos, NoPrefix, NoSymbol, tparams, targs, "") match {
- case Some(err) =>
- err
- case None =>
- if (fun.symbol == Predef_classOf) {
- checkClassType(args.head, true, false) match {
- case Some(err) => err
- case _ => atPos(tree.pos) { gen.mkClassOf(targs.head) }
- }
- } else {
- if (phase.id <= currentRun.typerPhase.id &&
- fun.symbol == Any_isInstanceOf && !targs.isEmpty)
- checkCheckable(tree.pos, targs.head, "")
- val resultpe = restpe.instantiateTypeParams(tparams, targs)
- //@M substitution in instantiateParams needs to be careful!
- //@M example: class Foo[a] { def foo[m[x]]: m[a] = error("") } (new Foo[Int]).foo[List] : List[Int]
- //@M --> first, m[a] gets changed to m[Int], then m gets substituted for List,
- // this must preserve m's type argument, so that we end up with List[Int], and not List[a]
- //@M related bug: #1438
- //println("instantiating type params "+restpe+" "+tparams+" "+targs+" = "+resultpe)
- treeCopy.TypeApply(tree, fun, args) setType resultpe
- }
+ checkBounds(tree.pos, NoPrefix, NoSymbol, tparams, targs, "")
+ if (fun.symbol == Predef_classOf) {
+ checkClassType(args.head, true, false)
+ atPos(tree.pos) { gen.mkClassOf(targs.head) }
+ } else {
+ if (phase.id <= currentRun.typerPhase.id &&
+ fun.symbol == Any_isInstanceOf && !targs.isEmpty)
+ checkCheckable(tree.pos, targs.head, "")
+ val resultpe = restpe.instantiateTypeParams(tparams, targs)
+ //@M substitution in instantiateParams needs to be careful!
+ //@M example: class Foo[a] { def foo[m[x]]: m[a] = error("") } (new Foo[Int]).foo[List] : List[Int]
+ //@M --> first, m[a] gets changed to m[Int], then m gets substituted for List,
+ // this must preserve m's type argument, so that we end up with List[Int], and not List[a]
+ //@M related bug: #1438
+ //println("instantiating type params "+restpe+" "+tparams+" "+targs+" = "+resultpe)
+ treeCopy.TypeApply(tree, fun, args) setType resultpe
}
} else {
- TypedApplyWrongNumberOfTpeParametersError(tree, fun)
+ errorTree(tree, "wrong number of type parameters for "+treeSymTypeMsg(fun))
}
case ErrorType =>
setError(tree)
case _ =>
- TypedApplyDoesNotTakeTpeParametersError(tree, fun)
+ errorTree(tree, treeSymTypeMsg(fun)+" does not take type parameters.")
}
@inline final def deindentTyping() = context.typingIndentLevel -= 2
@@ -3318,10 +3133,9 @@ trait Typers extends Modes with Adaptations {
atype0 // do not record selfsym if
// this annotation did not need it
- if (ainfo.isErroneous) {
- // Erroneous annotations were already reported in typedAnnotation
+ if (ainfo.isErroneous)
arg1 // simply drop erroneous annotations
- } else {
+ else {
ann.tpe = atype
TypeTree(atype) setOriginal tree
}
@@ -3355,24 +3169,18 @@ trait Typers extends Modes with Adaptations {
tree setSymbol vble setType vble.tpe
}
def typedBindTerm(name: TermName) = {
- def typedBindTerm0() = {
- val body1 = typed(body, mode, pt)
- vble.setInfo(
- if (treeInfo.isSequenceValued(body)) seqType(body1.tpe)
- else body1.tpe)
- treeCopy.Bind(tree, name, body1) setSymbol vble setType body1.tpe // burak, was: pt
- }
if (vble == NoSymbol)
vble = context.owner.newValue(tree.pos, name)
if (vble.name.toTermName != nme.WILDCARD) {
- vble = namer.enterInScope(vble)
-
if ((mode & ALTmode) != 0)
- VariableInPatternAlternativeError(tree)
- else {
- typedBindTerm0()
- }
- } else typedBindTerm0()
+ error(tree.pos, "illegal variable in pattern alternative")
+ vble = namer.enterInScope(vble)
+ }
+ val body1 = typed(body, mode, pt)
+ vble.setInfo(
+ if (treeInfo.isSequenceValued(body)) seqType(body1.tpe)
+ else body1.tpe)
+ treeCopy.Bind(tree, name, body1) setSymbol vble setType body1.tpe // burak, was: pt
}
name match {
case x: TypeName => typedBindType(x)
@@ -3392,12 +3200,15 @@ trait Typers extends Modes with Adaptations {
def typedAssign(lhs: Tree, rhs: Tree): Tree = {
val lhs1 = typed(lhs, EXPRmode | LHSmode, WildcardType)
val varsym = lhs1.symbol
+ def failMsg =
+ if (varsym != null && varsym.isValue) "reassignment to val"
+ else "assignment to non variable"
def fail = {
- if (lhs1.containsErrorOrIsErrorTyped())
- lhs1
- else // see #2494 for double error message example
- AssignmentError(tree, varsym)
+ if (!lhs1.tpe.isError)
+ error(tree.pos, failMsg)
+
+ setError(tree)
}
if (varsym == null)
return fail
@@ -3442,12 +3253,12 @@ trait Typers extends Modes with Adaptations {
enclMethod.owner.isConstructor ||
context.enclClass.enclMethod == enclMethod // i.e., we are in a constructor of a local class
) {
- ReturnOutsideOfDefError(tree)
+ errorTree(tree, "return outside method definition")
} else {
val DefDef(_, name, _, _, restpt, _) = enclMethod.tree
- if (restpt.tpe eq null) {
- ReturnWithoutTypeError(tree, enclMethod.owner)
- } else {
+ if (restpt.tpe eq null)
+ errorTree(tree, enclMethod.owner + " has return statement; needs result type")
+ else {
context.enclMethod.returnsSeen = true
val expr1: Tree = typed(expr, EXPRmode | BYVALmode, restpt.tpe)
// Warn about returning a value if no value can be returned.
@@ -3466,15 +3277,12 @@ trait Typers extends Modes with Adaptations {
def typedNew(tpt: Tree) = {
val tpt1 = {
val tpt0 = typedTypeConstructor(tpt)
- checkClassType(tpt0, false, true) match {
- case Some(err) => err
- case _ =>
- if (tpt0.hasSymbol && !tpt0.symbol.typeParams.isEmpty) {
- context.undetparams = cloneSymbols(tpt0.symbol.typeParams)
- TypeTree().setOriginal(tpt0)
- .setType(appliedType(tpt0.tpe, context.undetparams map (_.tpeHK))) // @PP: tpeHK! #3343, #4018, #4347.
- } else tpt0
- }
+ checkClassType(tpt0, false, true)
+ if (tpt0.hasSymbol && !tpt0.symbol.typeParams.isEmpty) {
+ context.undetparams = cloneSymbols(tpt0.symbol.typeParams)
+ TypeTree().setOriginal(tpt0)
+ .setType(appliedType(tpt0.tpe, context.undetparams map (_.tpeHK))) // @PP: tpeHK! #3343, #4018, #4347.
+ } else tpt0
}
/** If current tree <tree> appears in <val x(: T)? = <tree>>
@@ -3493,15 +3301,17 @@ trait Typers extends Modes with Adaptations {
val tp = tpt1.tpe
val sym = tp.typeSymbol
if (sym.isAbstractType || sym.hasAbstractFlag)
- IsAbstractError(tree, sym)
+ error(tree.pos, sym + " is abstract; cannot be instantiated")
else if (!( tp == sym.initialize.thisSym.tpe // when there's no explicit self type -- with (#3612) or without self variable
// sym.thisSym.tpe == tp.typeOfThis (except for objects)
|| narrowRhs(tp) <:< tp.typeOfThis
|| phase.erasedTypes
)) {
- DoesNotConformToSelfTypeError(tree, sym, tp.typeOfThis)
- } else
- treeCopy.New(tree, tpt1).setType(tp)
+ error(tree.pos, sym +
+ " cannot be instantiated because it does not conform to its self-type "+
+ tp.typeOfThis)
+ }
+ treeCopy.New(tree, tpt1).setType(tp)
}
def typedEta(expr1: Tree): Tree = expr1.tpe match {
@@ -3539,23 +3349,22 @@ trait Typers extends Modes with Adaptations {
case ErrorType =>
expr1
case _ =>
- UnderscoreEtaError(expr1)
+ errorTree(expr1, "_ must follow method; cannot follow " + expr1.tpe)
}
/**
* @param args ...
* @return ...
*/
- def tryTypedArgs(args: List[Tree], mode: Int): List[Tree] = {
+ def tryTypedArgs(args: List[Tree], mode: Int, other: TypeError): List[Tree] = {
val c = context.makeSilent(false)
c.retyping = true
try {
newTyper(c).typedArgs(args, mode)
} catch {
- case ex: CyclicReference =>
- throw ex
- case _: TypeError =>
- List(NullErrorTree)
+ case ex: CyclicReference => throw ex
+ case ex: TypeError =>
+ null
}
}
@@ -3564,8 +3373,10 @@ trait Typers extends Modes with Adaptations {
*/
def tryTypedApply(fun: Tree, args: List[Tree]): Tree = {
val start = startTimer(failedApplyNanos)
-
- def onError(treeWithError: Tree): Tree = {
+ silent(_.doTypedApply(tree, fun, args, mode, pt)) match {
+ case t: Tree =>
+ t
+ case ex: TypeError =>
stopTimer(failedApplyNanos, start)
// If the problem is with raw types, copnvert to existentials and try again.
@@ -3588,42 +3399,26 @@ trait Typers extends Modes with Adaptations {
case Typed(r, Function(Nil, EmptyTree)) => treesInResult(r)
case _ => Nil
})
- // Get correct posiition for the error
- val firstToReport = quickErrorTreeFinder(treeWithError)
- val ePos = firstToReport.pos
- def errorInResult(tree: Tree) = treesInResult(tree) exists (_.pos == ePos)
-
- val retry = (ePos != null) && (fun :: tree :: args exists errorInResult)
- if (settings.errortrees.value)
- println("[ErrorTree retry] " + retry + " with " + treeWithError + " " + firstToReport.exception)
+ def errorInResult(tree: Tree) = treesInResult(tree) exists (_.pos == ex.pos)
+ val retry = fun :: tree :: args exists errorInResult
printTyping {
val funStr = ptTree(fun) + " and " + (args map ptTree mkString ", ")
if (retry) "second try: " + funStr
- else "no second try: " + funStr + " because error not in result: " + ePos+"!="+tree.pos
+ else "no second try: " + funStr + " because error not in result: " + ex.pos+"!="+tree.pos
}
if (retry) {
val Select(qual, name) = fun
- val args1 = tryTypedArgs(args, forArgMode(fun, mode))
- val invalidArgs = args1.length == 1 && (args1.head.containsError() || args1.head.tpe.isErroneous)
+ val args1 = tryTypedArgs(args, forArgMode(fun, mode), ex)
val qual1 =
- if (!invalidArgs && !pt.isError) adaptToArguments(qual, name, args1, pt)
+ if ((args1 ne null) && !pt.isError) adaptToArguments(qual, name, args1, pt)
else qual
if (qual1 ne qual) {
val tree1 = Apply(Select(qual1, name) setPos fun.pos, args1) setPos tree.pos
return typed1(tree1, mode | SNDTRYmode, pt)
}
}
-
- firstToReport
- }
-
- silent(_.doTypedApply(tree, fun, args, mode, pt)) match {
- case t: Tree if !t.containsError() =>
- t
- case t: Tree =>
- onError(t)
- case ex: TypeError =>
- onError(TypedApplyError(fun, ex))
+ reportTypeError(tree.pos, ex)
+ setError(tree)
}
}
@@ -3636,32 +3431,10 @@ trait Typers extends Modes with Adaptations {
val funpt = if (isPatternMode) pt else WildcardType
val appStart = startTimer(failedApplyNanos)
val opeqStart = startTimer(failedOpEqNanos)
-
- def onError(reportError: => Tree): Tree = {
- fun match {
- case Select(qual, name)
- if !isPatternMode && nme.isOpAssignmentName(name.decode) =>
- val qual1 = typedQualifier(qual)
- if (treeInfo.isVariableOrGetter(qual1)) {
- stopTimer(failedOpEqNanos, opeqStart)
- convertToAssignment(fun, qual1, name, args)
- } else {
- stopTimer(failedApplyNanos, appStart)
- if ((qual1.symbol ne null) && qual1.symbol.isValue)
- AssignmentTypedApplyError(tree)
- else
- reportError
- }
- case _ =>
- stopTimer(failedApplyNanos, appStart)
- reportError
- }
- }
-
silent(_.typed(fun, forFunMode(mode), funpt),
if ((mode & EXPRmode) != 0) false else context.reportAmbiguousErrors,
if ((mode & EXPRmode) != 0) tree else context.tree) match {
- case fun1: Tree if !fun1.containsErrorOrIsErrorTyped() =>
+ case fun1: Tree =>
val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1
incCounter(typedApplyCount)
def isImplicitMethod(tpe: Type) = tpe match {
@@ -3687,29 +3460,39 @@ trait Typers extends Modes with Adaptations {
//if (fun2.hasSymbol && fun2.symbol.name == nme.apply && fun2.symbol.owner == ArrayClass) {
// But this causes cyclic reference for Array class in Cleanup. It is easy to overcome this
// by calling ArrayClass.info here (or some other place before specialize).
- if (fun2.symbol == Array_apply && !res.containsError()) {
+ if (fun2.symbol == Array_apply) {
val checked = gen.mkCheckInit(res)
// this check is needed to avoid infinite recursion in Duplicators
// (calling typed1 more than once for the same tree)
if (checked ne res) typed { atPos(tree.pos)(checked) }
else res
} else res
-
- case eTree: Tree =>
- if (settings.errortrees.value)
- println("[ErrorTree silent] Encounter error in silent typing of apply")
-
- onError(if (eTree.containsError()) {val ex = quickErrorTreeFinder(eTree); if (ex.exception == null) ex else TypedApplyError(fun, ex.exception)} else eTree)
-
case ex: TypeError =>
- onError(TypedApplyError(fun, ex))
-
-
+ fun match {
+ case Select(qual, name)
+ if !isPatternMode && nme.isOpAssignmentName(name.decode) =>
+ val qual1 = typedQualifier(qual)
+ if (treeInfo.isVariableOrGetter(qual1)) {
+ stopTimer(failedOpEqNanos, opeqStart)
+ convertToAssignment(fun, qual1, name, args, ex)
+ } else {
+ stopTimer(failedApplyNanos, appStart)
+ if ((qual1.symbol ne null) && qual1.symbol.isValue)
+ error(tree.pos, "reassignment to val")
+ else
+ reportTypeError(fun.pos, ex)
+ setError(tree)
+ }
+ case _ =>
+ stopTimer(failedApplyNanos, appStart)
+ reportTypeError(fun.pos, ex)
+ setError(tree)
+ }
}
}
}
- def convertToAssignment(fun: Tree, qual: Tree, name: Name, args: List[Tree]): Tree = {
+ def convertToAssignment(fun: Tree, qual: Tree, name: Name, args: List[Tree], ex: TypeError): Tree = {
val prefix = name.subName(0, name.length - nme.EQL.length)
def mkAssign(vble: Tree): Tree =
Assign(
@@ -3750,11 +3533,10 @@ trait Typers extends Modes with Adaptations {
case Apply(fn, indices) =>
treeInfo.methPart(fn) match {
case Select(table, nme.apply) => mkUpdate(table, indices)
- case _ => UnexpectedTreeAssignmentConversionError(qual)
+ case _ => errorTree(qual, "Unexpected tree during assignment conversion.")
}
}
typed1(tree1, mode, pt)
-
/*
debuglog("retry assign: "+tree1)
silent(_.typed1(tree1, mode, pt)) match {
@@ -3767,8 +3549,8 @@ trait Typers extends Modes with Adaptations {
*/
}
- def qualifyingClassSym(qual: Name): Either[ErrorTree, Symbol] =
- if (tree.symbol != NoSymbol) Right(tree.symbol) else qualifyingClass(tree, qual, false)
+ def qualifyingClassSym(qual: Name): Symbol =
+ if (tree.symbol != NoSymbol) tree.symbol else qualifyingClass(tree, qual, false)
def typedSuper(qual: Tree, mix: TypeName) = {
val qual1 = typed(qual)
@@ -3779,7 +3561,7 @@ trait Typers extends Modes with Adaptations {
}
//println(clazz+"/"+qual1.tpe.typeSymbol+"/"+qual1)
- def findMixinSuper(site: Type): Either[ErrorTree, Type] = {
+ def findMixinSuper(site: Type): Type = {
var ps = site.parents filter (_.typeSymbol.name == mix)
if (ps.isEmpty)
ps = site.parents filter (_.typeSymbol.toInterface.name == mix)
@@ -3794,48 +3576,35 @@ trait Typers extends Modes with Adaptations {
// println(mix)
// the reference to super class got lost during erasure
restrictionError(tree.pos, unit, "traits may not select fields or methods from super[C] where C is a class")
- Left(NullErrorTree)
} else {
- Left(MixinMissingParentClassNameError(tree, mix, clazz))
+ error(tree.pos, mix+" does not name a parent class of "+clazz)
}
+ ErrorType
} else if (!ps.tail.isEmpty) {
- Left(AmbiguousParentClassError(tree))
+ error(tree.pos, "ambiguous parent class qualifier")
+ ErrorType
} else {
- Right(ps.head)
+ ps.head
}
}
val owntype =
if (mix.isEmpty) {
if ((mode & SUPERCONSTRmode) != 0)
- if (clazz.info.parents.isEmpty) Right(AnyRefClass.tpe) // can happen due to cyclic references ==> #1036
- else Right(clazz.info.parents.head)
- else Right(intersectionType(clazz.info.parents))
+ if (clazz.info.parents.isEmpty) AnyRefClass.tpe // can happen due to cyclic references ==> #1036
+ else clazz.info.parents.head
+ else intersectionType(clazz.info.parents)
} else {
findMixinSuper(clazz.tpe)
}
- val owntype1 = if (owntype.isLeft) {
- // Is there any way we can push the error tree into super?
- // Report here for the moment
- try {
- owntype.left.get.emit(context)
- } catch {
- case _: TypeError =>
- assert(false, "Invalid type error when typing Super")
- }
- ErrorType
- } else owntype.right.get
-
- treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype1)
+ treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype)
}
def typedThis(qual: Name) = {
- val clazzOrError = qualifyingClassSym(qual)
- if (clazzOrError.isLeft) clazzOrError.left.get
- else if (clazzOrError.right.get == NoSymbol) setError(tree)
+ val clazz = qualifyingClassSym(qual)
+ if (clazz == NoSymbol) setError(tree)
else {
- val clazz = clazzOrError.right.get
tree setSymbol clazz setType clazz.thisType.underlying
if (isStableContext(tree, mode, pt)) tree setType clazz.thisType
tree
@@ -3869,14 +3638,9 @@ trait Typers extends Modes with Adaptations {
}
if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & EXPRmode) != 0) {
val qual1 =
- if (member(qual, name) != NoSymbol) NullErrorTree
+ if (member(qual, name) != NoSymbol) qual
else adaptToMemberWithArgs(tree, qual, name, mode)
- if (!qual1.containsError()) {
- if (qual1 ne qual)
- return typed(treeCopy.Select(tree, qual1, name), mode, pt)
- } else {
- return qual1
- }
+ if (qual1 ne qual) return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}
if (!reallyExists(sym)) {
@@ -3907,7 +3671,7 @@ trait Typers extends Modes with Adaptations {
)
}
- def makeInteractiveErrorTree = {
+ def makeErrorTree = {
val tree1 = tree match {
case Select(_, _) => treeCopy.Select(tree, qual, name)
case SelectFromTypeTree(_, _) => treeCopy.SelectFromTypeTree(tree, qual, name)
@@ -3915,15 +3679,16 @@ trait Typers extends Modes with Adaptations {
setError(tree1)
}
+ if (name == nme.ERROR && forInteractive)
+ return makeErrorTree
- if (forInteractive)
- makeInteractiveErrorTree
- else if (!qual.tpe.widen.isErroneous) {
+ if (!qual.tpe.widen.isErroneous) {
val lastTry = missingHook(qual.tpe.typeSymbol, name)
if (lastTry != NoSymbol) return typed1(tree setSymbol lastTry, mode, pt)
- NotAMemberError(tree, qual, name)
- } else
- NotAMemberErroneous(tree)
+ notAMemberError(tree.pos, qual, name)
+ }
+
+ if (forInteractive) makeErrorTree else setError(tree)
} else {
val tree1 = tree match {
case Select(_, _) => treeCopy.Select(tree, qual, name)
@@ -3949,32 +3714,16 @@ trait Typers extends Modes with Adaptations {
result,
(TypeTreeWithDeferredRefCheck(){ () => val tp = qual.tpe; val sym = tp.typeSymbolDirect
// will execute during refchecks -- TODO: make private checkTypeRef in refchecks public and call that one?
- checkBounds(qual.pos, tp.prefix, sym.owner, sym.typeParams, tp.typeArgs, "") match {
- case Some(err) => Left(err)
- case _ => Right(qual) // you only get to see the wrapped tree after running this check :-p
- }
+ checkBounds(qual.pos, tp.prefix, sym.owner, sym.typeParams, tp.typeArgs, "")
+ qual // you only get to see the wrapped tree after running this check :-p
}) setType qual.tpe,
name)
- case tt if tt.containsError() =>
- val errTree = quickErrorTreeFinder(tt)
- errTree match {
- case accError: AccessError =>
- val qual1 =
- try adaptToMemberWithArgs(tree, qual, name, mode)
- catch {
- case _: TypeError =>
- // Ambigues implicits throw TypeError
- // and then they are reported here.
- NullErrorTree
- }
- if (!qual1.containsError() && (qual1 ne qual)) {
- typed(Select(qual1, name) setPos tree.pos, mode, pt)
- } else {
- accError
- }
- case _ =>
- tt
- }
+ case accErr: Inferencer#AccessError =>
+ val qual1 =
+ try adaptToMemberWithArgs(tree, qual, name, mode)
+ catch { case _: TypeError => qual }
+ if (qual1 ne qual) typed(Select(qual1, name) setPos tree.pos, mode, pt)
+ else accErr.emit()
case _ =>
result
}
@@ -3982,8 +3731,7 @@ trait Typers extends Modes with Adaptations {
// getClass, we have to catch it immediately so expressions
// like x.getClass().newInstance() are typed with the type of x.
val isRefinableGetClass = (
- !selection.containsError()
- && selection.symbol.name == nme.getClass_
+ selection.symbol.name == nme.getClass_
&& selection.tpe.params.isEmpty
// TODO: If the type of the qualifier is inaccessible, we can cause private types
// to escape scope here, e.g. pos/t1107. I'm not sure how to properly handle this
@@ -3991,7 +3739,7 @@ trait Typers extends Modes with Adaptations {
&& qual.tpe.typeSymbol.isPublic
)
if (isRefinableGetClass)
- selection setType MethodType(Nil, erasure.getClassReturnType(qual.tpe))
+ selection setType MethodType(Nil, erasure.getClassReturnType(qual.tpe))
else
selection
}
@@ -4005,17 +3753,8 @@ trait Typers extends Modes with Adaptations {
* (2) Change imported symbols to selections
*/
def typedIdent(name: Name): Tree = {
- var errorContainer: Tree = null
- @inline
- def ambiguousError(msg: String) = {
- assert(errorContainer == null, "Cannot set ambiguous error twice for identifier")
- errorContainer = AmbiguousIdentError(tree, name, msg)
- }
- @inline
- def identError(tree: ErrorTree) = {
- assert(errorContainer == null, "Cannot set ambiguous error twice for identifier")
- errorContainer = tree
- }
+ def ambiguousError(msg: String) =
+ error(tree.pos, "reference to " + name + " is ambiguous;\n" + msg)
var defSym: Symbol = tree.symbol // the directly found symbol
var pre: Type = NoPrefix // the prefix type of defSym, if a class member
@@ -4117,7 +3856,7 @@ trait Typers extends Modes with Adaptations {
ambiguousError(
"it is imported twice in the same scope by\n"+imports.head + "\nand "+imports1.head)
}
- while (errorContainer == null && !imports1.isEmpty &&
+ while (!imports1.isEmpty &&
(!imports.head.isExplicitImport(name) ||
imports1.head.depth == imports.head.depth)) {
var impSym1 = imports1.head.importedSymbol(name)
@@ -4132,17 +3871,11 @@ trait Typers extends Modes with Adaptations {
}
imports1 = imports1.tail
}
- if (errorContainer == null) {
- if (imports.head.qual.containsError()) {
- defSym = context.owner.newErrorSymbol(name)
- } else {
- defSym = impSym
- val qual0 = imports.head.qual
- if (!(shortenImports && qual0.symbol.isPackage)) // optimization: don't write out package prefixes
- qual = atPos(tree.pos.focusStart)(resetPos(qual0.duplicate))
- pre = qual.tpe
- }
- }
+ defSym = impSym
+ val qual0 = imports.head.qual
+ if (!(shortenImports && qual0.symbol.isPackage)) // optimization: don't write out package prefixes
+ qual = atPos(tree.pos.focusStart)(resetPos(qual0.duplicate))
+ pre = qual.tpe
}
else if (settings.exposeEmptyPackage.value && checkEmptyPackage())
log("Allowing empty package member " + name + " due to settings.")
@@ -4156,53 +3889,50 @@ trait Typers extends Modes with Adaptations {
if (inaccessibleSym eq NoSymbol) {
// Avoiding some spurious error messages: see SI-2388.
if (reporter.hasErrors && (name startsWith tpnme.ANON_CLASS_NAME)) ()
- else identError(SymbolNotFound(tree, name, context.owner))
- } else {
- identError(AccessError(
- tree, inaccessibleSym, context.enclClass.owner.thisType, context.enclClass.owner,
- inaccessibleExplanation
- ))
+ else error(tree.pos, "not found: "+decodeWithKind(name, context.owner))
}
+ else new AccessError(
+ tree, inaccessibleSym, context.enclClass.owner.thisType,
+ inaccessibleExplanation
+ ).emit()
defSym = context.owner.newErrorSymbol(name)
}
}
}
-
- if (errorContainer != null) {
- errorContainer
+ if (defSym.owner.isPackageClass) pre = defSym.owner.thisType
+ if (defSym.isThisSym) {
+ typed1(This(defSym.owner) setPos tree.pos, mode, pt)
} else {
- if (defSym.owner.isPackageClass) pre = defSym.owner.thisType
- if (defSym.isThisSym) {
- typed1(This(defSym.owner) setPos tree.pos, mode, pt)
- } else {
- val tree1 = if (qual == EmptyTree) tree
- else atPos(tree.pos)(Select(qual, name))
- // atPos necessary because qualifier might come from startContext
- val (tree2, pre2) = makeAccessible(tree1, defSym, pre, qual)
- // assert(pre.typeArgs isEmpty) // no need to add #2416-style check here, right?
- stabilize(tree2, pre2, mode, pt)
+ val tree1 = if (qual == EmptyTree) tree
+ else atPos(tree.pos)(Select(qual, name))
+ // atPos necessary because qualifier might come from startContext
+ val (tree2, pre2) = makeAccessible(tree1, defSym, pre, qual)
+ // assert(pre.typeArgs isEmpty) // no need to add #2416-style check here, right?
+ stabilize(tree2, pre2, mode, pt) match {
+ case accErr: Inferencer#AccessError => accErr.emit()
+ case result => result
}
}
}
def typedCompoundTypeTree(templ: Template) = {
val parents1 = templ.parents mapConserve (typedType(_, mode))
- if (parents1 exists (_.containsErrorOrIsErrorTyped())) tree setType ErrorType
+ if (parents1 exists (_.tpe.isError)) tree setType ErrorType
else {
val decls = new Scope
//Console.println("Owner: " + context.enclClass.owner + " " + context.enclClass.owner.id)
val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls, templ.pos)
newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ.body)
- tree.setType(self)
+ tree setType self
}
}
def typedAppliedTypeTree(tpt: Tree, args: List[Tree]) = {
val tpt1 = typed1(tpt, mode | FUNmode | TAPPmode, WildcardType)
- if (tpt1.containsErrorOrIsErrorTyped()) {
- setError(treeCopy.AppliedTypeTree(tree, tpt1, args))
+ if (tpt1.tpe.isError) {
+ setError(tree)
} else if (!tpt1.hasSymbol) {
- AppliedTypeNoParametersError(tree, tpt1.tpe)
+ errorTree(tree, tpt1.tpe+" does not take type parameters")
} else {
val tparams = tpt1.symbol.typeParams
if (sameLength(tparams, args)) {
@@ -4235,18 +3965,16 @@ trait Typers extends Modes with Adaptations {
// wrap the tree and include the bounds check -- refchecks will perform this check (that the beta reduction was indeed allowed) and unwrap
// we can't simply use original in refchecks because it does not contains types
// (and the only typed trees we have have been mangled so they're not quite the original tree anymore)
- checkBounds(result.pos, tpt1.tpe.prefix, tpt1.symbol.owner, tpt1.symbol.typeParams, argtypes, "") match {
- case Some(err) => Left(err)
- case _ => Right(result) // you only get to see the wrapped tree after running this check :-p
- }
+ checkBounds(result.pos, tpt1.tpe.prefix, tpt1.symbol.owner, tpt1.symbol.typeParams, argtypes, "")
+ result // you only get to see the wrapped tree after running this check :-p
}).setType(result.tpe)
else result
} else if (tparams.isEmpty) {
- AppliedTypeNoParametersError(tree, tpt1.tpe)
+ errorTree(tree, tpt1.tpe+" does not take type parameters")
} else {
//Console.println("\{tpt1}:\{tpt1.symbol}:\{tpt1.symbol.info}")
if (settings.debug.value) Console.println(tpt1+":"+tpt1.symbol+":"+tpt1.symbol.info)//debug
- AppliedTypeWrongNumberOfArgsError(tree, "wrong number of type arguments for "+tpt1.tpe+", should be "+tparams.length)
+ errorTree(tree, "wrong number of type arguments for "+tpt1.tpe+", should be "+tparams.length)
}
}
}
@@ -4260,12 +3988,7 @@ trait Typers extends Modes with Adaptations {
//if (settings.debug.value && tree.isDef) log("typing definition of "+sym);//DEBUG
tree match {
case PackageDef(pid, stats) =>
- val pid1 = typedQualifier(pid) match {
- case e: ErrorTree =>
- RefTreeError(e, pid.name)
- case t: RefTree =>
- t
- }
+ val pid1 = typedQualifier(pid).asInstanceOf[RefTree]
assert(sym.moduleClass ne NoSymbol, sym)
// complete lazy annotations
val annots = sym.annotations
@@ -4300,9 +4023,6 @@ trait Typers extends Modes with Adaptations {
typer1.silent(_.typedUseCase(useCase)) match {
case ex: TypeError =>
unit.warning(useCase.pos, ex.msg)
- case tree: Tree if tree.containsError() =>
- val ex = quickErrorTreeFinder(tree)
- unit.warning(useCase.pos, ex.exception.msg)
case _ =>
}
for (useCaseSym <- useCase.defined) {
@@ -4325,14 +4045,9 @@ trait Typers extends Modes with Adaptations {
treeCopy.Alternative(tree, alts1) setType pt
case Star(elem) =>
- val err0 = checkStarPatOK(tree.pos, mode)
+ checkStarPatOK(tree.pos, mode)
val elem1 = typed(elem, mode, pt)
- val elem2 = err0 match {
- case Some(err) =>
- wrapInBlock(err, elem1)
- case _ => elem1
- }
- treeCopy.Star(tree, elem2) setType makeFullyDefined(pt)
+ treeCopy.Star(tree, elem1) setType makeFullyDefined(pt)
case Bind(name, body) =>
typedBind(name, body)
@@ -4416,32 +4131,25 @@ trait Typers extends Modes with Adaptations {
val tparam = context.owner freshExistential "" setInfo TypeBounds.upper(pt)
ExistentialType(List(tparam), arrayType(tparam.tpe))
}
-
- if (expr0.containsError())
- treeCopy.Typed(tree, expr0, tpt setType ErrorType) setType ErrorType
- else {
- val (expr1, baseClass) = expr0.tpe.typeSymbol match {
- case ArrayClass => (adapt(expr0, onlyStickyModes(mode), subArrayType(pt)), ArrayClass)
- case _ => (adapt(expr0, onlyStickyModes(mode), seqType(pt)), SeqClass)
- }
- expr1.tpe.baseType(baseClass) match {
- case TypeRef(_, _, List(elemtp)) =>
- treeCopy.Typed(tree, expr1, tpt setType elemtp) setType elemtp
- case _ =>
- setError(tree)
- }
+ val (expr1, baseClass) = expr0.tpe.typeSymbol match {
+ case ArrayClass => (adapt(expr0, onlyStickyModes(mode), subArrayType(pt)), ArrayClass)
+ case _ => (adapt(expr0, onlyStickyModes(mode), seqType(pt)), SeqClass)
+ }
+ expr1.tpe.baseType(baseClass) match {
+ case TypeRef(_, _, List(elemtp)) =>
+ treeCopy.Typed(tree, expr1, tpt setType elemtp) setType elemtp
+ case _ =>
+ setError(tree)
}
case Typed(expr, tpt) =>
val tpt1 = typedType(tpt, mode)
val expr1 = typed(expr, onlyStickyModes(mode), tpt1.tpe.deconst)
- val (expr2, ownType) = if (isPatternMode)
- inferTypedPattern(tpt1.pos, tpt1.tpe, pt) match {
- case Left(err) =>
- (wrapInBlock(expr1, err), ErrorType)
- case Right(tp) => (expr1, tp)
- } else (expr1, tpt1.tpe)
- treeCopy.Typed(tree, expr1, tpt1) setType ownType
+ val owntype =
+ if (isPatternMode) inferTypedPattern(tpt1.pos, tpt1.tpe, pt)
+ else tpt1.tpe
+ //Console.println(typed pattern: "+tree+":"+", tp = "+tpt1.tpe+", pt = "+pt+" ==> "+owntype)//DEBUG
+ treeCopy.Typed(tree, expr1, tpt1) setType owntype
case TypeApply(fun, args) =>
// @M: kind-arity checking is done here and in adapt, full kind-checking is in checkKindBounds (in Infer)
@@ -4484,8 +4192,6 @@ trait Typers extends Modes with Adaptations {
case Apply(fun, args) =>
typedApply(fun, args) match {
- case tree1 if tree1.containsError() =>
- tree1
case Apply(Select(New(tpt), name), args)
if (tpt.tpe != null &&
tpt.tpe.typeSymbol == ArrayClass &&
@@ -4495,14 +4201,12 @@ trait Typers extends Modes with Adaptations {
// convert new Array^N[T](len) for N > 1 to evidence[ClassManifest[T]].newArrayN(len)
val Some((level, manifType)) = erasure.GenericArray.unapply(tpt.tpe)
if (level > MaxArrayDims)
- MultiDimensionalArrayError(tree)
- else {
- val newArrayApp = atPos(tree.pos) {
- val manif = getManifestTree(tree.pos, manifType, false)
- new ApplyToImplicitArgs(Select(manif, if (level == 1) "newArray" else "newArray"+level), args)
- }
- typed(newArrayApp, mode, pt)
+ error(tree.pos, "cannot create a generic multi-dimensional array of more than "+MaxArrayDims+" dimensions")
+ val newArrayApp = atPos(tree.pos) {
+ val manif = getManifestTree(tree.pos, manifType, false)
+ new ApplyToImplicitArgs(Select(manif, if (level == 1) "newArray" else "newArray"+level), args)
}
+ typed(newArrayApp, mode, pt)
case tree1 =>
tree1
}
@@ -4531,26 +4235,20 @@ trait Typers extends Modes with Adaptations {
if (name.isTypeName) qual1 = checkStable(qual1)
val tree1 = // temporarily use `filter` and an alternative for `withFilter`
- if (qual1.containsError())
- treeCopy.Select(tree, qual1, name) setType ErrorType
- else if (name == nme.withFilter)
+ if (name == nme.withFilter)
silent(_ => typedSelect(qual1, name)) match {
- case result1: Tree if !result1.containsError() =>
+ case result1: Tree =>
result1
- case ex1 =>
+ case ex1: TypeError =>
silent(_ => typed1(Select(qual1, nme.filter) setPos tree.pos, mode, pt)) match {
case result2: Tree =>
unit.deprecationWarning(
tree.pos, "`withFilter' method does not yet exist on "+qual1.tpe.widen+
", using `filter' method instead")
result2
- case _: TypeError =>
- val ex2 = ex1 match {
- case te: TypeError => te
- case t: Tree =>
- quickErrorTreeFinder(t).exception
- }
- WithFilterError(tree, ex2)
+ case ex2: TypeError =>
+ reportTypeError(tree.pos, ex1)
+ setError(tree)
}
}
else
@@ -4575,17 +4273,12 @@ trait Typers extends Modes with Adaptations {
case SingletonTypeTree(ref) =>
val ref1 = checkStable(
typed(ref, EXPRmode | QUALmode | (mode & TYPEPATmode), AnyRefClass.tpe))
- if (ref1.containsError())
- treeCopy.SingletonTypeTree(tree, ref1) setType ErrorType
- else
- tree setType ref1.tpe.resultType
+ tree setType ref1.tpe.resultType
case SelectFromTypeTree(qual, selector) =>
val qual1 = typedType(qual, mode)
- if (qual1.tpe.isVolatile)
- TypeSelectionFromVolatileTypeError(tree, qual)
- else
- typedSelect(qual1, selector)
+ if (qual1.tpe.isVolatile) error(tree.pos, "illegal type selection from volatile type "+qual.tpe)
+ typedSelect(qual1, selector)
case CompoundTypeTree(templ) =>
typedCompoundTypeTree(templ)
@@ -4618,39 +4311,6 @@ trait Typers extends Modes with Adaptations {
}
}
- def handleErrorTree(t: Tree) {
- val allErrors = errorTreesFinder(t)
-
- // Report any errors if possible in the current context
- // If an error tree throws type error (we are in silent mode), then we will not mark
- // tree as visited and it will be reported later if necessary
- allErrors.foreach { t0 =>
- try {
- if (settings.errortrees.value) {
- println("[ErrorTree emit] " + t0)
- if (t0.exception != null) {
- println(t0.exception.getClass)
- }
- }
- t0.emit(context)
- t0.reported = true
- } catch {
- case te: TypeError =>
- // Catch all type errors if we are in typer phase.
- // All typer errors will be reported at some point anyway.
- if (settings.errortrees.value)
- println("[ErrorTree TypeError] Throws " + te)
-
- // After typer all bets are off
- // and we do not try to hide TypeError within error tree
- if (phase.id > currentRun.typerPhase.id) {
- t0.reported = true
- throw te
- }
- }
- }
- }
-
/**
* @param tree ...
* @param mode ...
@@ -4694,36 +4354,22 @@ trait Typers extends Modes with Adaptations {
tree1
}
- if (tree1.containsError()) {
- handleErrorTree(tree1)
- if (phase.id <= currentRun.typerPhase.id) signalDone(context.asInstanceOf[analyzer.Context], tree, tree1)
- tree1
- } else {
- tree1.tpe = addAnnotations(tree1, tree1.tpe)
- val result = if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt, tree)
+ tree1.tpe = addAnnotations(tree1, tree1.tpe)
+ val result = if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt, tree)
- if (!alreadyTyped) {
- printTyping("adapted %s: %s to %s, %s".format(
- tree1, tree1.tpe.widen, pt, context.undetparamsString)
- ) //DEBUG
- }
- if (phase.id <= currentRun.typerPhase.id) signalDone(context.asInstanceOf[analyzer.Context], tree, result)
- if (result.containsError()) handleErrorTree(result)
- result
+ if (!alreadyTyped) {
+ printTyping("adapted %s: %s to %s, %s".format(
+ tree1, tree1.tpe.widen, pt, context.undetparamsString)
+ ) //DEBUG
}
+
+// for (t <- tree1.tpe) assert(t != WildcardType)
+// if ((mode & TYPEmode) != 0) println("type: "+tree1+" has type "+tree1.tpe)
+ if (phase.id <= currentRun.typerPhase.id) signalDone(context.asInstanceOf[analyzer.Context], tree, result)
+ result
} catch {
case ex: TypeError =>
tree.tpe = null
- // At some point we might want to get rid of the code below
- // because everything will be handled by error trees.
- // The only problematic case are Cyclic errors which can pop up almost anywhere
- if (settings.errortrees.value) {
- println("[ErrorTree CAUGHT] %s: while typing %s".format(ex, tree))
- println("TODO with error trees shouldn't throw non-cyclic errors")
- ex.printStackTrace()
- println("----------")
- }
-
printTyping("caught %s: while typing %s".format(ex, tree)) //DEBUG
reportTypeError(tree.pos, ex)
setError(tree)
@@ -4827,12 +4473,12 @@ trait Typers extends Modes with Adaptations {
// to see are those in the signatures. These do not need a unique object as a prefix.
// The situation is different for new's and super's, but scalac does not look deep
// enough to see those. See #3938
- return ConstructorPrefixError(tree, restpe)
+ error(tree.pos, restpe.prefix+" is not a legal prefix for a constructor")
}
//@M fix for #2208
// if there are no type arguments, normalization does not bypass any checks, so perform it to get rid of AnyRef
- if (result.tpe.typeArgs.isEmpty && !result.containsError()) {
+ if(result.tpe.typeArgs.isEmpty) {
// minimal check: if(result.tpe.typeSymbolDirect eq AnyRefClass) {
// must expand the fake AnyRef type alias, because bootstrapping (init in Definitions) is not
// designed to deal with the cycles in the scala package (ScalaObject extends
@@ -4848,23 +4494,10 @@ trait Typers extends Modes with Adaptations {
def typedTypeConstructor(tree: Tree): Tree = typedTypeConstructor(tree, NOmode)
- // Because this is called from Namers and pattern matcher, we
- // have to report missing errors (if any)
def computeType(tree: Tree, pt: Type): Type = {
val tree1 = typed(tree, pt)
- if (tree1.containsError())
- ErrorType
- else {
- transformed(tree) = tree1
- val (tpe, errs) = packedType(tree1, context.owner)
- try {
- errs.foreach(_.emit(context))
- tpe
- } catch {
- case _: TypeError =>
- ErrorType
- }
- }
+ transformed(tree) = tree1
+ packedType(tree1, context.owner)
}
def transformedOrTyped(tree: Tree, mode: Int, pt: Type): Tree = transformed.get(tree) match {
@@ -4882,7 +4515,8 @@ trait Typers extends Modes with Adaptations {
def getManifestTree(pos: Position, tp: Type, full: Boolean): Tree = {
val manifestOpt = findManifest(tp, full)
if (manifestOpt.tree.isEmpty) {
- MissingManifestError(pos, full, tp)
+ error(pos, "cannot find "+(if (full) "" else "class ")+"manifest for element type "+tp)
+ Literal(Constant(null))
} else {
manifestOpt.tree
}