-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Only allow sound inline parameters in overrides #8785
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
89672bf
9b78ef9
b5a968e
e9c1e7e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -451,7 +451,8 @@ object Checking { | |
|| sym.is(TermParam) && !sym.owner.isInlineMethod | ||
)) | ||
fail(ParamsNoInline(sym.owner)) | ||
|
||
if sym.isInlineMethod && !sym.is(Deferred) && sym.allOverriddenSymbols.nonEmpty then | ||
checkInlineOverrideParameters(sym) | ||
if (sym.isOneOf(GivenOrImplicit)) { | ||
if (sym.owner.is(Package)) | ||
fail(TopLevelCantBeImplicit(sym)) | ||
|
@@ -646,6 +647,18 @@ object Checking { | |
val enumCls = enumCase.owner.linkedClass | ||
if !cls.info.parents.exists(_.typeSymbol == enumCls) then | ||
ctx.error(i"enum case does not extend its enum $enumCls", enumCase.sourcePos) | ||
|
||
/** Check the inline override methods only use inline parameteres if they override an inline parameter. */ | ||
def checkInlineOverrideParameters(sym: Symbol)(using Context): Unit = | ||
val params = sym.paramSymss.flatten | ||
if params.exists(_.is(Inline)) then | ||
for | ||
sym2 <- sym.allOverriddenSymbols | ||
(p1, p2) <- params.lazyZip(sym2.paramSymss.flatten) | ||
if p1.is(Inline) && !p2.is(Inline) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about the reverse? Is it ok for a non-inline parameter to override an inline parameter? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's debatable whether it's OK or desirable. But at least it is sound, because, as @nicolasstucki observed, you can always emulate the semantics of a non- However, personally I think we should not allow it either. In Scala, typically overrides must have exactly the same parameters. I think we should also apply that to the quality of being There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, actually I think they're unsound. If we have a method with two parameters, the first one being either def foo(inline x: Int, y: Int): Int = {
val x2 = x
x2 * x2 + y
}
foo({ println(1); 3 }, { println(2); 4 })
// prints 2
// prints 1
// returns 13 but def foo(x: Int, y: Int): Int = {
x * x + y
}
foo({ println(1); 3 }, { println(2); 4 })
// prints 1
// prints 2
// returns 13 So overriding an inline parameter with a by-value parameter is unsound. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I already added a commit disallowing them. |
||
do | ||
ctx.error("Cannot override non-inline parameter with and inline parameter", p1.sourcePos) | ||
nicolasstucki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
} | ||
|
||
trait Checking { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
|
||
|
||
abstract class Logger { | ||
def log1(msg: String): Unit | ||
inline def log2(msg: String): Unit | ||
inline def log3(inline msg: String): Unit | ||
} | ||
|
||
class Logger1 extends Logger { | ||
inline def log1(msg: String): Unit = () | ||
inline def log2(msg: String): Unit = () | ||
inline def log3(msg: String): Unit = () | ||
} | ||
|
||
class Logger2 extends Logger { | ||
inline def log1(inline msg: String): Unit = () // error: Cannot override non-inline parameter with and inline parameter | ||
inline def log2(inline msg: String): Unit = () // error: Cannot override non-inline parameter with and inline parameter | ||
nicolasstucki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
inline def log3(inline msg: String): Unit = () | ||
} | ||
|
||
trait A { | ||
inline def f(inline a: Int): Int | ||
} | ||
|
||
trait B { | ||
def f(a: Int): Int | ||
} | ||
|
||
class C extends A, B { | ||
inline def f(inline a: Int): Int = 3 // error: Cannot override non-inline parameter with and inline parameter | ||
} | ||
|
||
class D extends B, A { | ||
inline def f(inline a: Int): Int = 3 // error: Cannot override non-inline parameter with and inline parameter | ||
} |
Uh oh!
There was an error while loading. Please reload this page.