summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala72
1 files changed, 39 insertions, 33 deletions
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)
}