Skip to content

Commit 6353ed9

Browse files
Merge pull request #14284 from dotty-staging/fix-#14282
Properly desugar `inline given .. with ..`
2 parents 6597292 + 09a46f1 commit 6353ed9

File tree

7 files changed

+76
-3
lines changed

7 files changed

+76
-3
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ object desugar {
783783
DefDef(
784784
className.toTermName, joinParams(constrTparams, defParamss),
785785
classTypeRef, creatorExpr)
786-
.withMods(companionMods | mods.flags.toTermFlags & GivenOrImplicit | Final)
786+
.withMods(companionMods | mods.flags.toTermFlags & (GivenOrImplicit | Inline) | Final)
787787
.withSpan(cdef.span) :: Nil
788788
}
789789

@@ -809,7 +809,9 @@ object desugar {
809809
Nil
810810
}
811811
}
812-
val classMods = if mods.is(Given) then mods | Synthetic else mods
812+
if mods.isAllOf(Given | Inline | Transparent) then
813+
report.error("inline given instances cannot be trasparent", cdef)
814+
val classMods = if mods.is(Given) then mods &~ (Inline | Transparent) | Synthetic else mods
813815
cpy.TypeDef(cdef: TypeDef)(
814816
name = className,
815817
rhs = cpy.Template(impl)(constr, parents1, clsDerived, self1,

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3637,7 +3637,7 @@ object Parsers {
36373637
val templ =
36383638
if isStatSep || isStatSeqEnd then Template(constr, parents, Nil, EmptyValDef, Nil)
36393639
else withTemplate(constr, parents)
3640-
if noParams then ModuleDef(name, templ)
3640+
if noParams && !mods.is(Inline) then ModuleDef(name, templ)
36413641
else TypeDef(name.toTypeName, templ)
36423642
end gdef
36433643
finalizeDef(gdef, mods1, start)

docs/docs/reference/contextual/givens.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,28 @@ transparent inline given mkAnnotations[A, T]: Annotations[A, T] = ${
100100

101101
Since `mkAnnotations` is `transparent`, the type of an application is the type of its right-hand side, which can be a proper subtype of the declared result type `Annotations[A, T]`.
102102

103+
Given instances can have the `inline` but not `transparent` modifiers as their type is already known from the signature.
104+
Example:
105+
106+
```scala
107+
trait Show[T] {
108+
inline def show(x: T): String
109+
}
110+
111+
inline given Show[Foo] with {
112+
/*transparent*/ inline def show(x: Foo): String = ${ ... }
113+
}
114+
115+
def app =
116+
// inlines `show` method call and removes the call to `given Show[Foo]`
117+
summon[Show[Foo]].show(foo)
118+
```
119+
Note that the inline methods within the given instances may be `transparent`.
120+
121+
The inlining of given instances will not inline/duplicate the implementation of the given, it will just inline the instantiation of that instance.
122+
This is used to help dead code elimination of the given instances that are not used after inlining.
123+
124+
103125
## Pattern-Bound Given Instances
104126

105127
Given instances can also appear in patterns. Example:

tests/neg/i14177a.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import scala.compiletime.*
2+
3+
trait C[A]
4+
5+
inline given [Tup <: Tuple]: C[Tup] with
6+
val cs = summonAll[Tuple.Map[Tup, C]] // error cannot reduce inline match with

tests/neg/i14177c.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class T
2+
3+
transparent inline given fail1: T with // error
4+
val cs = scala.compiletime.summonAll[EmptyTuple]
5+
transparent inline given fail2[X]: T with // error
6+
val cs = scala.compiletime.summonAll[EmptyTuple]
7+
transparent inline given fail3(using DummyImplicit): T with // error
8+
val cs = scala.compiletime.summonAll[EmptyTuple]
9+
10+
transparent inline given ok1: T = new T:
11+
val cs = scala.compiletime.summonAll[EmptyTuple]
12+
transparent inline given ok2[X]: T = new T:
13+
val cs = scala.compiletime.summonAll[EmptyTuple]
14+
transparent inline given ok3(using DummyImplicit): T = new T:
15+
val cs = scala.compiletime.summonAll[EmptyTuple]

tests/pos/i14177b.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class T
2+
3+
inline given fail1: T with
4+
val cs = scala.compiletime.summonAll[EmptyTuple]
5+
inline given fail2[X]: T with
6+
val cs = scala.compiletime.summonAll[EmptyTuple]
7+
inline given fail3(using DummyImplicit): T with
8+
val cs = scala.compiletime.summonAll[EmptyTuple]
9+
10+
inline given ok1: T = new T:
11+
val cs = scala.compiletime.summonAll[EmptyTuple]
12+
inline given ok2[X]: T = new T:
13+
val cs = scala.compiletime.summonAll[EmptyTuple]
14+
inline given ok3(using DummyImplicit): T = new T:
15+
val cs = scala.compiletime.summonAll[EmptyTuple]

tests/pos/i14282.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
trait Foo[A] {
2+
inline def foo(): Unit
3+
}
4+
5+
inline given FooA[A]: Foo[A] with {
6+
inline def foo(): Unit = println()
7+
}
8+
def test1 = FooA.foo()
9+
10+
inline given FooInt: Foo[Int] with {
11+
inline def foo(): Unit = println()
12+
}
13+
def test2 = FooInt.foo()

0 commit comments

Comments
 (0)