/* NSC -- new Scala compiler * Copyright 2005-2011 LAMP/EPFL * @author Martin Odersky */ package scala.tools.nsc package typechecker import scala.collection.{ mutable, immutable } import scala.tools.util.StringOps.{ countElementsAsString, countAsString } import symtab.Flags.{ PRIVATE, PROTECTED } import scala.tools.util.EditDistance.similarString trait ContextErrors { self: Analyzer => import global._ object ErrorKinds extends Enumeration { type ErrorKind = Value val Normal, Access, Ambiguous, Divergent = Value } import ErrorKinds.ErrorKind trait AbsTypeError extends Throwable { def errPos: Position def errMsg: String def kind: ErrorKind } case class NormalTypeError(underlyingTree: Tree, errMsg: String, kind: ErrorKind = ErrorKinds.Normal) extends AbsTypeError { def errPos:Position = underlyingTree.pos override def toString() = "[Type error at:" + underlyingTree.pos + "] " + errMsg } case class SymbolTypeError(underlyingSym: Symbol, errMsg: String, kind: ErrorKind = ErrorKinds.Normal) extends AbsTypeError { def errPos = underlyingSym.pos } case class TypeErrorWrapper(ex: TypeError, kind: ErrorKind = ErrorKinds.Normal) extends AbsTypeError { def errMsg = ex.msg def errPos = ex.pos } case class TypeErrorWithUnderlyingTree(tree: Tree, ex: TypeError, kind: ErrorKind = ErrorKinds.Normal) extends AbsTypeError { def errMsg = ex.msg def errPos = tree.pos } case class AmbiguousTypeError(underlyingTree: Tree, errPos: Position, errMsg: String, kind: ErrorKind = ErrorKinds.Ambiguous) extends AbsTypeError case class PosAndMsgTypeError(errPos: Position, errMsg: String, kind: ErrorKind = ErrorKinds.Normal) extends AbsTypeError object ErrorUtils { def issueNormalTypeError(tree: Tree, msg: String)(implicit context: Context) { issueTypeError(NormalTypeError(tree, msg)) } def issueSymbolTypeError(sym: Symbol, msg: String)(implicit context: Context) { issueTypeError(SymbolTypeError(sym, msg)) } def issueDivergentImplicitsError(tree: Tree, msg: String)(implicit context: Context) { issueTypeError(NormalTypeError(tree, msg, ErrorKinds.Divergent)) } def issueAmbiguousTypeError(pre: Type, sym1: Symbol, sym2: Symbol, err: AmbiguousTypeError)(implicit context: Context) { context.issueAmbiguousError(pre, sym1, sym2, err) } def issueTypeError(err: AbsTypeError)(implicit context: Context) { context.issue(err) } def typeErrorMsg(found: Type, req: Type, possiblyMissingArgs: Boolean) = { def missingArgsMsg = if (possiblyMissingArgs) "\n possible cause: missing arguments for method or constructor" else "" "type mismatch" + foundReqMsg(found, req) + missingArgsMsg } } import ErrorUtils._ trait TyperContextErrors { self: Typer => import infer.setError object TyperErrorGen { implicit val context0: Context = infer.getContext def UnstableTreeError(tree: Tree) = { def addendum = { "\n Note that "+tree.symbol+" is not stable because its type, "+tree.tpe+", is volatile." } issueNormalTypeError(tree, "stable identifier required, but "+tree+" found." + ( if (isStableExceptVolatile(tree)) addendum else "")) setError(tree) } def NoImplicitFoundError(tree: Tree, param: Symbol) = { 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 } } issueNormalTypeError(tree, errMsg) } def AdaptTypeError(tree: Tree, found: Type, req: Type) = { // 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 // members present, then display along with the expected members. This is done here because // this is the last point where we still have access to the original tree, rather than just // the found/req types. val foundType: Type = req.normalize match { case RefinedType(parents, decls) if !decls.isEmpty && found.typeSymbol.isAnonOrRefinementClass => val retyped = typed (tree.duplicate setType null) val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic) if (foundDecls.isEmpty) found else { // The members arrive marked private, presumably because there was no // expected type and so they're considered members of an anon class. foundDecls foreach (_ resetFlag (PRIVATE | PROTECTED)) // TODO: if any of the found parents match up with required parents after normalization, // print the error so that they match. The major beneficiary there would be // java.lang.Object vs. AnyRef. refinedType(found.parents, found.typeSymbol.owner, foundDecls, tree.pos) } case _ => found } assert(!found.isErroneous && !req.isErroneous, (found, req)) issueNormalTypeError(tree, withAddendum(tree.pos)(typeErrorMsg(found, req, infer.isPossiblyMissingArgs(found, req))) ) if (settings.explaintypes.value) explainTypes(found, req) } def WithFilterError(tree: Tree, ex: AbsTypeError) = { issueTypeError(ex) setError(tree) } def ParentTypesError(templ: Template, ex: TypeError) = { templ.tpe = null issueNormalTypeError(templ, ex.getMessage()) } // additional parentTypes errors def ConstrArgsInTraitParentTpeError(arg: Tree, parent: Symbol) = issueNormalTypeError(arg, parent + " is a trait; does not take constructor arguments") def MissingTypeArgumentsParentTpeError(supertpt: Tree) = issueNormalTypeError(supertpt, "missing type arguments") // typedIdent def AmbiguousIdentError(tree: Tree, name: Name, msg: String) = NormalTypeError(tree, "reference to " + name + " is ambiguous;\n" + msg) def SymbolNotFoundError(tree: Tree, name: Name, owner: Symbol, startingIdentCx: Context) = { /*** Disabled pending investigation of performance impact. // This laborious determination arrived at to keep the tests working. val calcSimilar = ( name.length > 2 && ( startingIdentCx.reportErrors || startingIdentCx.enclClassOrMethod.reportErrors ) ) // avoid calculating if we're in "silent" mode. // name length check to limit unhelpful suggestions for e.g. "x" and "b1" val similar = { if (!calcSimilar) "" else { val allowed = ( startingIdentCx.enclosingContextChain flatMap (ctx => ctx.scope.toList ++ ctx.imports.flatMap(_.allImportedSymbols)) filter (sym => sym.isTerm == name.isTermName) filterNot (sym => sym.isPackage || sym.isSynthetic || sym.hasMeaninglessName) ) val allowedStrings = ( allowed.map("" + _.name).distinct.sorted filterNot (s => (s contains '$') || (s contains ' ')) ) similarString("" + name, allowedStrings) } } */ val similar = "" NormalTypeError(tree, "not found: "+decodeWithKind(name, owner) + similar) } // typedAppliedTypeTree def AppliedTypeNoParametersError(tree: Tree, errTpe: Type) = { issueNormalTypeError(tree, errTpe + " does not take type parameters") setError(tree) } def AppliedTypeWrongNumberOfArgsError(tree: Tree, tpt: Tree, tparams: List[Symbol]) = { val tptSafeString: String = try { tpt.tpe.toString() } catch { case _: CyclicReference => tpt.toString() } val msg = "wrong number of type arguments for "+tptSafeString+", should be "+tparams.length issueNormalTypeError(tree, msg) setError(tree) } // typedTypeDef def LowerBoundError(tree: TypeDef, lowB: Type, highB: Type) = issueNormalTypeError(tree, "lower bound "+lowB+" does not conform to upper bound "+highB) def HiddenSymbolWithError[T <: Tree](tree: T): T = setError(tree) def SymbolEscapesScopeError[T <: Tree](tree: T, badSymbol: Symbol): T = { val modifierString = if (badSymbol.isPrivate) "private " else "" issueNormalTypeError(tree, modifierString + badSymbol + " escapes its defining scope as part of type "+tree.tpe) setError(tree) } // typedDefDef def StarParamNotLastError(param: Tree) = issueNormalTypeError(param, "*-parameter must come last") def StarWithDefaultError(meth: Symbol) = issueSymbolTypeError(meth, "a parameter section with a `*'-parameter is not allowed to have default arguments") def InvalidConstructorDefError(ddef: Tree) = issueNormalTypeError(ddef, "constructor definition not allowed here") def DeprecatedParamNameError(param: Symbol, name: Name) = issueSymbolTypeError(param, "deprecated parameter name "+ name +" has to be distinct from any other parameter name (deprecated or not).") // computeParamAliases def SuperConstrReferenceError(tree: Tree) = NormalTypeError(tree, "super constructor cannot be passed a self reference unless parameter is declared by-name") def SuperConstrArgsThisReferenceError(tree: Tree) = NormalTypeError(tree, "super constructor arguments cannot reference unconstructed `this`") // typedValDef def VolatileValueError(vdef: Tree) = issueNormalTypeError(vdef, "values cannot be volatile") def FinalVolatileVarError(vdef: Tree) = issueNormalTypeError(vdef, "final vars cannot be volatile") def LocalVarUninitializedError(vdef: Tree) = issueNormalTypeError(vdef, "local variables must be initialized") //typedAssign def AssignmentError(tree: Tree, varSym: Symbol) = { issueNormalTypeError(tree, if (varSym != null && varSym.isValue) "reassignment to val" else "assignment to non variable") setError(tree) } def UnexpectedTreeAssignmentConversionError(tree: Tree) = { issueNormalTypeError(tree, "Unexpected tree during assignment conversion.") setError(tree) } def MultiDimensionalArrayError(tree: Tree) = { issueNormalTypeError(tree, "cannot create a generic multi-dimensional array of more than "+ definitions.MaxArrayDims+" dimensions") setError(tree) } //typedSuper def MixinMissingParentClassNameError(tree: Tree, mix: Name, clazz: Symbol) = issueNormalTypeError(tree, mix+" does not name a parent class of "+clazz) def AmbiguousParentClassError(tree: Tree) = issueNormalTypeError(tree, "ambiguous parent class qualifier") //typedSelect def NotAMemberError(sel: Tree, qual: Tree, name: Name) = { 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 ) } issueNormalTypeError(sel, errMsg) // the error has to be set for the copied tree, otherwise // the error remains persistent acros multiple compilations // and causes problems //setError(sel) } //typedNew def IsAbstractError(tree: Tree, sym: Symbol) = { issueNormalTypeError(tree, sym + " is abstract; cannot be instantiated") setError(tree) } def DoesNotConformToSelfTypeError(tree: Tree, sym: Symbol, tpe0: Type) = { issueNormalTypeError(tree, sym + " cannot be instantiated because it does not conform to its self-type " + tpe0) setError(tree) } //typedEta def UnderscoreEtaError(tree: Tree) = { issueNormalTypeError(tree, "_ must follow method; cannot follow " + tree.tpe) setError(tree) } //typedReturn def ReturnOutsideOfDefError(tree: Tree) = { issueNormalTypeError(tree, "return outside method definition") setError(tree) } def ReturnWithoutTypeError(tree: Tree, owner: Symbol) = { issueNormalTypeError(tree, owner + " has return statement; needs result type") setError(tree) } //typedBind def VariableInPatternAlternativeError(tree: Tree) = { issueNormalTypeError(tree, "illegal variable in pattern alternative") //setError(tree) } //typedCase def StarPositionInPatternError(tree: Tree) = issueNormalTypeError(tree, "_* may only come last") //typedFunction def MaxFunctionArityError(fun: Tree) = { issueNormalTypeError(fun, "implementation restricts functions to " + definitions.MaxFunctionArity + " parameters") setError(fun) } def WrongNumberOfParametersError(tree: Tree, argpts: List[Type]) = { issueNormalTypeError(tree, "wrong number of parameters; expected = " + argpts.length) setError(tree) } def MissingParameterTypeError(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 }) issueNormalTypeError(vparam, "missing parameter type" + suffix) } def ConstructorsOrderError(tree: Tree) = { issueNormalTypeError(tree, "called constructor's definition must precede calling constructor's definition") setError(tree) } def OnlyDeclarationsError(tree: Tree) = { issueNormalTypeError(tree, "only declarations allowed here") setError(tree) } // typedAnnotation def AnnotationNotAConstantError(tree: Tree) = NormalTypeError(tree, "annotation argument needs to be a constant; found: " + tree) def AnnotationArgNullError(tree: Tree) = NormalTypeError(tree, "annotation argument cannot be null") def ArrayConstantsError(tree: Tree) = NormalTypeError(tree, "Array constants have to be specified using the `Array(...)' factory method") def ArrayConstantsTypeMismatchError(tree: Tree, pt: Type) = NormalTypeError(tree, "found array constant, expected argument of type " + pt) def UnexpectedTreeAnnotation(tree: Tree) = NormalTypeError(tree, "unexpected tree in annotation: "+ tree) def AnnotationTypeMismatchError(tree: Tree, expected: Type, found: Type) = NormalTypeError(tree, "expected annotation of type " + expected + ", found " + found) def MultipleArgumentListForAnnotationError(tree: Tree) = NormalTypeError(tree, "multiple argument lists on classfile annotation") def UnknownAnnotationNameError(tree: Tree, name: Name) = NormalTypeError(tree, "unknown annotation argument name: " + name) def DuplicateValueAnnotationError(tree: Tree, name: Name) = NormalTypeError(tree, "duplicate value for annotation argument " + name) def ClassfileAnnotationsAsNamedArgsError(tree: Tree) = NormalTypeError(tree, "classfile annotation arguments have to be supplied as named arguments") def AnnotationMissingArgError(tree: Tree, annType: Type, sym: Symbol) = NormalTypeError(tree, "annotation " + annType.typeSymbol.fullName + " is missing argument " + sym.name) def NestedAnnotationError(tree: Tree, annType: Type) = NormalTypeError(tree, "nested classfile annotations must be defined in java; found: "+ annType) def UnexpectedTreeAnnotationError(tree: Tree, unexpected: Tree) = NormalTypeError(tree, "unexpected tree after typing annotation: "+ unexpected) // TODO no test case //typedExistentialTypeTree def AbstractionFromVolatileTypeError(vd: ValDef) = issueNormalTypeError(vd, "illegal abstraction from value with volatile type "+vd.symbol.tpe) def TypedApplyWrongNumberOfTpeParametersError(tree: Tree, fun: Tree) = { issueNormalTypeError(tree, "wrong number of type parameters for "+treeSymTypeMsg(fun)) setError(tree) } def TypedApplyDoesNotTakeTpeParametersError(tree: Tree, fun: Tree) = { issueNormalTypeError(tree, treeSymTypeMsg(fun)+" does not take type parameters.") setError(tree) } // doTypeApply //tryNamesDefaults def WrongNumberOfArgsError(tree: Tree, fun: Tree) = NormalTypeError(tree, "wrong number of arguments for "+ treeSymTypeMsg(fun)) def TooManyArgsNamesDefaultsError(tree: Tree, fun: Tree) = NormalTypeError(tree, "too many arguments for "+treeSymTypeMsg(fun)) // can it still happen? see test case neg/t960.scala // TODO no test case def OverloadedUnapplyError(tree: Tree) = issueNormalTypeError(tree, "cannot resolve overloaded unapply") def UnapplyWithSingleArgError(tree: Tree) = issueNormalTypeError(tree, "an unapply method must accept a single argument.") def MultipleVarargError(tree: Tree) = NormalTypeError(tree, "when using named arguments, the vararg parameter has to be specified exactly once") def ModuleUsingCompanionClassDefaultArgsErrror(tree: Tree) = NormalTypeError(tree, "module extending its companion class cannot use default constructor arguments") def NotEnoughArgsError(tree: Tree, fun0: Tree, missing0: List[Symbol]) = { 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 } NormalTypeError(tree, notEnoughArgumentsMsg(fun0, missing0)) } //doTypedApply - patternMode // TODO: missing test case def TooManyArgsPatternError(fun: Tree) = NormalTypeError(fun, "too many arguments for unapply pattern, maximum = "+definitions.MaxTupleArity) def WrongNumberArgsPatternError(tree: Tree, fun: Tree) = NormalTypeError(tree, "wrong number of arguments for "+treeSymTypeMsg(fun)) def ApplyWithoutArgsError(tree: Tree, fun: Tree) = NormalTypeError(tree, fun.tpe+" does not take parameters") //checkClassType def TypeNotAStablePrefixError(tpt: Tree, pre: Type) = { issueNormalTypeError(tpt, "type "+pre+" is not a stable prefix") setError(tpt) } def ClassTypeRequiredError(tree: Tree, found: AnyRef) = { issueNormalTypeError(tree, "class type required but "+found+" found") setError(tree) } // validateParentClasses def ParentSuperSubclassError(parent: Tree, superclazz: Symbol, parentSym: Symbol, mixin: Symbol) = NormalTypeError(parent, "illegal inheritance; super"+superclazz+ "\n is not a subclass of the super"+parentSym+ "\n of the mixin " + mixin) def ParentNotATraitMixinError(parent: Tree, mixin: Symbol) = NormalTypeError(parent, mixin+" needs to be a trait to be mixed in") def ParentFinalInheritanceError(parent: Tree, mixin: Symbol) = NormalTypeError(parent, "illegal inheritance from final "+mixin) def ParentSealedInheritanceError(parent: Tree, psym: Symbol) = NormalTypeError(parent, "illegal inheritance from sealed " + psym + ": " + context.unit.source.file.canonicalPath + " != " + psym.sourceFile.canonicalPath) def ParentSelfTypeConformanceError(parent: Tree, selfType: Type) = NormalTypeError(parent, "illegal inheritance;\n self-type "+selfType+" does not conform to "+ parent +"'s selftype "+parent.tpe.typeOfThis) // TODO: missing test case def ParentInheritedTwiceError(parent: Tree, parentSym: Symbol) = NormalTypeError(parent, parentSym+" is inherited twice") //adapt def MissingArgsForMethodTpeError(tree: Tree, meth: Symbol) = { issueNormalTypeError(tree, "missing arguments for " + meth.fullLocationString + ( if (meth.isConstructor) "" else ";\nfollow this method with `_' if you want to treat it as a partially applied function" )) setError(tree) } def MissingTypeParametersError(tree: Tree) = { issueNormalTypeError(tree, tree.symbol+" takes type parameters") setError(tree) } def KindArityMismatchError(tree: Tree, pt: Type) = { issueNormalTypeError(tree, tree.tpe+" takes "+countElementsAsString(tree.tpe.typeParams.length, "type parameter")+ ", expected: "+countAsString(pt.typeParams.length)) setError(tree) } def CaseClassConstructorError(tree: Tree) = { issueNormalTypeError(tree, tree.symbol + " is not a case class constructor, nor does it have an unapply/unapplySeq method") setError(tree) } //TODO Needs test case def ConstructorPrefixError(tree: Tree, restpe: Type) = { issueNormalTypeError(tree, restpe.prefix+" is not a legal prefix for a constructor") setError(tree) } // SelectFromTypeTree def TypeSelectionFromVolatileTypeError(tree: Tree, qual: Tree) = { issueNormalTypeError(tree, "illegal type selection from volatile type "+qual.tpe) setError(tree) } // packedType def InferTypeWithVolatileTypeSelectionError(tree: Tree, pre: Type) = issueNormalTypeError(tree, "Inferred type "+tree.tpe+" contains type selection from volatile type "+pre) def AbstractExistentiallyOverParamerizedTpeError(tree: Tree, tp: Type) = issueNormalTypeError(tree, "can't existentially abstract over parameterized type " + tp) //manifestTreee def MissingManifestError(tree: Tree, full: Boolean, tp: Type) = { issueNormalTypeError(tree, "cannot find "+(if (full) "" else "class ")+"manifest for element type "+tp) setError(tree) } // TODO needs test case // cases where we do not necessarily return trees def DependentMethodTpeConversionToFunctionError(tree: Tree, tp: Type) = issueNormalTypeError(tree, "method with dependent type "+tp+" cannot be converted to function value") //checkStarPatOK def StarPatternWithVarargParametersError(tree: Tree) = issueNormalTypeError(tree, "star patterns must correspond with varargs parameters") // TODO missing test case def FinitaryError(tparam: Symbol) = issueSymbolTypeError(tparam, "class graph is not finitary because type parameter "+tparam.name+" is expansively recursive") // TODO missing test case for a second case def QualifyingClassError(tree: Tree, qual: Name) = { issueNormalTypeError(tree, if (qual.isEmpty) tree + " can be used only in a class, object, or template" else qual + " is not an enclosing class") setError(tree) } // def stabilize def NotAValueError(tree: Tree, sym: Symbol) = { issueNormalTypeError(tree, sym.kindString + " " + sym.fullName + " is not a value") setError(tree) } // checkNoDoubleDefs... def DefDefinedTwiceError(sym0: Symbol, sym1: Symbol) = issueSymbolTypeError(sym0, sym1+" is defined twice"+ {if(!settings.debug.value) "" else " in "+context0.unit}+ {if (sym0.isMacro && sym1.isMacro) " \n(note that macros cannot be overloaded)" else ""}) // cyclic errors def CyclicAliasingOrSubtypingError(errPos: Position, sym0: Symbol) = issueTypeError(PosAndMsgTypeError(errPos, "cyclic aliasing or subtyping involving "+sym0)) def CyclicReferenceError(errPos: Position, lockedSym: Symbol) = issueTypeError(PosAndMsgTypeError(errPos, "illegal cyclic reference involving " + lockedSym)) } } trait InferencerContextErrors { 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 } } object InferErrorGen { implicit val context0 = getContext object PolyAlternativeErrorKind extends Enumeration { type ErrorType = Value val WrongNumber, NoParams, ArgsDoNotConform = Value } private def ambiguousErrorMsgPos(pos: Position, pre: Type, sym1: Symbol, sym2: Symbol, rest: String) = if (sym1.hasDefaultFlag && sym2.hasDefaultFlag && sym1.enclClass == sym2.enclClass) { val methodName = nme.defaultGetterToMethod(sym1.name) (sym1.enclClass.pos, "in "+ sym1.enclClass +", multiple overloaded alternatives of " + methodName + " define default arguments") } else { (pos, ("ambiguous reference to overloaded definition,\n" + "both " + sym1 + sym1.locationString + " of type " + pre.memberType(sym1) + "\nand " + sym2 + sym2.locationString + " of type " + pre.memberType(sym2) + "\nmatch " + rest) ) } def AccessError(tree: Tree, sym: Symbol, pre: Type, owner0: Symbol, explanation: String) = { def errMsg = { val location = if (sym.isClassConstructor) owner0 else pre.widen underlying(sym).fullLocationString + " cannot be accessed in " + location + explanation } NormalTypeError(tree, errMsg, ErrorKinds.Access) } def NoMethodInstanceError(fn: Tree, args: List[Tree], msg: String) = issueNormalTypeError(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) // TODO: no test case def NoConstructorInstanceError(tree: Tree, restpe: Type, pt: Type, msg: String) = { issueNormalTypeError(tree, "constructor of type " + restpe + " cannot be uniquely instantiated to expected type " + pt + "\n --- because ---\n" + msg) setError(tree) } def ConstrInstantiationError(tree: Tree, restpe: Type, pt: Type) = { issueNormalTypeError(tree, "constructor cannot be instantiated to expected type" + foundReqMsg(restpe, pt)) setError(tree) } def NoBestMethodAlternativeError(tree: Tree, argtpes: List[Type], pt: Type) = { issueNormalTypeError(tree, applyErrorMsg(tree, " cannot be applied to ", argtpes, pt)) // since inferMethodAlternative modifies the state of the tree // we have to set the type of tree to ErrorType only in the very last // fallback action that is done in the inference (tracking it manually is error prone). // This avoids entering infinite loop in doTypeApply. // TODO: maybe we should do the same thing with inferExprAlternative. if (implicitly[Context].reportErrors) setError(tree) } def AmbiguousMethodAlternativeError(tree: Tree, pre: Type, best: Symbol, firstCompeting: Symbol, argtpes: List[Type], pt: Type) = { val msg0 = "argument types " + argtpes.mkString("(", ",", ")") + (if (pt == WildcardType) "" else " and expected result type " + pt) val (pos, msg) = ambiguousErrorMsgPos(tree.pos, pre, best, firstCompeting, msg0) issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(tree, pos, msg)) } def NoBestExprAlternativeError(tree: Tree, pt: Type) = issueNormalTypeError(tree, withAddendum(tree.pos)(typeErrorMsg(tree.symbol.tpe, pt, isPossiblyMissingArgs(tree.symbol.tpe, pt)))) def AmbiguousExprAlternativeError(tree: Tree, pre: Type, best: Symbol, firstCompeting: Symbol, pt: Type) = { val (pos, msg) = ambiguousErrorMsgPos(tree.pos, pre, best, firstCompeting, "expected type " + pt) setError(tree) issueAmbiguousTypeError(pre, best, firstCompeting, AmbiguousTypeError(tree, pos, msg)) } // checkBounds def KindBoundErrors(tree: Tree, prefix: String, targs: List[Type], tparams: List[Symbol], kindErrors: List[String]) = { issueNormalTypeError(tree, 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", ", ", "")) } def NotWithinBounds(tree: Tree, prefix: String, targs: List[Type], tparams: List[Symbol], kindErrors: List[String]) = { 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)) () } issueNormalTypeError(tree, prefix + "type arguments " + targs.mkString("[", ",", "]") + " do not conform to " + tparams.head.owner + "'s type parameter bounds " + (tparams map (_.defString)).mkString("[", ",", "]")) } //substExpr def PolymorphicExpressionInstantiationError(tree: Tree, undetparams: List[Symbol], pt: Type) = issueNormalTypeError(tree, "polymorphic expression cannot be instantiated to expected type" + foundReqMsg(polyType(undetparams, skipImplicit(tree.tpe)), pt)) //checkCheckable def TypePatternOrIsInstanceTestError(tree: Tree, tp: Type) = issueNormalTypeError(tree, "type "+tp+" cannot be used in a type pattern or isInstanceOf test") def PatternTypeIncompatibleWithPtError1(tree: Tree, pattp: Type, pt: Type) = issueNormalTypeError(tree, "pattern type is incompatible with expected type" + foundReqMsg(pattp, pt)) def IncompatibleScrutineeTypeError(tree: Tree, pattp: Type, pt: Type) = issueNormalTypeError(tree, "scrutinee is incompatible with pattern type" + foundReqMsg(pattp, pt)) def PatternTypeIncompatibleWithPtError2(pat: Tree, pt1: Type, pt: Type) = { 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 } issueNormalTypeError(pat, errMsg) } def PolyAlternativeError(tree: Tree, argtypes: List[Type], sym: Symbol, err: PolyAlternativeErrorKind.ErrorType) = { import PolyAlternativeErrorKind._ val msg = err match { case WrongNumber => "wrong number of type parameters for " + treeSymTypeMsg(tree) case NoParams => treeSymTypeMsg(tree) + " does not take type parameters" case ArgsDoNotConform => "type arguments " + argtypes.mkString("[", ",", "]") + " conform to the bounds of none of the overloaded alternatives of\n "+sym+ ": "+sym.info } issueNormalTypeError(tree, msg) () } } } trait NamerContextErrors { self: Namer => object NamerErrorGen { implicit val context0 = context object SymValidateErrors extends Enumeration { val ImplicitConstr, ImplicitNotTerm, ImplicitTopObject, OverrideClass, SealedNonClass, AbstractNonClass, OverrideConstr, AbstractOverride, LazyAndEarlyInit, ByNameParameter, AbstractVar = Value } object DuplicatesErrorKinds extends Enumeration { val RenamedTwice, AppearsTwice = Value } import SymValidateErrors._ import DuplicatesErrorKinds._ import symtab.Flags def TypeSigError(tree: Tree, ex: TypeError) = { ex match { case CyclicReference(sym, info: TypeCompleter) => issueNormalTypeError(tree, typer.cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage()) case _ => context0.issue(TypeErrorWithUnderlyingTree(tree, ex)) } } def GetterDefinedTwiceError(getter: Symbol) = issueSymbolTypeError(getter, getter+" is defined twice") def ValOrValWithSetterSuffixError(tree: Tree) = issueNormalTypeError(tree, "Names of vals or vars may not end in `_='") def PrivateThisCaseClassParameterError(tree: Tree) = issueNormalTypeError(tree, "private[this] not allowed for case class parameters") def BeanPropertyAnnotationLimitationError(tree: Tree) = issueNormalTypeError(tree, "implementation limitation: the BeanProperty annotation cannot be used in a type alias or renamed import") def BeanPropertyAnnotationFieldWithoutLetterError(tree: Tree) = issueNormalTypeError(tree, "`BeanProperty' annotation can be applied only to fields that start with a letter") def BeanPropertyAnnotationPrivateFieldError(tree: Tree) = issueNormalTypeError(tree, "`BeanProperty' annotation can be applied only to non-private fields") def DoubleDefError(currentSym: Symbol, prevSym: Symbol) = { val s1 = if (prevSym.isModule) "case class companion " else "" val s2 = if (prevSym.isSynthetic) "(compiler-generated) " + s1 else "" val s3 = if (prevSym.isCase) "case class " + prevSym.name else "" + prevSym issueSymbolTypeError(currentSym, prevSym.name + " is already defined as " + s2 + s3) } def MaxParametersCaseClassError(tree: Tree) = issueNormalTypeError(tree, "Implementation restriction: case classes cannot have more than " + definitions.MaxFunctionArity + " parameters.") def InheritsItselfError(tree: Tree) = issueNormalTypeError(tree, tree.tpe.typeSymbol+" inherits itself") def MissingParameterOrValTypeError(vparam: Tree) = issueNormalTypeError(vparam, "missing parameter type") def RootImportError(tree: Tree) = issueNormalTypeError(tree, "_root_ cannot be imported") def SymbolValidationError(sym: Symbol, errKind: SymValidateErrors.Value) { val msg = errKind match { case ImplicitConstr => "`implicit' modifier not allowed for constructors" case ImplicitNotTerm => "`implicit' modifier can be used only for values, variables and methods" case ImplicitTopObject => "`implicit' modifier cannot be used for top-level objects" case OverrideClass => "`override' modifier not allowed for classes" case SealedNonClass => "`sealed' modifier can be used only for classes" case AbstractNonClass => "`abstract' modifier can be used only for classes; it should be omitted for abstract members" case OverrideConstr => "`override' modifier not allowed for constructors" case AbstractOverride => "`abstract override' modifier only allowed for members of traits" case LazyAndEarlyInit => "`lazy' definitions may not be initialized early" case ByNameParameter => "pass-by-name arguments not allowed for case class parameters" case AbstractVar => "only classes can have declared but undefined members" + abstractVarMessage(sym) } issueSymbolTypeError(sym, msg) } def AbstractMemberWithModiferError(sym: Symbol, flag: Int) = issueSymbolTypeError(sym, "abstract member may not have " + Flags.flagsToString(flag) + " modifier") def IllegalModifierCombination(sym: Symbol, flag1: Int, flag2: Int) = issueSymbolTypeError(sym, "illegal combination of modifiers: %s and %s for: %s".format( Flags.flagsToString(flag1), Flags.flagsToString(flag2), sym)) def IllegalDependentMethTpeError(sym: Symbol)(context: Context) = { val errorAddendum = ": parameter appears in the type of another parameter in the same section or an earlier one" issueSymbolTypeError(sym, "illegal dependent method type" + errorAddendum)(context) } def DuplicatesError(tree: Tree, name: Name, kind: DuplicatesErrorKinds.Value) = { val msg = kind match { case RenamedTwice => "is renamed twice" case AppearsTwice => "appears twice as a target of a renaming" } issueNormalTypeError(tree, name.decode + " " + msg) } } } trait ImplicitsContextErrors { self: ImplicitSearch => import definitions._ def AmbiguousImplicitError(info1: ImplicitInfo, info2: ImplicitInfo, pre1: String, pre2: String, trailer: String) (isView: Boolean, pt: Type, tree: Tree)(implicit context0: Context) = { if (!info1.tpe.isErroneous && !info2.tpe.isErroneous) { val coreMsg = pre1+" "+info1.sym.fullLocationString+" of type "+info1.tpe+"\n "+ pre2+" "+info2.sym.fullLocationString+" of type "+info2.tpe+"\n "+ trailer val errMsg = if (isView) { val found = pt.typeArgs(0) val req = pt.typeArgs(1) def defaultExplanation = "Note that implicit conversions are not applicable because they are ambiguous:\n "+ coreMsg+"are possible conversion functions from "+ found+" to "+req def explanation = { val sym = found.typeSymbol // Explain some common situations a bit more clearly. if (AnyRefClass.tpe <:< req) { if (sym == AnyClass || sym == UnitClass) { "Note: " + sym.name + " is not implicitly converted to AnyRef. You can safely\n" + "pattern match `x: AnyRef` or cast `x.asInstanceOf[AnyRef]` to do so." } else boxedClass get sym match { case Some(boxed) => "Note: an implicit exists from " + sym.fullName + " => " + boxed.fullName + ", but\n" + "methods inherited from Object are rendered ambiguous. This is to avoid\n" + "a blanket implicit which would convert any " + sym.fullName + " to any AnyRef.\n" + "You may wish to use a type ascription: `x: " + boxed.fullName + "`." case _ => defaultExplanation } } else defaultExplanation } typeErrorMsg(found, req, infer.isPossiblyMissingArgs(found, req)) + "\n" + explanation } else { "ambiguous implicit values:\n "+coreMsg + "match expected type "+pt } context.issueAmbiguousError(AmbiguousTypeError(tree, tree.pos, errMsg)) } } def DivergingImplicitExpansionError(tree: Tree, pt: Type, sym: Symbol)(implicit context0: Context) = issueDivergentImplicitsError(tree, "diverging implicit expansion for type "+pt+"\nstarting with "+ sym.fullLocationString) } object NamesDefaultsErrorsGen { import typer.infer.setError def NameClashError(sym: Symbol, arg: Tree)(implicit context: Context) = { setError(arg) // to distinguish it from ambiguous reference error 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) issueSymbolTypeError(sym, errMsg) } def AmbiguousReferenceInNamesDefaultError(arg: Tree, name: Name)(implicit context: Context) = { if (!arg.isErroneous) { // check if name clash wasn't reported already issueNormalTypeError(arg, "reference to "+ name +" is ambiguous; it is both a method parameter "+ "and a variable in scope.") setError(arg) } else arg } def UnknownParameterNameNamesDefaultError(arg: Tree, name: Name)(implicit context: Context) = { issueNormalTypeError(arg, "unknown parameter name: " + name) setError(arg) } def DoubleParamNamesDefaultError(arg: Tree, name: Name)(implicit context: Context) = { issueNormalTypeError(arg, "parameter specified twice: "+ name) setError(arg) } def PositionalAfterNamedNamesDefaultError(arg: Tree)(implicit context: Context) = { issueNormalTypeError(arg, "positional after named argument.") setError(arg) } } }