summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker')
-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 {