Skip to content

Commit 051039e

Browse files
committed
Make concrete inline methods effectively final
1 parent e6f5df6 commit 051039e

File tree

5 files changed

+14
-10
lines changed

5 files changed

+14
-10
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

+3-1
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,9 @@ object SymDenotations {
10941094

10951095
/** A symbol is effectively final if it cannot be overridden in a subclass */
10961096
final def isEffectivelyFinal(implicit ctx: Context): Boolean =
1097-
isOneOf(EffectivelyFinalFlags) || !owner.isExtensibleClass
1097+
isOneOf(EffectivelyFinalFlags)
1098+
|| is(Inline, butNot = Deferred)
1099+
|| !owner.isExtensibleClass
10981100

10991101
/** A class is effectively sealed if has the `final` or `sealed` modifier, or it
11001102
* is defined in Scala 3 and is neither abstract nor open.

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ object RefChecks {
157157
* 1.8.3 M is of type ()S, O is of type []T and S <: T, or
158158
* 1.9.1 If M is erased, O is erased. If O is erased, M is erased or inline.
159159
* 1.9.2 If M or O are extension methods, they must both be extension methods.
160-
* 1.10 If O is inline, M must be inline
160+
* 1.10 If O is inline (and deferred, otherwise O would be final), M must be inline
161161
* 1.11. If O is a Scala-2 macro, M must be a Scala-2 macro.
162162
* 2. Check that only abstract classes have deferred members
163163
* 3. Check that concrete classes do not have deferred definitions
@@ -398,7 +398,7 @@ object RefChecks {
398398
else if (other.isAllOf(ExtensionMethod) && !member.isAllOf(ExtensionMethod)) // (1.9.2)
399399
overrideError("is a normal method, cannot override an extension method")
400400
else if other.isInlineMethod && !member.isInlineMethod then // (1.10)
401-
overrideError("is not inline, cannot override an inline method")
401+
overrideError("is not inline, cannot implement an inline method")
402402
else if (other.isScala2Macro && !member.isScala2Macro) // (1.11)
403403
overrideError("cannot be used here - only Scala-2 macros can override Scala-2 macros")
404404
else if (!compatibleTypes(memberTp(self), otherTp(self)) &&

docs/docs/reference/metaprogramming/inline.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ funkyAssertEquals(computeActual(), computeExpected(), computeDelta())
144144
```
145145
### Rules for Overriding
146146

147-
Inline methods can override other methods and can themselves be overridden by other inline methods. The rules are as follows:
147+
Inline methods can override other methods. Abstract inline methods can themselves be implemented by other inline methods. The rules are as follows:
148148

149149
1. If an inline method `f` implements or overrides another, non-inline method, the inline method can also be invoked at runtime. For instance, consider the scenario:
150150
```scala
@@ -167,7 +167,8 @@ assert(a.g() == 33)
167167
```
168168
The inlined invocations and the dynamically dispatched invocations give the same results.
169169

170-
2. Inline methods can override or implement normal methods, as the previous example shows. Inline methods can be overridden only by other inline methods.
170+
2. Inline methods can override or implement normal methods, as the previous example shows. Concrete inline methods are effectively final; they cannot be
171+
overriden.
171172

172173
3. Inline methods can also be abstract. An abstract inline method can be implemented only by other inline methods. It cannot be invoked directly:
173174
```scala

tests/neg-macros/quote-MacroOverride.scala

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ object Test {
33
abstract class A {
44
def f(): Unit
55
inline def g(): Unit = ()
6+
inline def h(): Unit
67
}
78

89
object B extends A {
910
override inline def f() = ()
10-
override def g() = () // error: is not inline, cannot override an inline method
11+
override def g() = () // error: cannot override final member
12+
def h() = () // error: is not inline, cannot implement an inline method
1113
}
1214

1315
}

tests/run/quote-MacroOverride.scala

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
object Test {
22

33
abstract class A {
4-
inline def f1(): String = "A.f1"
5-
inline def f2(): String = "A.f2"
4+
inline def f1(): String
5+
def f2(): String
66
def f3(): String = "A.f3"
77
}
88

@@ -14,8 +14,7 @@ object Test {
1414

1515
def main(args: Array[String]): Unit = {
1616
val a: A = B
17-
assert(a.f1() == "A.f1")
18-
assert(a.f2() == "A.f2")
17+
assert(a.f2() == "B.f2")
1918
assert(a.f3() == "B.f3")
2019

2120
val b: B.type = B

0 commit comments

Comments
 (0)