Skip to content

Commit bff6b09

Browse files
oderskyDarkDimius
authored andcommitted
Add language feature mechanism
Add a method "featureEnabled" that checks whether a feature is enabled. Features can be enabled by imports or by command-line options. The Scala 2.10 way of enabling features by implicits got dropped, because the use of the feature mechanism is now different. Previously, features imposed restrictions on what used to work. So it was important to offer way to avoid the restrictions it that was as smooth as possible, and implicits fit the bill. Furthermore, features did not change the way things were compiled, so it was OK to test them only once all types were compiled. Now, features are essentially switches that change compile time behavior. keepUnions and noAutoTupling, if on, will modify the way type inference works. So we need to interprete a switch on the spot, and doing an implicit search to determine a switch value is too dangerous in what concerns causing cyclic references. At the same time, because we are dealing with new functionality, there is less of a concern for being able to set or reset features for large pieces of code with some implicit. You could argue that's not even desirable, and that an explicit import or command line option is preferable. Conflicts: src/dotty/tools/dotc/core/SymDenotations.scala
1 parent 2df29a2 commit bff6b09

File tree

5 files changed

+67
-1
lines changed

5 files changed

+67
-1
lines changed

src/dotty/language.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package dotty
2+
3+
object language {
4+
5+
class Feature
6+
7+
/** Allow higher-kinded type syntax (not yet checked) */
8+
val higherKinds = new Feature
9+
10+
/** Keep union types */
11+
val keepUnions = new Feature
12+
13+
/** No auto tupling */
14+
val noAutoTupling = new Feature
15+
16+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ class Definitions {
215215
lazy val JavaSerializableClass = ctx.requiredClass("java.lang.Serializable")
216216
lazy val ComparableClass = ctx.requiredClass("java.lang.Comparable")
217217
lazy val ProductClass = ctx.requiredClass("scala.Product")
218+
lazy val LanguageModuleClass = ctx.requiredModule("dotty.language").moduleClass
218219

219220
// Annotation base classes
220221
lazy val AnnotationClass = ctx.requiredClass("scala.annotation.Annotation")

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ object StdNames {
375375
val hashCode_ : N = "hashCode"
376376
val hash_ : N = "hash"
377377
val head: N = "head"
378+
val higherKinds: N = "higherKinds"
378379
val identity: N = "identity"
379380
val implicitly: N = "implicitly"
380381
val in: N = "in"
@@ -387,6 +388,7 @@ object StdNames {
387388
val isInstanceOf_ : N = "isInstanceOf"
388389
val isInstanceOf_Ob : N = "$isInstanceOf"
389390
val java: N = "java"
391+
val keepUnions: N = "keepUnions"
390392
val key: N = "key"
391393
val lang: N = "lang"
392394
val length: N = "length"
@@ -415,6 +417,7 @@ object StdNames {
415417
val next: N = "next"
416418
val nmeNewTermName: N = "newTermName"
417419
val nmeNewTypeName: N = "newTypeName"
420+
val noAutoTupling: N = "noAutoTupling"
418421
val normalize: N = "normalize"
419422
val notifyAll_ : N = "notifyAll"
420423
val notify_ : N = "notify"

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import collection.mutable
99
import collection.immutable.BitSet
1010
import scala.reflect.io.AbstractFile
1111
import Decorators.SymbolIteratorDecorator
12-
import ast.tpd
12+
import ast._
1313
import annotation.tailrec
1414
import util.SimpleMap
1515
import util.Stats
@@ -195,6 +195,18 @@ object SymDenotations {
195195
final def hasAnnotation(cls: Symbol)(implicit ctx: Context) =
196196
dropOtherAnnotations(annotations, cls).nonEmpty
197197

198+
/** Optionally, the arguments of the first annotation matching the given class symbol */
199+
final def getAnnotationArgs(cls: Symbol)(implicit ctx: Context): Option[List[tpd.Tree]] =
200+
dropOtherAnnotations(annotations, cls) match {
201+
case annot :: _ =>
202+
Some(
203+
annot.tree match {
204+
case Trees.Apply(_, args) => args
205+
case _ => Nil
206+
})
207+
case nil => None
208+
}
209+
198210
/** Add given annotation to the annotations of this denotation */
199211
final def addAnnotation(annot: Annotation): Unit =
200212
annotations = annot :: myAnnotations

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,40 @@ trait TypeOps { this: Context =>
266266
}
267267
parentRefs
268268
}
269+
270+
/** Is `feature` enabled in class `owner`?
271+
* This is the case if one of the following two alternatives holds:
272+
*
273+
* 1. The feature is imported by a named import
274+
*
275+
* import owner.feature
276+
*
277+
* (the feature may be bunched with others, or renamed, but wildcard imports
278+
* don't count).
279+
*
280+
* 2. The feature is enabled by a compiler option
281+
*
282+
* - language:<prefix>feature
283+
*
284+
* where <prefix> is the full name of the owner followed by a "." minus
285+
* the prefix "dotty.language.".
286+
*/
287+
def featureEnabled(owner: ClassSymbol, feature: TermName): Boolean = {
288+
def toPrefix(sym: Symbol): String =
289+
if (sym eq defn.LanguageModuleClass) "" else toPrefix(sym.owner) + sym.name + "."
290+
def featureName = toPrefix(owner) + feature
291+
def hasImport(implicit ctx: Context): Boolean = (
292+
ctx.importInfo != null
293+
&& ( (ctx.importInfo.site.widen.typeSymbol eq owner)
294+
&& ctx.importInfo.originals.contains(feature)
295+
||
296+
{ var c = ctx.outer
297+
while (c.importInfo eq ctx.importInfo) c = c.outer
298+
hasImport(c)
299+
}))
300+
def hasOption = ctx.base.settings.language.value exists (s => s == featureName || s == "_")
301+
hasImport || hasOption
302+
}
269303
}
270304

271305
object TypeOps {

0 commit comments

Comments
 (0)