Skip to content

Commit

Permalink
Merge pull request #14284 from dotty-staging/fix-#14282
Browse files Browse the repository at this point in the history
Properly desugar `inline given .. with ..`
  • Loading branch information
nicolasstucki authored Jan 27, 2022
2 parents 6597292 + 09a46f1 commit 6353ed9
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 3 deletions.
6 changes: 4 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ object desugar {
DefDef(
className.toTermName, joinParams(constrTparams, defParamss),
classTypeRef, creatorExpr)
.withMods(companionMods | mods.flags.toTermFlags & GivenOrImplicit | Final)
.withMods(companionMods | mods.flags.toTermFlags & (GivenOrImplicit | Inline) | Final)
.withSpan(cdef.span) :: Nil
}

Expand All @@ -809,7 +809,9 @@ object desugar {
Nil
}
}
val classMods = if mods.is(Given) then mods | Synthetic else mods
if mods.isAllOf(Given | Inline | Transparent) then
report.error("inline given instances cannot be trasparent", cdef)
val classMods = if mods.is(Given) then mods &~ (Inline | Transparent) | Synthetic else mods
cpy.TypeDef(cdef: TypeDef)(
name = className,
rhs = cpy.Template(impl)(constr, parents1, clsDerived, self1,
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3637,7 +3637,7 @@ object Parsers {
val templ =
if isStatSep || isStatSeqEnd then Template(constr, parents, Nil, EmptyValDef, Nil)
else withTemplate(constr, parents)
if noParams then ModuleDef(name, templ)
if noParams && !mods.is(Inline) then ModuleDef(name, templ)
else TypeDef(name.toTypeName, templ)
end gdef
finalizeDef(gdef, mods1, start)
Expand Down
22 changes: 22 additions & 0 deletions docs/docs/reference/contextual/givens.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,28 @@ transparent inline given mkAnnotations[A, T]: Annotations[A, T] = ${

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]`.

Given instances can have the `inline` but not `transparent` modifiers as their type is already known from the signature.
Example:

```scala
trait Show[T] {
inline def show(x: T): String
}

inline given Show[Foo] with {
/*transparent*/ inline def show(x: Foo): String = ${ ... }
}

def app =
// inlines `show` method call and removes the call to `given Show[Foo]`
summon[Show[Foo]].show(foo)
```
Note that the inline methods within the given instances may be `transparent`.

The inlining of given instances will not inline/duplicate the implementation of the given, it will just inline the instantiation of that instance.
This is used to help dead code elimination of the given instances that are not used after inlining.


## Pattern-Bound Given Instances

Given instances can also appear in patterns. Example:
Expand Down
6 changes: 6 additions & 0 deletions tests/neg/i14177a.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import scala.compiletime.*

trait C[A]

inline given [Tup <: Tuple]: C[Tup] with
val cs = summonAll[Tuple.Map[Tup, C]] // error cannot reduce inline match with
15 changes: 15 additions & 0 deletions tests/neg/i14177c.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class T

transparent inline given fail1: T with // error
val cs = scala.compiletime.summonAll[EmptyTuple]
transparent inline given fail2[X]: T with // error
val cs = scala.compiletime.summonAll[EmptyTuple]
transparent inline given fail3(using DummyImplicit): T with // error
val cs = scala.compiletime.summonAll[EmptyTuple]

transparent inline given ok1: T = new T:
val cs = scala.compiletime.summonAll[EmptyTuple]
transparent inline given ok2[X]: T = new T:
val cs = scala.compiletime.summonAll[EmptyTuple]
transparent inline given ok3(using DummyImplicit): T = new T:
val cs = scala.compiletime.summonAll[EmptyTuple]
15 changes: 15 additions & 0 deletions tests/pos/i14177b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class T

inline given fail1: T with
val cs = scala.compiletime.summonAll[EmptyTuple]
inline given fail2[X]: T with
val cs = scala.compiletime.summonAll[EmptyTuple]
inline given fail3(using DummyImplicit): T with
val cs = scala.compiletime.summonAll[EmptyTuple]

inline given ok1: T = new T:
val cs = scala.compiletime.summonAll[EmptyTuple]
inline given ok2[X]: T = new T:
val cs = scala.compiletime.summonAll[EmptyTuple]
inline given ok3(using DummyImplicit): T = new T:
val cs = scala.compiletime.summonAll[EmptyTuple]
13 changes: 13 additions & 0 deletions tests/pos/i14282.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
trait Foo[A] {
inline def foo(): Unit
}

inline given FooA[A]: Foo[A] with {
inline def foo(): Unit = println()
}
def test1 = FooA.foo()

inline given FooInt: Foo[Int] with {
inline def foo(): Unit = println()
}
def test2 = FooInt.foo()

0 comments on commit 6353ed9

Please sign in to comment.