Skip to content

Commit 47901c0

Browse files
ennrufelixmulder
authored andcommitted
Ennru forward reference error (#1973)
* Change 'forward reference extending over the definition' to Message * Change 'forward reference extending over the definition' to Message * pesky file should not be included * Change 'forward reference extending over the definition' to Message (test case)
1 parent b297832 commit 47901c0

File tree

4 files changed

+51
-3
lines changed

4 files changed

+51
-3
lines changed

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,4 +1034,23 @@ object messages {
10341034
|"""
10351035
}
10361036

1037+
case class ForwardReferenceExtendsOverDefinition(value: Symbol, definition: Symbol)(implicit ctx: Context)
1038+
extends Message(39) {
1039+
val kind = "Reference"
1040+
val msg = hl"`${definition.name}` is a forward reference extending over the definition of `${value.name}`"
1041+
1042+
val explanation =
1043+
hl"""|`${definition.name}` is used before you define it, and the definition of `${value.name}`
1044+
|appears between that use and the definition of `${definition.name}`.
1045+
|
1046+
|Forward references are allowed only, if there are no value definitions between
1047+
|the reference and the referred method definition.
1048+
|
1049+
|Define `${definition.name}` before it is used,
1050+
|or move the definition of `${value.name}` so it does not appear between
1051+
|the declartion of `${definition.name}` and its use,
1052+
|or define `${value.name}` as lazy.
1053+
|""".stripMargin
1054+
}
1055+
10371056
}

compiler/src/dotty/tools/dotc/typer/RefChecks.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,7 @@ import RefChecks._
767767
class RefChecks extends MiniPhase { thisTransformer =>
768768

769769
import tpd._
770+
import reporting.diagnostic.messages.ForwardReferenceExtendsOverDefinition
770771

771772
override def phaseName: String = "refchecks"
772773

@@ -789,8 +790,7 @@ class RefChecks extends MiniPhase { thisTransformer =>
789790
if (sym.exists && sym.owner.isTerm && !sym.is(Lazy))
790791
currentLevel.levelAndIndex.get(sym) match {
791792
case Some((level, symIdx)) if symIdx < level.maxIndex =>
792-
ctx.debuglog("refsym = " + level.refSym)
793-
ctx.error(s"forward reference extends over definition of $sym", level.refPos)
793+
ctx.error(ForwardReferenceExtendsOverDefinition(sym, level.refSym), level.refPos)
794794
case _ =>
795795
}
796796
tree

compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ package reporting
44

55
import core.Contexts.Context
66
import diagnostic.messages._
7-
87
import org.junit.Assert._
98
import org.junit.Test
109

@@ -85,4 +84,27 @@ class ErrorMessagesTests extends ErrorMessagesTest {
8584
assert(sameName.forall(_.symbol.name.show == "bar"),
8685
"at least one method had an unexpected name")
8786
}
87+
88+
@Test def forwardReference =
89+
checkMessagesAfter("refchecks") {
90+
"""
91+
|object Forward {
92+
| def block = {
93+
| a.toInt
94+
| val b = 2
95+
| val a = BigDecimal("4")
96+
| }
97+
|}
98+
""".stripMargin
99+
}
100+
.expect { (ictx, messages) =>
101+
implicit val ctx: Context = ictx
102+
val defn = ictx.definitions
103+
104+
assertMessageCount(1, messages)
105+
val ForwardReferenceExtendsOverDefinition(value, definition) :: Nil = messages
106+
assertEquals("value b", value.show)
107+
assertEquals("value a", definition.show)
108+
}
109+
88110
}

tests/repl/errmsgs.check

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,11 @@ scala> val x: List[Int] = "foo" :: List(1)
8585
| found: String($1$)
8686
| required: Int
8787
|
88+
scala> { def f: Int = g; val x: Int = 1; def g: Int = 5; }
89+
-- [E039] Reference Error: <console> -------------------------------------------
90+
5 |{ def f: Int = g; val x: Int = 1; def g: Int = 5; }
91+
| ^
92+
| `g` is a forward reference extending over the definition of `x`
93+
94+
longer explanation available when compiling with `-explain`
8895
scala> :quit

0 commit comments

Comments
 (0)