Skip to content

Commit 2081372

Browse files
committed
Fix stability check for inline parameters
Inline parameters are not stable. Two references to the same parameter may not be idempotent.
1 parent 80f67df commit 2081372

File tree

13 files changed

+27
-13
lines changed

13 files changed

+27
-13
lines changed

compiler/src/dotty/tools/dotc/core/SymDenotations.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ object SymDenotations {
742742
* So the first call to a stable member might fail and/or produce side effects.
743743
*/
744744
final def isStableMember(using Context): Boolean = {
745-
def isUnstableValue = isOneOf(UnstableValueFlags) || info.isInstanceOf[ExprType]
745+
def isUnstableValue = isOneOf(UnstableValueFlags) || info.isInstanceOf[ExprType] || isAllOf(InlineParam)
746746
isType || is(StableRealizable) || exists && !isUnstableValue
747747
}
748748

language-server/test/dotty/tools/languageserver/CompletionTest.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class CompletionTest {
2727

2828
@Test def completionFromNewScalaPredef: Unit = {
2929
code"class Foo { val foo = summ${m1} }"
30-
.completion(("summon", Method, "[T](using x: T): x.type"))
30+
.completion(("summon", Method, "[T](using x: T): T"))
3131
}
3232

3333
@Test def completionFromScalaPackage: Unit = {

library/src/scala/quoted/Quotes.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import scala.reflect.TypeTest
1414
* }
1515
* ```
1616
*/
17-
transparent inline def quotes(using inline q: Quotes): q.type = q
17+
transparent inline def quotes(using q: Quotes): q.type = q
1818

1919
/** Quotation context provided by a macro expansion or in the scope of `scala.quoted.staging.run`.
2020
* Used to perform all operations on quoted `Expr` or `Type`.

library/src/scala/runtime/stdLibPatches/Predef.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ object Predef:
3131
* @tparam T the type of the value to be summoned
3232
* @return the given value typed: the provided type parameter
3333
*/
34-
transparent inline def summon[T](using inline x: T): x.type = x
34+
transparent inline def summon[T](using inline x: T): T = x
3535

3636
// Extension methods for working with explicit nulls
3737

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
object B {
22

3-
inline def inlinedAny(x: String): x.type = x
3+
inline def inlinedAny(x: String): String = x
44

55
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
object B {
22

3-
inline def inlinedAny(inline x: String): x.type = x
3+
inline def inlinedAny(inline x: String): String = x
44

55
}

scaladoc/src/dotty/tools/scaladoc/tasty/reflect.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ package tasty
44
import scala.quoted._
55

66
/** Shorthand for `quotes.reflect` */
7-
transparent inline def reflect(using inline q: Quotes): q.reflect.type = q.reflect
7+
transparent inline def reflect(using q: Quotes): q.reflect.type = q.reflect
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
inline val a = 3
2+
inline def f(inline x: Int, y: Int, z: => Int): Unit =
3+
val x2: x.type = x // error: (x : Int) is not a valid singleton type, since it is not an immutable path
4+
val y2: y.type = y
5+
val z2: z.type = z // error: (z : Int) is not a valid singleton type, since it is not an immutable path
6+
val a2: a.type = a
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
inline def f(inline x: Int): Unit =
2+
inline val b = x
3+
val c: b.type = b
4+
5+
def test =
6+
f(1)
7+
def a = 1
8+
f(a) // error: inline value must have a literal constant type

tests/pos/i11163.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
inline def summonA[T](using x: T): x.type = x
2-
inline def summonB[T](using inline x: T): x.type = x
2+
// inline def summonB[T](using inline x: T): x.type = x // inline parameters are unstable
33
inline def summonC[T](using inline x: T): T = x
44

55
trait Foo:
66
def f: Int = 9
77

88
def test(using Foo) =
99
summonA[Foo].f
10-
summonB[Foo].f
10+
// summonB[Foo].f
1111
summonC[Foo].f
1212
()

tests/pos/i12379a.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
inline def convFail[Of, From](inline from : From) : Unit =
1+
inline def convFail[Of, From](from : From) : Unit = // removed inline from parameter to avoid unsound path selection
22
val c = compiletime.summonInline[Conversion[from.type, Of]]
33

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

66
class Bar[T](value : T)
77
given [T <: Int] : Conversion[T, Bar[T]] = Bar(_)

tests/run/deriving-constructor-order.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import scala.compiletime.erasedValue
22
import scala.deriving.Mirror
33

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

0 commit comments

Comments
 (0)