Skip to content

Commit

Permalink
Warn when calling synchronized on AnyVal
Browse files Browse the repository at this point in the history
Co-Authored-By: James You <[email protected]>
Co-Authored-By: diogocanut <[email protected]>
  • Loading branch information
3 people committed Jun 20, 2023
1 parent 5da12b7 commit 78a543e
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe
case AmbiguousExtensionMethodID // errorNumber 180
case UnqualifiedCallToAnyRefMethodID // errorNumber: 181
case NotConstantID // errorNumber: 182
case SynchronizedCallOnBoxedClassID // errorNumber: 183

def errorNumber = ordinal - 1

Expand Down
9 changes: 9 additions & 0 deletions compiler/src/dotty/tools/dotc/reporting/messages.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2298,6 +2298,15 @@ class UnqualifiedCallToAnyRefMethod(stat: untpd.Tree, method: Symbol)(using Cont
|you intended."""
}

class SynchronizedCallOnBoxedClass(stat: untpd.Tree)(using Context)
extends Message(SynchronizedCallOnBoxedClassID) {
def kind = MessageKind.PotentialIssue
def msg(using Context) = i"Suspicious ${hl("synchronized")} call on boxed class"
def explain(using Context) =
i"""|You called the ${hl("synchronized")} method on a boxed primitive. This might not be what
|you intended."""
}

class TraitCompanionWithMutableStatic()(using Context)
extends SyntaxMsg(TraitCompanionWithMutableStaticID) {
def msg(using Context) = i"Companion of traits cannot define mutable @static fields"
Expand Down
4 changes: 4 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,10 @@ class RefChecks extends MiniPhase { thisPhase =>
checkAnyRefMethodCall(tree)
tree

override def transformSelect(tree: tpd.Select)(using Context): tpd.Tree =
if defn.ScalaBoxedClasses().contains(tree.qualifier.tpe.typeSymbol) && tree.name == nme.synchronized_ then
report.warning(SynchronizedCallOnBoxedClass(tree), tree.srcPos)
tree
}

/* todo: rewrite and re-enable
Expand Down
30 changes: 30 additions & 0 deletions tests/neg/17284.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-- [E183] Potential Issue Error: tests/neg/17284.scala:4:6 -------------------------------------------------------------
4 | 451.synchronized {} // error
| ^^^^^^^^^^^^^^^^
| Suspicious synchronized call on boxed class
|---------------------------------------------------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| You called the synchronized method on a boxed primitive. This might not be what
| you intended.
---------------------------------------------------------------------------------------------------------------------
-- [E183] Potential Issue Error: tests/neg/17284.scala:8:4 -------------------------------------------------------------
8 | x.synchronized {} // error
| ^^^^^^^^^^^^^^
| Suspicious synchronized call on boxed class
|---------------------------------------------------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| You called the synchronized method on a boxed primitive. This might not be what
| you intended.
---------------------------------------------------------------------------------------------------------------------
-- [E183] Potential Issue Error: tests/neg/17284.scala:11:7 ------------------------------------------------------------
11 | true.synchronized {} // error
| ^^^^^^^^^^^^^^^^^
| Suspicious synchronized call on boxed class
|--------------------------------------------------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| You called the synchronized method on a boxed primitive. This might not be what
| you intended.
--------------------------------------------------------------------------------------------------------------------
14 changes: 14 additions & 0 deletions tests/neg/17284.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// scalac: -Werror -explain

def test =
451.synchronized {} // error

def test2 =
val x: Integer = 451
x.synchronized {} // error

def test3 =
true.synchronized {} // error

def test4 =
true.hashCode() // success

0 comments on commit 78a543e

Please sign in to comment.