summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2014-12-11 12:57:32 +0100
committerLukas Rytz <lukas.rytz@gmail.com>2014-12-12 08:18:30 +0100
commita4a892fb0196f2f66d86f9cfa508deabe7d2aaae (patch)
treef86405ae87fe1ebac37f92bef3a01d94d8075c91 /src/compiler/scala/tools
parent36b1014ac63205a38e73ae18a05ac6f956c3410f (diff)
downloadscala-a4a892fb0196f2f66d86f9cfa508deabe7d2aaae.tar.gz
scala-a4a892fb0196f2f66d86f9cfa508deabe7d2aaae.tar.bz2
scala-a4a892fb0196f2f66d86f9cfa508deabe7d2aaae.zip
SI-8841 report named arg / assignment ambiguity also in silent mode.
For local definitions (eg. in a block that is an argument of a method call), the type completer may have a silent context. A CyclicReference is then not thrown but transformed into a NormalTypeError. When deciding if 'x = e' is an assignment or a named arg, we need to report cyclic references, but not other type errors. In the above case, the cyclic reference was not reported. Also makes sure that warnings are printed after typing argument expressions.
Diffstat (limited to 'src/compiler/scala/tools')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala17
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala18
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala19
3 files changed, 43 insertions, 11 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 866ca37303..6868f06606 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -45,6 +45,14 @@ trait ContextErrors {
case class NormalTypeError(underlyingTree: Tree, errMsg: String)
extends TreeTypeError
+ /**
+ * Marks a TypeError that was constructed from a CyclicReference (under silent).
+ * This is used for named arguments, where we need to know if an assignment expression
+ * failed with a cyclic reference or some other type error.
+ */
+ class NormalTypeErrorFromCyclicReference(underlyingTree: Tree, errMsg: String)
+ extends NormalTypeError(underlyingTree, errMsg)
+
case class AccessTypeError(underlyingTree: Tree, errMsg: String)
extends TreeTypeError
@@ -1087,8 +1095,9 @@ trait ContextErrors {
// hence we (together with reportTypeError in TypeDiagnostics) make sure that this CyclicReference
// evades all the handlers on its way and successfully reaches `isCyclicOrErroneous` in Implicits
throw ex
- case CyclicReference(sym, info: TypeCompleter) =>
- issueNormalTypeError(tree, typer.cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage())
+ case c @ CyclicReference(sym, info: TypeCompleter) =>
+ val error = new NormalTypeErrorFromCyclicReference(tree, typer.cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage)
+ issueTypeError(error)
case _ =>
contextNamerErrorGen.issue(TypeErrorWithUnderlyingTree(tree, ex))
}
@@ -1275,8 +1284,8 @@ trait ContextErrors {
}
def WarnAfterNonSilentRecursiveInference(param: Symbol, arg: Tree)(implicit context: Context) = {
- val note = "type-checking the invocation of "+ param.owner +" checks if the named argument expression '"+ param.name + " = ...' is a valid assignment\n"+
- "in the current scope. The resulting type inference error (see above) can be fixed by providing an explicit type in the local definition for "+ param.name +"."
+ val note = "failed to determine if '"+ param.name + " = ...' is a named argument or an assignment expression.\n"+
+ "an explicit type is required for the definition mentioned in the error message above."
context.warning(arg.pos, note)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index b6387fd56b..4f943fcd28 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -521,8 +521,22 @@ trait NamesDefaults { self: Analyzer =>
WarnAfterNonSilentRecursiveInference(param, arg)(context)
res
} match {
- case SilentResultValue(t) => !t.isErroneous // #4041
- case _ => false
+ case SilentResultValue(t) =>
+ !t.isErroneous // #4041
+ case SilentTypeError(e: NormalTypeErrorFromCyclicReference) =>
+ // If we end up here, the CyclicReference was reported in a silent context. This can
+ // happen for local definitions, when the completer for a definition is created during
+ // type checking in silent mode. ContextErrors.TypeSigError catches that cyclic reference
+ // and transforms it into a NormalTypeErrorFromCyclicReference.
+ // The cycle needs to be reported, because the program cannot be typed: we don't know
+ // if we have an assignment or a named arg.
+ context.issue(e)
+ // 'err = true' is required because we're in a silent context
+ WarnAfterNonSilentRecursiveInference(param, arg)(context)
+ false
+ case _ =>
+ // We got a type error, so it cannot be an assignment (it doesn't type check as one).
+ false
}
catch {
// `silent` only catches and returns TypeErrors which are not
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index aaa75b5ee1..22cf8c6808 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -76,7 +76,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case s : SilentTypeError => f(s.reportableErrors)
}
}
- class SilentTypeError private(val errors: List[AbsTypeError]) extends SilentResult[Nothing] {
+ class SilentTypeError private(val errors: List[AbsTypeError], val warnings: List[(Position, String)]) extends SilentResult[Nothing] {
override def isEmpty = true
def err: AbsTypeError = errors.head
def reportableErrors = errors match {
@@ -87,10 +87,14 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
}
object SilentTypeError {
- def apply(errors: AbsTypeError*): SilentTypeError = new SilentTypeError(errors.toList)
+ def apply(errors: AbsTypeError*): SilentTypeError = apply(errors.toList, Nil)
+ def apply(errors: List[AbsTypeError], warnings: List[(Position, String)]): SilentTypeError = new SilentTypeError(errors, warnings)
+ // todo: this extracts only one error, should be a separate extractor.
def unapply(error: SilentTypeError): Option[AbsTypeError] = error.errors.headOption
}
+ // todo: should include reporter warnings in SilentResultValue.
+ // e.g. tryTypedApply could print warnings on arguments when the typing succeeds.
case class SilentResultValue[+T](value: T) extends SilentResult[T] { override def isEmpty = false }
def newTyper(context: Context): Typer = new NormalTyper(context)
@@ -661,7 +665,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
@inline def wrapResult(reporter: ContextReporter, result: T) =
if (reporter.hasErrors) {
stopStats()
- SilentTypeError(reporter.errors: _*)
+ SilentTypeError(reporter.errors.toList, reporter.warnings.toList)
} else SilentResultValue(result)
try {
@@ -4401,7 +4405,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def tryTypedApply(fun: Tree, args: List[Tree]): Tree = {
val start = if (Statistics.canEnable) Statistics.startTimer(failedApplyNanos) else null
- def onError(typeErrors: Seq[AbsTypeError]): Tree = {
+ def onError(typeErrors: Seq[AbsTypeError], warnings: Seq[(Position, String)]): Tree = {
if (Statistics.canEnable) Statistics.stopTimer(failedApplyNanos, start)
// If the problem is with raw types, copnvert to existentials and try again.
@@ -4449,10 +4453,14 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
}
typeErrors foreach context.issue
+ warnings foreach { case (p, m) => context.warning(p, m) }
setError(treeCopy.Apply(tree, fun, args))
}
- silent(_.doTypedApply(tree, fun, args, mode, pt)) orElse onError
+ silent(_.doTypedApply(tree, fun, args, mode, pt)) match {
+ case SilentResultValue(value) => value
+ case e: SilentTypeError => onError(e.errors, e.warnings)
+ }
}
def normalTypedApply(tree: Tree, fun: Tree, args: List[Tree]) = {
@@ -4503,6 +4511,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
case err: SilentTypeError =>
onError({
err.reportableErrors foreach context.issue
+ err.warnings foreach { case (p, m) => context.warning(p, m) }
args foreach (arg => typed(arg, mode, ErrorType))
setError(tree)
})