summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Typers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-04-11 11:06:54 -0700
committerMartin Odersky <odersky@gmail.com>2012-04-11 11:06:54 -0700
commitf7a0558059559305a88ffa2c28506b29b2bc57f2 (patch)
tree267f7d00bbb327ca80b14df92e540251bf2da283 /src/compiler/scala/tools/nsc/typechecker/Typers.scala
parent754b4a85e4093f25cc10f092fefdb34215097c94 (diff)
downloadscala-f7a0558059559305a88ffa2c28506b29b2bc57f2.tar.gz
scala-f7a0558059559305a88ffa2c28506b29b2bc57f2.tar.bz2
scala-f7a0558059559305a88ffa2c28506b29b2bc57f2.zip
Implementation of SIP 18. We still need to get rid of the warnings caused by it. Before we do that, I'd like to check in the SIP 13 implementation.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Typers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala56
1 files changed, 53 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 36c81b09cd..19d7dde875 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -508,7 +508,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
res
}
-
/** The typer for a label definition. If this is part of a template we
* first have to enter the label definition.
*/
@@ -730,6 +729,38 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
+ def checkFeature(pos: Position, featureTrait: Symbol, construct: => String = "") =
+ if (!isPastTyper) {
+ val nestedOwners =
+ featureTrait.owner.ownerChain.takeWhile(_ != languageFeatureModule.moduleClass).reverse
+ val featureName = (nestedOwners map (_ + ".")).mkString + featureTrait.name
+ unit.toCheck += { () =>
+ if (!(unit.checkedFeatures contains featureTrait)) {
+ def hasImport = inferImplicit(EmptyTree: Tree, featureTrait.tpe, true, false, context) != SearchFailure
+ def hasOption = settings.feature.value contains featureName
+ if (!hasImport && !hasOption) {
+ val Some(AnnotationInfo(_, List(Literal(Constant(featureDesc: String)), Literal(Constant(required: Boolean))), _)) =
+ featureTrait getAnnotation LanguageFeatureClass
+ val req = if (required) "needs to" else "should"
+ val raw = featureDesc + " " + req + " be enabled by making\n" +
+ "the implicit value language." + featureName + " visible. This can be achieved by adding the import\n" +
+ "import language." + featureName + " or by setting the compiler option -language:" + featureName + ".\n" +
+ "See the Scala docs for value scala.language." + featureName + "for a discussion\n" +
+ "why the feature " + req + " be explicitly enabled."
+ val msg = raw replace ("#", construct)
+ if (required) unit.error(pos, msg) else unit.warning(pos, msg)
+ unit.checkedFeatures += featureTrait
+ }
+ }
+ }
+ }
+
+ def checkExistentialsFeature(pos: Position, tpe: Type, prefix: String) = tpe match {
+ case extp: ExistentialType if !extp.isRepresentableWithWildcards(checkBounds = false) =>
+ checkFeature(pos, ExistentialsFeature, prefix+" "+tpe)
+ case _ =>
+ }
+
/** Perform the following adaptations of expression, pattern or type `tree` wrt to
* given mode `mode` and given prototype `pt`:
* (-1) For expressions with annotated types, let AnnotationCheckers decide what to do
@@ -1937,6 +1968,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (meth.isStructuralRefinementMember)
checkMethodStructuralCompatible(meth)
+ if (meth.isImplicit) meth.info.paramss match {
+ case List(param) :: _ if !param.isImplicit =>
+ println("check implicit +"+meth+" "+isPastTyper)
+ checkFeature(ddef.pos, ImplicitConversionsFeature, meth.toString)
+ case _ =>
+ }
+
treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
@@ -1968,6 +2006,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case TypeBounds(lo1, hi1) if (!(lo1 <:< hi1)) => LowerBoundError(tdef, lo1, hi1)
case _ => ()
}
+
+ if (tdef.symbol.isDeferred && tdef.symbol.info.isHigherKinded)
+ checkFeature(tdef.pos, HigherKindsFeature)
+
treeCopy.TypeDef(tdef, typedMods, tdef.name, tparams1, rhs1) setType NoType
}
@@ -4666,6 +4708,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
else
typedSelect(qual1, name)
+ val sym = tree1.symbol
+ if (sym != null && sym.isTerm && sym.owner.isRefinementClass && !sym.isConstant)
+ checkFeature(tree1.pos, ReflectiveCallsFeature, sym.toString)
+
if (qual1.symbol == RootPackage) treeCopy.Ident(tree1, name)
else tree1
@@ -4708,9 +4754,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
treeCopy.TypeBoundsTree(tree, lo1, hi1) setType TypeBounds(lo1.tpe, hi1.tpe)
case etpt @ ExistentialTypeTree(_, _) =>
- typerWithLocalContext(context.makeNewScope(tree, context.owner)){
+ val tree1 = typerWithLocalContext(context.makeNewScope(tree, context.owner)){
_.typedExistentialTypeTree(etpt, mode)
}
+ checkExistentialsFeature(tree1.pos, tree1.tpe, "the existential type")
+ tree1
case dc@TypeTreeWithDeferredRefCheck() => dc // TODO: should we re-type the wrapped tree? then we need to change TypeTreeWithDeferredRefCheck's representation to include the wrapped tree explicitly (instead of in its closure)
case tpt @ TypeTree() =>
@@ -4918,7 +4966,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def computeType(tree: Tree, pt: Type): Type = {
val tree1 = typed(tree, pt)
transformed(tree) = tree1
- packedType(tree1, context.owner)
+ val tpe = packedType(tree1, context.owner)
+ checkExistentialsFeature(tree.pos, tpe, "inferred existential type")
+ tpe
}
def transformedOrTyped(tree: Tree, mode: Int, pt: Type): Tree = transformed.get(tree) match {