summaryrefslogtreecommitdiff
path: root/src/compiler/scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala26
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Modes.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala5
3 files changed, 34 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala b/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala
index d26c5d65a0..be2e520554 100644
--- a/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala
+++ b/src/compiler/scala/tools/nsc/symtab/AnnotationCheckers.scala
@@ -47,6 +47,13 @@ trait AnnotationCheckers {
* before. If the implementing class cannot do the adaptiong, it
* should return the tree unchanged.*/
def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = tree
+
+ /** Adapt the type of a return expression. The decision of an annotation checker
+ * whether the type should be adapted is based on the type of the expression
+ * which is returned, as well as the result type of the method (pt).
+ * By default, this method simply returns the passed `default` type.
+ */
+ def adaptTypeOfReturn(tree: Tree, pt: Type, default: => Type): Type = default
}
/** The list of annotation checkers that have been registered */
@@ -117,4 +124,23 @@ trait AnnotationCheckers {
annotationCheckers.foldLeft(tree)((tree, checker) =>
checker.adaptAnnotations(tree, mode, pt))
}
+
+ /** Let a registered annotation checker adapt the type of a return expression.
+ * Annotation checkers that cannot do the adaptation should simply return
+ * the `default` argument.
+ *
+ * Note that the result is undefined if more than one annotation checker
+ * returns an adapted type which is not a subtype of `default`.
+ */
+ def adaptTypeOfReturn(tree: Tree, pt: Type, default: => Type): Type = {
+ val adaptedTypes = annotationCheckers flatMap { checker =>
+ val adapted = checker.adaptTypeOfReturn(tree, pt, default)
+ if (!(adapted <:< default)) List(adapted)
+ else List()
+ }
+ adaptedTypes match {
+ case fst :: _ => fst
+ case List() => default
+ }
+ }
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Modes.scala b/src/compiler/scala/tools/nsc/typechecker/Modes.scala
index ad4be4662c..b8308ebabf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Modes.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Modes.scala
@@ -86,6 +86,10 @@ trait Modes {
*/
final val TYPEPATmode = 0x10000
+ /** RETmode is set when we are typing a return expression.
+ */
+ final val RETmode = 0x20000
+
final private val StickyModes = EXPRmode | PATTERNmode | TYPEmode | ALTmode
final def onlyStickyModes(mode: Int) =
@@ -130,4 +134,4 @@ trait Modes {
def modeString(mode: Int): String =
if (mode == 0) "NOmode"
else (modeNameMap filterKeys (bit => inAllModes(mode, bit))).values mkString " "
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 1a77ee6a9b..05b36d128e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3181,7 +3181,7 @@ trait Typers extends Modes {
errorTree(tree, enclMethod.owner + " has return statement; needs result type")
else {
context.enclMethod.returnsSeen = true
- val expr1: Tree = typed(expr, EXPRmode | BYVALmode, restpt.tpe)
+ val expr1: Tree = typed(expr, EXPRmode | BYVALmode | RETmode, restpt.tpe)
// Warn about returning a value if no value can be returned.
if (restpt.tpe.typeSymbol == UnitClass) {
// The typing in expr1 says expr is Unit (it has already been coerced if
@@ -3190,7 +3190,8 @@ trait Typers extends Modes {
if (typed(expr).tpe.typeSymbol != UnitClass)
unit.warning(tree.pos, "enclosing method " + name + " has result type Unit: return value discarded")
}
- treeCopy.Return(tree, checkDead(expr1)) setSymbol enclMethod.owner setType NothingClass.tpe
+ treeCopy.Return(tree, checkDead(expr1)).setSymbol(enclMethod.owner)
+ .setType(adaptTypeOfReturn(expr1, restpt.tpe, NothingClass.tpe))
}
}
}