Skip to content

Commit af93c7a

Browse files
committed
Merge pull request scala#5209 from adriaanm/trait-no-native-meth
Prohibit @Native method in trait
2 parents ae03df9 + 5667ff4 commit af93c7a

File tree

4 files changed

+32
-13
lines changed

4 files changed

+32
-13
lines changed

src/compiler/scala/tools/nsc/typechecker/RefChecks.scala

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,24 +1659,32 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
16591659
// inside annotations.
16601660
applyRefchecksToAnnotations(tree)
16611661
var result: Tree = tree match {
1662-
case DefDef(_, _, _, _, _, EmptyTree) if sym hasAnnotation NativeAttr =>
1663-
sym resetFlag DEFERRED
1664-
transform(deriveDefDef(tree)(_ => typed(gen.mkSysErrorCall("native method stub"))))
1665-
1666-
case ValDef(_, _, _, _) | DefDef(_, _, _, _, _, _) =>
1662+
case vod: ValOrDefDef =>
16671663
checkDeprecatedOvers(tree)
1668-
checkInfiniteLoop(tree.asInstanceOf[ValOrDefDef])
1664+
checkInfiniteLoop(vod)
16691665
if (settings.warnNullaryUnit)
16701666
checkNullaryMethodReturnType(sym)
16711667
if (settings.warnInaccessible) {
16721668
if (!sym.isConstructor && !sym.isEffectivelyFinalOrNotOverridden && !sym.isSynthetic)
16731669
checkAccessibilityOfReferencedTypes(tree)
16741670
}
1675-
tree match {
1676-
case dd: DefDef => checkByNameRightAssociativeDef(dd)
1677-
case _ =>
1671+
vod match {
1672+
case dd: DefDef =>
1673+
checkByNameRightAssociativeDef(dd)
1674+
1675+
if (sym hasAnnotation NativeAttr) {
1676+
if (sym.owner.isTrait) {
1677+
reporter.error(tree.pos, "A trait cannot define a native method.")
1678+
tree
1679+
} else if (dd.rhs == EmptyTree) {
1680+
// pretend it had a stub implementation
1681+
sym resetFlag DEFERRED
1682+
deriveDefDef(dd)(_ => typed(gen.mkSysErrorCall("native method stub")))
1683+
} else tree
1684+
} else tree
1685+
1686+
case _ => tree
16781687
}
1679-
tree
16801688

16811689
case Template(parents, self, body) =>
16821690
localTyper = localTyper.atOwner(tree, currentOwner)

src/library/scala/native.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ package scala
1616
* @native def f(x: Int, y: List[Long]): String = ...
1717
* }}}
1818
*
19-
* Method body is not generated if method is marked with `@native`,
20-
* but it is type checked when present.
19+
* A `@native` method is compiled to the platform's native method,
20+
* while discarding the method's body (if any). The body will be type checked if present.
2121
*
22-
* @since 2.6 */
22+
* A method marked @native must be a member of a class, not a trait (since 2.12).
23+
*
24+
* @since 2.6
25+
*/
2326
class native extends scala.annotation.StaticAnnotation {}

test/files/neg/trait-no-native.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
trait-no-native.scala:3: error: A trait cannot define a native method.
2+
@native def foo = ???
3+
^
4+
one error found

test/files/neg/trait-no-native.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
trait T {
2+
// should not compile, because it would result in a VerifyError
3+
@native def foo = ???
4+
}

0 commit comments

Comments
 (0)