diff options
Diffstat (limited to 'src/dotty/tools/dotc/typer/Typer.scala')
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 47 |
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)) } |