From 61c6c62512e4c72074d5ab97d59b9e1ffcbb3795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Marks?= Date: Thu, 23 Nov 2023 20:18:02 +0100 Subject: [PATCH] Warn when calling synchronized on AnyVal Co-Authored-By: James You Co-Authored-By: diogocanut Co-Authored-By: Nicolas Stucki <3648029+nicolasstucki@users.noreply.github.com> [Cherry-picked 59825924183d457f3a7a16570bac6674b504efb9][modified] --- .../tools/dotc/reporting/ErrorMessageID.scala | 1 + .../dotty/tools/dotc/reporting/messages.scala | 9 ++++++ .../dotty/tools/dotc/typer/RefChecks.scala | 4 +++ tests/neg/17284.check | 30 +++++++++++++++++++ tests/neg/17284.scala | 14 +++++++++ tests/neg/i17266.check | 10 +++++++ tests/neg/i17266.scala | 2 +- 7 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 tests/neg/17284.check create mode 100644 tests/neg/17284.scala diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index ad56f29287fc..53cef15d3c05 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -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: 187 def errorNumber = ordinal - 1 diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index a536e10fb959..ff86bdc7b420 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -2338,6 +2338,15 @@ class UnqualifiedCallToAnyRefMethod(stat: untpd.Tree, method: Symbol)(using Cont |you intended.""" } +class SynchronizedCallOnBoxedClass(stat: tpd.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" diff --git a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala index 025eae3606af..9ee7a672ffba 100644 --- a/compiler/src/dotty/tools/dotc/typer/RefChecks.scala +++ b/compiler/src/dotty/tools/dotc/typer/RefChecks.scala @@ -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 diff --git a/tests/neg/17284.check b/tests/neg/17284.check new file mode 100644 index 000000000000..fa248c598311 --- /dev/null +++ b/tests/neg/17284.check @@ -0,0 +1,30 @@ +-- [E187] 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. + --------------------------------------------------------------------------------------------------------------------- +-- [E187] 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. + --------------------------------------------------------------------------------------------------------------------- +-- [E187] 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. + -------------------------------------------------------------------------------------------------------------------- diff --git a/tests/neg/17284.scala b/tests/neg/17284.scala new file mode 100644 index 000000000000..177926de7287 --- /dev/null +++ b/tests/neg/17284.scala @@ -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 diff --git a/tests/neg/i17266.check b/tests/neg/i17266.check index 7e07e3d43de4..1a84d1bf5e89 100644 --- a/tests/neg/i17266.check +++ b/tests/neg/i17266.check @@ -20,6 +20,16 @@ | resolved to calls on Predef or on imported methods. This might not be what | you intended. -------------------------------------------------------------------------------------------------------------------- +-- [E187] Potential Issue Error: tests/neg/i17266.scala:22:4 ----------------------------------------------------------- +22 | 1.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. + -------------------------------------------------------------------------------------------------------------------- -- [E181] Potential Issue Error: tests/neg/i17266.scala:108:2 ---------------------------------------------------------- 108 | wait() // error | ^^^^ diff --git a/tests/neg/i17266.scala b/tests/neg/i17266.scala index 5b74ea76810b..166ed2239875 100644 --- a/tests/neg/i17266.scala +++ b/tests/neg/i17266.scala @@ -19,7 +19,7 @@ def test3 = } def test4 = - 1.synchronized { // not an error (should be?) + 1.synchronized { // error println("hello") }