Skip to content

Commit

Permalink
Check that overrides don't change the @unbox status of their parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
odersky committed Jul 12, 2024
1 parent a2876f7 commit 954fdcd
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 1 deletion.
17 changes: 16 additions & 1 deletion compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import CaptureSet.{withCaptureSetsExplained, IdempotentCaptRefMap, CompareResult
import CCState.*
import StdNames.nme
import NameKinds.{DefaultGetterName, WildcardParamName, UniqueNameKind}
import reporting.{trace, Message}
import reporting.{trace, Message, OverrideError}

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

override def checkInheritedTraitParameters: Boolean = false

/** Check that overrides don't change the @unbox status of their parameters */
override def additionalChecks(member: Symbol, other: Symbol)(using Context): Unit =
for
(params1, params2) <- member.rawParamss.lazyZip(other.rawParamss)
(param1, param2) <- params1.lazyZip(params2)
do
if param1.hasAnnotation(defn.UnboxAnnot) != param2.hasAnnotation(defn.UnboxAnnot) then
report.error(
OverrideError(
i"has a parameter ${param1.name} with different @unbox status than the corresponding parameter in the overridden definition",
self, member, other, self.memberInfo(member), self.memberInfo(other)
),
if member.owner == clazz then member.srcPos else clazz.srcPos
)
end OverridingPairsCheckerCC

def traverse(t: Tree)(using Context) =
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/RefChecks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,15 @@ object RefChecks {
*/
def needsCheck(overriding: Symbol, overridden: Symbol)(using Context): Boolean = true

protected def additionalChecks(overriding: Symbol, overridden: Symbol)(using Context): Unit = ()

private val subtypeChecker: (Type, Type) => Context ?=> Boolean = this.checkSubType

def checkAll(checkOverride: ((Type, Type) => Context ?=> Boolean, Symbol, Symbol) => Unit) =
while hasNext do
if needsCheck(overriding, overridden) then
checkOverride(subtypeChecker, overriding, overridden)
additionalChecks(overriding, overridden)
next()

// The OverridingPairs cursor does assume that concrete overrides abstract
Expand Down
21 changes: 21 additions & 0 deletions tests/neg-custom-args/captures/unbox-overrides.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- [E164] Declaration Error: tests/neg-custom-args/captures/unbox-overrides.scala:8:6 ----------------------------------
8 | def foo(x: C): C // error
| ^
|error overriding method foo in trait A of type (x: C): C;
| method foo of type (x: C): C has a parameter x with different @unbox status than the corresponding parameter in the overridden definition
|
| longer explanation available when compiling with `-explain`
-- [E164] Declaration Error: tests/neg-custom-args/captures/unbox-overrides.scala:9:6 ----------------------------------
9 | def bar(@unbox x: C): C // error
| ^
|error overriding method bar in trait A of type (x: C): C;
| method bar of type (x: C): C has a parameter x with different @unbox status than the corresponding parameter in the overridden definition
|
| longer explanation available when compiling with `-explain`
-- [E164] Declaration Error: tests/neg-custom-args/captures/unbox-overrides.scala:15:15 --------------------------------
15 |abstract class C extends A[C], B2 // error
| ^
|error overriding method foo in trait A of type (x: C): C;
| 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
|
| longer explanation available when compiling with `-explain`
15 changes: 15 additions & 0 deletions tests/neg-custom-args/captures/unbox-overrides.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import caps.unbox

trait A[X]:
def foo(@unbox x: X): X
def bar(x: X): X

trait B extends A[C]:
def foo(x: C): C // error
def bar(@unbox x: C): C // error

trait B2:
def foo(x: C): C
def bar(@unbox x: C): C

abstract class C extends A[C], B2 // error

0 comments on commit 954fdcd

Please sign in to comment.