Skip to content

Commit 0920fed

Browse files
committed
Add scala.Dynamic language feature check.
1 parent b4b9b4d commit 0920fed

File tree

6 files changed

+35
-1
lines changed

6 files changed

+35
-1
lines changed

src/dotty/tools/dotc/core/StdNames.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ object StdNames {
383383
val delayedInit: N = "delayedInit"
384384
val delayedInitArg: N = "delayedInit$body"
385385
val drop: N = "drop"
386+
val dynamics: N = "dynamics"
386387
val dummyApply: N = "<dummy-apply>"
387388
val elem: N = "elem"
388389
val emptyValDef: N = "emptyValDef"

src/dotty/tools/dotc/reporting/Reporter.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,23 @@ trait Reporting { this: Context =>
6868
def featureWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
6969
reporter.report(new FeatureWarning(msg, pos))
7070

71+
def featureWarning(pos: SourcePosition, feature: String, featureDescription: String, required: Boolean): Unit = {
72+
val req = if (required) "needs to" else "should"
73+
val fqname = "dotty.language." + feature
74+
75+
val explain = {
76+
s"""|
77+
|This can be achieved by adding the import clause 'import $fqname'
78+
|or by setting the compiler option -language:$feature.
79+
|See the Scala docs for value $fqname for a discussion
80+
|why the feature $req be explicitly enabled.""".stripMargin
81+
}
82+
83+
val msg = s"$featureDescription $req be enabled\nby making the implicit value $fqname visible.$explain"
84+
if (required) error(msg, pos)
85+
else featureWarning(msg, pos)
86+
}
87+
7188
def warning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
7289
reporter.report(new Warning(msg, pos))
7390

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1098,7 +1098,12 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
10981098
.withType(dummy.nonMemberTermRef)
10991099
checkVariance(impl1)
11001100
if (!cls.is(AbstractOrTrait) && !ctx.isAfterTyper) checkRealizableBounds(cls.typeRef, cdef.pos)
1101-
assignType(cpy.TypeDef(cdef)(name, impl1, Nil), cls)
1101+
val cdef1 = assignType(cpy.TypeDef(cdef)(name, impl1, Nil), cls)
1102+
if (cdef1.tpe <:< defn.DynamicType && !ctx.featureEnabled(defn.LanguageModuleClass, nme.dynamics)) {
1103+
val isRequired = parents1.exists(_.tpe =:= defn.DynamicType)
1104+
ctx.featureWarning(cdef.pos, nme.dynamics.toString, "extension of type scala.Dynamic", isRequired)
1105+
}
1106+
cdef1
11021107

11031108
// todo later: check that
11041109
// 1. If class is non-abstract, it is instantiatable:

tests/neg/dynamicNoImport.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class Foo extends scala.Dynamic // error
2+
trait Bar extends scala.Dynamic // error
3+
object Baz extends scala.Dynamic // error
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
package foo {
3+
import dotty.language.dynamics
4+
class Bar extends scala.Dynamic
5+
}
6+
7+
class Baz extends foo.Bar

tests/run/dynamicDynamicTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import dotty.language.dynamics
12

23
class Foo extends scala.Dynamic {
34
def selectDynamic(name: String): String = "selectDynamic(" + name + ")"

0 commit comments

Comments
 (0)