Skip to content

Commit

Permalink
SI-6923 Context now buffers warnings as well as errors
Browse files Browse the repository at this point in the history
Code that was silently typed would not report warnings, even if it
returned a successful result.

This appeared in the following code which didn't show warnings even
with -Ywarn-adapted-args:

    def foo(a: Any) = a; foo(1, 2)

While the following would show the expected warning:

    def foo[A](a: Any) = a; foo(1, 2)
  • Loading branch information
puffnfresh committed Jan 7, 2013
1 parent 766bb97 commit 66fe64f
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 3 deletions.
9 changes: 9 additions & 0 deletions src/compiler/scala/tools/nsc/typechecker/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ trait Contexts { self: Analyzer =>
def typingIndent = " " * typingIndentLevel

var buffer: Set[AbsTypeError] = _
var warningsBuffer: Set[(Position, String)] = _

def enclClassOrMethod: Context =
if ((owner eq NoSymbol) || (owner.isClass) || (owner.isMethod)) this
Expand All @@ -165,6 +166,7 @@ trait Contexts { self: Analyzer =>

def errBuffer = buffer
def hasErrors = buffer.nonEmpty
def hasWarnings = warningsBuffer.nonEmpty

def state: Int = mode
def restoreState(state0: Int) = mode = state0
Expand Down Expand Up @@ -193,6 +195,11 @@ trait Contexts { self: Analyzer =>
buffer.clear()
current
}
def flushAndReturnWarningsBuffer(): Set[(Position, String)] = {
val current = warningsBuffer.clone()
warningsBuffer.clear()
current
}

def logError(err: AbsTypeError) = buffer += err

Expand Down Expand Up @@ -282,6 +289,7 @@ trait Contexts { self: Analyzer =>
c.retyping = this.retyping
c.openImplicits = this.openImplicits
c.buffer = if (this.buffer == null) LinkedHashSet[AbsTypeError]() else this.buffer // need to initialize
c.warningsBuffer = if (this.warningsBuffer == null) LinkedHashSet[(Position, String)]() else this.warningsBuffer
registerContext(c.asInstanceOf[analyzer.Context])
debuglog("[context] ++ " + c.unit + " / " + tree.summaryString)
c
Expand Down Expand Up @@ -406,6 +414,7 @@ trait Contexts { self: Analyzer =>
def warning(pos: Position, msg: String): Unit = warning(pos, msg, false)
def warning(pos: Position, msg: String, force: Boolean) {
if (reportErrors || force) unit.warning(pos, msg)
else if (bufferErrors) warningsBuffer += ((pos, msg))
}

def isLocal(): Boolean = tree match {
Expand Down
10 changes: 9 additions & 1 deletion src/compiler/scala/tools/nsc/typechecker/Typers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,15 @@ trait Typers extends Modes with Adaptations with Tags {
if (context1.hasErrors) {
stopStats()
SilentTypeError(context1.errBuffer.head)
} else SilentResultValue(result)
} else {
// If we have a successful result, emit any warnings it created.
if (context1.hasWarnings) {
context1.flushAndReturnWarningsBuffer() foreach {
case (pos, msg) => unit.warning(pos, msg)
}
}
SilentResultValue(result)
}
} else {
assert(context.bufferErrors || isPastTyper, "silent mode is not available past typer")
withSavedContext(context){
Expand Down
10 changes: 9 additions & 1 deletion test/files/neg/names-defaults-neg.check
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,17 @@ names-defaults-neg.scala:144: error: variable definition needs type because 'x'
names-defaults-neg.scala:147: error: variable definition needs type because 'x' is used as a named argument in its body.
object t6 { var x = t.f(x = 1) }
^
names-defaults-neg.scala:147: warning: type-checking the invocation of method f checks if the named argument expression 'x = ...' is a valid assignment
in the current scope. The resulting type inference error (see above) can be fixed by providing an explicit type in the local definition for x.
object t6 { var x = t.f(x = 1) }
^
names-defaults-neg.scala:150: error: variable definition needs type because 'x' is used as a named argument in its body.
class t9 { var x = t.f(x = 1) }
^
names-defaults-neg.scala:150: warning: type-checking the invocation of method f checks if the named argument expression 'x = ...' is a valid assignment
in the current scope. The resulting type inference error (see above) can be fixed by providing an explicit type in the local definition for x.
class t9 { var x = t.f(x = 1) }
^
names-defaults-neg.scala:164: error: variable definition needs type because 'x' is used as a named argument in its body.
def u3 { var x = u.f(x = 1) }
^
Expand All @@ -156,5 +164,5 @@ in the current scope. The resulting type inference error (see above) can be fixe
names-defaults-neg.scala:180: error: reference to x is ambiguous; it is both a method parameter and a variable in scope.
class u18 { var x: Int = u.f(x = 1) }
^
two warnings found
four warnings found
41 errors found
8 changes: 7 additions & 1 deletion test/files/neg/t4851.check
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,10 @@ S.scala:10: error: Adapting argument list by inserting (): this is unlikely to b
after adaptation: new J2((): Unit)
val z2 = new J2()
^
7 errors found
S.scala:14: error: Adapting argument list by creating a 3-tuple: this may not be what you want.
signature: Test.anyId(a: Any): Any
given arguments: 1, 2, 3
after adaptation: Test.anyId((1, 2, 3): (Int, Int, Int))
val w1 = anyId(1, 2 ,3)
^
8 errors found
5 changes: 5 additions & 0 deletions test/files/neg/t4851/S.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ object Test {
val z2 = new J2()
val z3 = new J2(())

def anyId(a: Any) = a
val w1 = anyId(1, 2 ,3)

def main(args: Array[String]): Unit = {
println(x1)
println(x2)
Expand All @@ -19,5 +22,7 @@ object Test {
println(z1)
println(z2)
println(z3)

println(w1)
}
}

0 comments on commit 66fe64f

Please sign in to comment.