Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
28 changes: 28 additions & 0 deletions compiler/src/dotty/tools/dotc/inlines/Inlines.scala
Original file line number Diff line number Diff line change
Expand Up @@ -619,4 +619,32 @@ object Inlines:
// the opaque type itself. An example is in pos/opaque-inline1.scala.
end expand
end InlineCall

/** An inline val is refinable if it has an explicit type that is not a
* singleton type.
*/
def mightRefineInlineVal(mdef: untpd.ValOrDefDef, sym: Symbol)(using Context): Boolean =
sym.isInlineVal && !sym.is(Final)
&& !mdef.tpt.isEmpty && !mdef.tpt.isInstanceOf[untpd.SingletonTypeTree]

/** Refine the type of an inline val to a constant type if its right hand
* side is a literal. See tests/pos/i24321.scala and tests/printing/i24321.scala.
*/
def refineInlineVal(mdef: untpd.ValOrDefDef, sym: Symbol, tp: Type)(using Context): Type =
if !Inlines.mightRefineInlineVal(mdef, sym) then
return tp

// Only refine if the explicit type is a primitive value types and String.
// We don't include opaque types. See tests/neg/i13851b.scala.
val tpSym = tp.dealiasKeepOpaques.typeSymbol
if !tpSym.isPrimitiveValueClass && tpSym != defn.StringClass then
return tp

untpd.stripBlock(mdef.rhs) match
case rhs: (untpd.Literal | untpd.Number) =>
ctx.typer.typedAheadExpr(rhs, tp) match
case tpd.ConstantValue(c) => ConstantType(Constant(c))
case _ => tp
case _ => tp

end Inlines
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1927,7 +1927,10 @@ class Namer { typer: Typer =>
sym.setFlag(Deferred | HasDefault)
case _ =>

val mbrTpe = paramFn(checkSimpleKinded(typedAheadType(mdef.tpt, tptProto)).tpe)
val mbrTpe0 = checkSimpleKinded(typedAheadType(mdef.tpt, tptProto)).tpe
val mbrTpe1 = Inlines.refineInlineVal(mdef, sym, mbrTpe0)
val mbrTpe = paramFn(mbrTpe1)

// Add an erased to the using clause generated from a `: Singleton` context bound
mdef.tpt match
case tpt: untpd.ContextBoundTypeTree if mbrTpe.typeSymbol == defn.SingletonClass =>
Expand Down
9 changes: 8 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3038,7 +3038,14 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
sym.resetFlag(Lazy)
checkErasedOK(sym)
sym.setFlag(Erased)
val tpt1 = checkSimpleKinded(typedType(tpt))

val isRefinedInlineVal =
Inlines.mightRefineInlineVal(vdef, sym)
&& sym.info.isInstanceOf[ConstantType]

val tpt0 = checkSimpleKinded(typedType(tpt))
val tpt1 = if isRefinedInlineVal then TypeTree(sym.info) else tpt0

val rhs1 = vdef.rhs match
case rhs @ Ident(nme.WILDCARD) =>
rhs.withType(tpt1.tpe)
Expand Down
4 changes: 0 additions & 4 deletions tests/neg/i8841.check
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
-- 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
| ^^^^^^^^^^^^^
Expand Down
2 changes: 1 addition & 1 deletion tests/neg/i8841.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
object Foo {
inline val log1 : Boolean = false // error
inline val log1 : Boolean = false // ok
inline val log2 = true: Boolean // error
inline val log3: false = { println(); false } // error
}
4 changes: 2 additions & 2 deletions tests/neg/inline-val.scala
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

inline val a = 1 : Int // error
inline val b: Int = 1 // error
inline val c = b // error
inline val b: Int = 1 // ok
inline val c = b // ok
4 changes: 4 additions & 0 deletions tests/pos/i24321.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
object Bar:
inline val MAX: Byte = 10

val y = Bar.MAX to Bar.MAX
15 changes: 15 additions & 0 deletions tests/printing/i24321.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[[syntax trees at end of typer]] // tests/printing/i24321.scala
package <empty> {
final lazy module val i24321$package: i24321$package = new i24321$package()
final module class i24321$package() extends Object() {
this: i24321$package.type =>
inline val BOOL_CONST: (true : Boolean) = true
inline val CHAR_CONST: ('A' : Char) = 'A'
inline val INT_CONST: (100000 : Int) = 100000
inline val LONG_CONST: (100000L : Long) = 100000L
inline val FLOAT_CONST: (3.14f : Float) = 3.14f
inline val DOUBLE_CONST: (3.14159d : Double) = 3.14159d
inline val STRING_CONST: ("Hello, Scala 3!" : String) = "Hello, Scala 3!"
}
}

7 changes: 7 additions & 0 deletions tests/printing/i24321.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
inline val BOOL_CONST: Boolean = true
inline val CHAR_CONST: Char = 'A'
inline val INT_CONST: Int = 100000
inline val LONG_CONST: Long = 100000L
inline val FLOAT_CONST: Float = 3.14f
inline val DOUBLE_CONST: Double = 3.14159
inline val STRING_CONST: String = "Hello, Scala 3!"
Loading