Skip to content

Commit

Permalink
Fix stability check for inline parameters (scala#15511)
Browse files Browse the repository at this point in the history
Inline parameters are not stable. Two references to the same parameter
may not be idempotent.
  • Loading branch information
smarter authored Dec 13, 2022
2 parents b21a457 + 77a8902 commit 5929a50
Show file tree
Hide file tree
Showing 12 changed files with 26 additions and 12 deletions.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,7 @@ object SymDenotations {
* So the first call to a stable member might fail and/or produce side effects.
*/
final def isStableMember(using Context): Boolean = {
def isUnstableValue = isOneOf(UnstableValueFlags) || info.isInstanceOf[ExprType]
def isUnstableValue = isOneOf(UnstableValueFlags) || info.isInstanceOf[ExprType] || isAllOf(InlineParam)
isType || is(StableRealizable) || exists && !isUnstableValue
}

Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/quoted/Quotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import scala.reflect.TypeTest
* }
* ```
*/
transparent inline def quotes(using inline q: Quotes): q.type = q
transparent inline def quotes(using q: Quotes): q.type = q

/** Quotation context provided by a macro expansion or in the scope of `scala.quoted.staging.run`.
* Used to perform all operations on quoted `Expr` or `Type`.
Expand Down
2 changes: 1 addition & 1 deletion library/src/scala/runtime/stdLibPatches/Predef.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object Predef:
* @tparam T the type of the value to be summoned
* @return the given value typed: the provided type parameter
*/
transparent inline def summon[T](using inline x: T): x.type = x
transparent inline def summon[T](using x: T): x.type = x

// Extension methods for working with explicit nulls

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
object B {

inline def inlinedAny(x: String): x.type = x
inline def inlinedAny(x: String): String = x

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
object B {

inline def inlinedAny(inline x: String): x.type = x
inline def inlinedAny(inline x: String): String = x

}
2 changes: 1 addition & 1 deletion scaladoc/src/dotty/tools/scaladoc/tasty/reflect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ package tasty
import scala.quoted._

/** Shorthand for `quotes.reflect` */
transparent inline def reflect(using inline q: Quotes): q.reflect.type = q.reflect
transparent inline def reflect(using q: Quotes): q.reflect.type = q.reflect
6 changes: 6 additions & 0 deletions tests/neg/inline-param-unstable-path.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
inline val a = 3
inline def f(inline x: Int, y: Int, z: => Int): Unit =
val x2: x.type = x // error: (x : Int) is not a valid singleton type, since it is not an immutable path
val y2: y.type = y
val z2: z.type = z // error: (z : Int) is not a valid singleton type, since it is not an immutable path
val a2: a.type = a
8 changes: 8 additions & 0 deletions tests/neg/inline-val-in-inline-method.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
inline def f(inline x: Int): Unit =
inline val b = x
val c: b.type = b

def test =
f(1)
def a = 1
f(a) // error: inline value must have a literal constant type
4 changes: 2 additions & 2 deletions tests/pos/i11163.scala
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
inline def summonA[T](using x: T): x.type = x
inline def summonB[T](using inline x: T): x.type = x
// inline def summonB[T](using inline x: T): x.type = x // inline parameters are unstable
inline def summonC[T](using inline x: T): T = x

trait Foo:
def f: Int = 9

def test(using Foo) =
summonA[Foo].f
summonB[Foo].f
// summonB[Foo].f
summonC[Foo].f
()
4 changes: 2 additions & 2 deletions tests/pos/i12379a.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
inline def convFail[Of, From](inline from : From) : Unit =
inline def convFail[Of, From](from : From) : Unit = // removed inline from parameter to avoid unsound path selection
val c = compiletime.summonInline[Conversion[from.type, Of]]

inline def convOK[Of, From](inline from : From)(using c : Conversion[from.type, Of]) : Unit = {}
inline def convOK[Of, From](from : From)(using c : Conversion[from.type, Of]) : Unit = {} // removed inline from parameter to avoid unsound path selection

class Bar[T](value : T)
given [T <: Int] : Conversion[T, Bar[T]] = Bar(_)
Expand Down
2 changes: 1 addition & 1 deletion tests/run/deriving-constructor-order.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import scala.compiletime.erasedValue
import scala.deriving.Mirror

object Test extends App {
inline def checkElems[A, T](using inline A: Mirror.SumOf[A]): Unit =
inline def checkElems[A, T](using A: Mirror.SumOf[A]): Unit = // removed inline from parameter to avoid unsound path selection
inline erasedValue[A.MirroredElemTypes] match {
case _: T => ()
}
Expand Down

0 comments on commit 5929a50

Please sign in to comment.