Skip to content

Commit 954fdcd

Browse files
committed
Check that overrides don't change the @unbox status of their parameters
1 parent a2876f7 commit 954fdcd

File tree

4 files changed

+55
-1
lines changed

4 files changed

+55
-1
lines changed

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import CaptureSet.{withCaptureSetsExplained, IdempotentCaptRefMap, CompareResult
2222
import CCState.*
2323
import StdNames.nme
2424
import NameKinds.{DefaultGetterName, WildcardParamName, UniqueNameKind}
25-
import reporting.{trace, Message}
25+
import reporting.{trace, Message, OverrideError}
2626

2727
/** The capture checker */
2828
object CheckCaptures:
@@ -1271,6 +1271,21 @@ class CheckCaptures extends Recheck, SymTransformer:
12711271
!setup.isPreCC(overriding) && !setup.isPreCC(overridden)
12721272

12731273
override def checkInheritedTraitParameters: Boolean = false
1274+
1275+
/** Check that overrides don't change the @unbox status of their parameters */
1276+
override def additionalChecks(member: Symbol, other: Symbol)(using Context): Unit =
1277+
for
1278+
(params1, params2) <- member.rawParamss.lazyZip(other.rawParamss)
1279+
(param1, param2) <- params1.lazyZip(params2)
1280+
do
1281+
if param1.hasAnnotation(defn.UnboxAnnot) != param2.hasAnnotation(defn.UnboxAnnot) then
1282+
report.error(
1283+
OverrideError(
1284+
i"has a parameter ${param1.name} with different @unbox status than the corresponding parameter in the overridden definition",
1285+
self, member, other, self.memberInfo(member), self.memberInfo(other)
1286+
),
1287+
if member.owner == clazz then member.srcPos else clazz.srcPos
1288+
)
12741289
end OverridingPairsCheckerCC
12751290

12761291
def traverse(t: Tree)(using Context) =

compiler/src/dotty/tools/dotc/typer/RefChecks.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,12 +250,15 @@ object RefChecks {
250250
*/
251251
def needsCheck(overriding: Symbol, overridden: Symbol)(using Context): Boolean = true
252252

253+
protected def additionalChecks(overriding: Symbol, overridden: Symbol)(using Context): Unit = ()
254+
253255
private val subtypeChecker: (Type, Type) => Context ?=> Boolean = this.checkSubType
254256

255257
def checkAll(checkOverride: ((Type, Type) => Context ?=> Boolean, Symbol, Symbol) => Unit) =
256258
while hasNext do
257259
if needsCheck(overriding, overridden) then
258260
checkOverride(subtypeChecker, overriding, overridden)
261+
additionalChecks(overriding, overridden)
259262
next()
260263

261264
// The OverridingPairs cursor does assume that concrete overrides abstract
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
-- [E164] Declaration Error: tests/neg-custom-args/captures/unbox-overrides.scala:8:6 ----------------------------------
2+
8 | def foo(x: C): C // error
3+
| ^
4+
|error overriding method foo in trait A of type (x: C): C;
5+
| method foo of type (x: C): C has a parameter x with different @unbox status than the corresponding parameter in the overridden definition
6+
|
7+
| longer explanation available when compiling with `-explain`
8+
-- [E164] Declaration Error: tests/neg-custom-args/captures/unbox-overrides.scala:9:6 ----------------------------------
9+
9 | def bar(@unbox x: C): C // error
10+
| ^
11+
|error overriding method bar in trait A of type (x: C): C;
12+
| method bar of type (x: C): C has a parameter x with different @unbox status than the corresponding parameter in the overridden definition
13+
|
14+
| longer explanation available when compiling with `-explain`
15+
-- [E164] Declaration Error: tests/neg-custom-args/captures/unbox-overrides.scala:15:15 --------------------------------
16+
15 |abstract class C extends A[C], B2 // error
17+
| ^
18+
|error overriding method foo in trait A of type (x: C): C;
19+
| method foo in trait B2 of type (x: C): C has a parameter x with different @unbox status than the corresponding parameter in the overridden definition
20+
|
21+
| longer explanation available when compiling with `-explain`
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import caps.unbox
2+
3+
trait A[X]:
4+
def foo(@unbox x: X): X
5+
def bar(x: X): X
6+
7+
trait B extends A[C]:
8+
def foo(x: C): C // error
9+
def bar(@unbox x: C): C // error
10+
11+
trait B2:
12+
def foo(x: C): C
13+
def bar(@unbox x: C): C
14+
15+
abstract class C extends A[C], B2 // error

0 commit comments

Comments
 (0)