Skip to content

Commit

Permalink
Fix stability check for inline parameters
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
nicolasstucki committed Dec 13, 2022
1 parent 01a5dd4 commit 77a8902
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 77a8902

Please sign in to comment.