Skip to content

Fix #8841: Improve inline val error message #8844

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -888,9 +888,12 @@ trait Checking {
// final vals can be marked inline even if they're not pure, see Typer#patchFinalVals
val purityLevel = if (sym.is(Final)) Idempotent else Pure
tpt.tpe.widenTermRefExpr.dealias match
case tp: ConstantType if exprPurity(tree) >= purityLevel => // ok
case tp: ConstantType =>
if !(exprPurity(tree) >= purityLevel) then
ctx.error(em"inline value must be pure", tree.sourcePos)
case _ =>
ctx.error(em"type of inline must be a known value", tree.sourcePos)
val pos = if tpt.span.isZeroExtent then tree.sourcePos else tpt.sourcePos
ctx.error(em"inline value must have a literal constant type", pos)
}

/** A hook to exclude selected symbols from double declaration check */
Expand Down
19 changes: 19 additions & 0 deletions docs/docs/reference/metaprogramming/inline.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,25 @@ constant expressions in the sense defined by the [SLS §
including _platform-specific_ extensions such as constant folding of pure
numeric computations.

An inline value must have a literal type such as `1` or `true`.
```scala
inline val four = 4
// equivalent to
inline val four: 4 = 4
```

It is also possible to have inline vals of types that do not have a syntax, such as `Short(4)`.

```scala
trait InlineConstants {
inline val myShort: Short
}

object Constants extends InlineConstants {
inline val myShort/*: Short(4)*/ = 4
}
```

## Transparent Inline Methods

Inline methods can additionally be declared `transparent`.
Expand Down
12 changes: 12 additions & 0 deletions tests/neg/i8841.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- Error: tests/neg/i8841.scala:2:20 -----------------------------------------------------------------------------------
2 | inline val log1 : Boolean = false // error
| ^^^^^^^
| inline value must have a literal constant type
-- Error: tests/neg/i8841.scala:3:20 -----------------------------------------------------------------------------------
3 | inline val log2 = true: Boolean // error
| ^^^^^^^^^^^^^
| inline value must have a literal constant type
-- Error: tests/neg/i8841.scala:4:28 -----------------------------------------------------------------------------------
4 | inline val log3: false = { println(); false } // error
| ^^^^^^^^^^^^^^^^^^^^
| inline value must be pure
5 changes: 5 additions & 0 deletions tests/neg/i8841.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object Foo {
inline val log1 : Boolean = false // error
inline val log2 = true: Boolean // error
inline val log3: false = { println(); false } // error
}
23 changes: 23 additions & 0 deletions tests/pos/inline-vals.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
trait InlineConstants {
inline val myInlinedBoolean: Boolean
inline val myInlinedByte: Byte
inline val myInlinedShort: Short
inline val myInlinedInt: Int
inline val myInlinedLong: Long
inline val myInlinedFloat: Float
inline val myInlinedDouble: Double
inline val myInlinedChar: Char
inline val myInlinedString: String
}

object Constants extends InlineConstants {
inline val myInlinedBoolean = true
inline val myInlinedByte = 1
inline val myInlinedShort = 2
inline val myInlinedInt = 3
inline val myInlinedLong = 4
inline val myInlinedFloat = 5
inline val myInlinedDouble = 6
inline val myInlinedChar = 'a'
inline val myInlinedString = "abc"
}