Skip to content

Commit 7f6d234

Browse files
committed
Merge pull request #302 from dotty-staging/fix/returns
Fix/returns
2 parents 3582c12 + 329b639 commit 7f6d234

File tree

5 files changed

+49
-31
lines changed

5 files changed

+49
-31
lines changed

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ object SymDenotations {
422422
}
423423

424424
/** Is this a user defined "def" method? Excluded are accessors. */
425-
final def isSourceMethod(implicit ctx: Context) = this is (Method, butNot = Accessor)
425+
final def isSourceMethod(implicit ctx: Context) = this is (Method, butNot = AccessorOrLabel)
426426

427427
/** Is this a setter? */
428428
final def isGetter(implicit ctx: Context) =
@@ -1664,4 +1664,6 @@ object SymDenotations {
16641664
private final val NumBits = NumWords << WordSizeLog
16651665
private final val Mask = NumBits - 1
16661666
}
1667+
1668+
private val AccessorOrLabel = Accessor | Label
16671669
}

src/dotty/tools/dotc/reporting/ConsoleReporter.scala

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,17 @@ class ConsoleReporter(
4040
}
4141
}
4242

43-
override def doReport(d: Diagnostic)(implicit ctx: Context): Unit = d match {
44-
case d: Error =>
45-
printMessageAndPos(s"error: ${d.msg}", d.pos)
46-
if (ctx.settings.prompt.value) displayPrompt()
47-
case d: ConditionalWarning if !d.enablingOption.value =>
48-
case d: Warning =>
49-
printMessageAndPos(s"warning: ${d.msg}", d.pos)
50-
case _ =>
51-
printMessageAndPos(d.msg, d.pos)
52-
}
43+
override def doReport(d: Diagnostic)(implicit ctx: Context): Unit =
44+
if (!d.isSuppressed) d match {
45+
case d: Error =>
46+
printMessageAndPos(s"error: ${d.msg}", d.pos)
47+
if (ctx.settings.prompt.value) displayPrompt()
48+
case d: ConditionalWarning if !d.enablingOption.value =>
49+
case d: Warning =>
50+
printMessageAndPos(s"warning: ${d.msg}", d.pos)
51+
case _ =>
52+
printMessageAndPos(d.msg, d.pos)
53+
}
5354

5455
def displayPrompt(): Unit = {
5556
writer.print("\na)bort, s)tack, r)esume: ")

src/dotty/tools/dotc/reporting/Reporter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ abstract class Reporter {
216216

217217
def report(d: Diagnostic)(implicit ctx: Context): Unit = if (!isHidden(d)) {
218218
doReport(d)
219-
if (!d.isSuppressed) d match {
219+
d match {
220220
case d: ConditionalWarning if !d.enablingOption.value => unreportedWarnings(d.enablingOption.name) += 1
221221
case d: Warning => warningCount += 1
222222
case d: Error => errorCount += 1

src/dotty/tools/dotc/transform/TreeTransform.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1141,7 +1141,11 @@ object TreeTransforms {
11411141
if (mutatedInfo eq null) tree
11421142
else {
11431143
val expr = transform(tree.expr, mutatedInfo, cur)
1144-
val from = transform(tree.from, mutatedInfo, cur)
1144+
val from = tree.from
1145+
// don't thansform the `from` part, as this is not a normal ident, but
1146+
// a pointer to the enclosing method. Transforming this as a normal ident
1147+
// can go wrong easily. If a transformation is needed, it should be
1148+
// the responsibility of the transformReturn method to handle this also.
11451149
goReturn(cpy.Return(tree)(expr, from), mutatedInfo.nx.nxTransReturn(cur))
11461150
}
11471151
case tree: Try =>

src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -669,25 +669,36 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
669669
}
670670

671671
def typedReturn(tree: untpd.Return)(implicit ctx: Context): Return = track("typedReturn") {
672-
def returnProto(owner: Symbol) =
673-
if (owner.isConstructor) defn.UnitType else owner.info.finalResultType
674-
def enclMethInfo(cx: Context): (Tree, Type) =
675-
if (tree.from.isEmpty) {
676-
val owner = cx.owner
677-
if (cx == NoContext || owner.isType) {
678-
ctx.error("return outside method definition", tree.pos)
679-
(EmptyTree, WildcardType)
680-
} else if (owner.isSourceMethod)
681-
if (owner.isCompleted) {
682-
val from = Ident(TermRef(NoPrefix, owner.asTerm))
683-
val proto = returnProto(owner)
684-
(from, proto)
685-
} else (EmptyTree, errorType(d"$owner has return statement; needs result type", tree.pos))
686-
else enclMethInfo(cx.outer)
672+
def returnProto(owner: Symbol, locals: Scope): Type =
673+
if (owner.isConstructor) defn.UnitType
674+
else owner.info match {
675+
case info: PolyType =>
676+
val tparams = locals.toList.takeWhile(_ is TypeParam)
677+
assert(info.paramNames.length == tparams.length,
678+
i"return mismatch from $owner, tparams = $tparams, locals = ${locals.toList}%, %")
679+
info.instantiate(tparams.map(_.typeRef)).finalResultType
680+
case info =>
681+
info.finalResultType
687682
}
688-
else
689-
(tree.from.asInstanceOf[tpd.Tree], returnProto(tree.from.symbol))
690-
val (from, proto) = enclMethInfo(ctx)
683+
def enclMethInfo(cx: Context): (Tree, Type) = {
684+
val owner = cx.owner
685+
if (cx == NoContext || owner.isType) {
686+
ctx.error("return outside method definition", tree.pos)
687+
(EmptyTree, WildcardType)
688+
}
689+
else if (owner != cx.outer.owner && owner.isSourceMethod) {
690+
if (owner.isCompleted) {
691+
val from = Ident(TermRef(NoPrefix, owner.asTerm))
692+
val proto = returnProto(owner, cx.scope)
693+
(from, proto)
694+
}
695+
else (EmptyTree, errorType(d"$owner has return statement; needs result type", tree.pos))
696+
}
697+
else enclMethInfo(cx.outer)
698+
}
699+
val (from, proto) =
700+
if (tree.from.isEmpty) enclMethInfo(ctx)
701+
else (tree.from.asInstanceOf[tpd.Tree], WildcardType)
691702
val expr1 = typedExpr(tree.expr orElse untpd.unitLiteral.withPos(tree.pos), proto)
692703
assignType(cpy.Return(tree)(expr1, from))
693704
}

0 commit comments

Comments
 (0)