aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala47
1 files changed, 29 insertions, 18 deletions
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 97eded7cb..5d388e7de 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -669,25 +669,36 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
def typedReturn(tree: untpd.Return)(implicit ctx: Context): Return = track("typedReturn") {
- def returnProto(owner: Symbol) =
- if (owner.isConstructor) defn.UnitType else owner.info.finalResultType
- def enclMethInfo(cx: Context): (Tree, Type) =
- if (tree.from.isEmpty) {
- val owner = cx.owner
- if (cx == NoContext || owner.isType) {
- ctx.error("return outside method definition", tree.pos)
- (EmptyTree, WildcardType)
- } else if (owner.isSourceMethod)
- if (owner.isCompleted) {
- val from = Ident(TermRef(NoPrefix, owner.asTerm))
- val proto = returnProto(owner)
- (from, proto)
- } else (EmptyTree, errorType(d"$owner has return statement; needs result type", tree.pos))
- else enclMethInfo(cx.outer)
+ def returnProto(owner: Symbol, locals: Scope): Type =
+ if (owner.isConstructor) defn.UnitType
+ else owner.info match {
+ case info: PolyType =>
+ val tparams = locals.toList.takeWhile(_ is TypeParam)
+ assert(info.paramNames.length == tparams.length,
+ i"return mismatch from $owner, tparams = $tparams, locals = ${locals.toList}%, %")
+ info.instantiate(tparams.map(_.typeRef)).finalResultType
+ case info =>
+ info.finalResultType
}
- else
- (tree.from.asInstanceOf[tpd.Tree], returnProto(tree.from.symbol))
- val (from, proto) = enclMethInfo(ctx)
+ def enclMethInfo(cx: Context): (Tree, Type) = {
+ val owner = cx.owner
+ if (cx == NoContext || owner.isType) {
+ ctx.error("return outside method definition", tree.pos)
+ (EmptyTree, WildcardType)
+ }
+ else if (owner != cx.outer.owner && owner.isSourceMethod) {
+ if (owner.isCompleted) {
+ val from = Ident(TermRef(NoPrefix, owner.asTerm))
+ val proto = returnProto(owner, cx.scope)
+ (from, proto)
+ }
+ else (EmptyTree, errorType(d"$owner has return statement; needs result type", tree.pos))
+ }
+ else enclMethInfo(cx.outer)
+ }
+ val (from, proto) =
+ if (tree.from.isEmpty) enclMethInfo(ctx)
+ else (tree.from.asInstanceOf[tpd.Tree], WildcardType)
val expr1 = typedExpr(tree.expr orElse untpd.unitLiteral.withPos(tree.pos), proto)
assignType(cpy.Return(tree)(expr1, from))
}