diff --git a/community-build/community-projects/protoquill b/community-build/community-projects/protoquill index 16d26fcb3072..e6d5fb3cd3b9 160000 --- a/community-build/community-projects/protoquill +++ b/community-build/community-projects/protoquill @@ -1 +1 @@ -Subproject commit 16d26fcb30720b9aa81d29f08b9da10916e269a2 +Subproject commit e6d5fb3cd3b978d3a9a18797f0f39ef03e2c5bba diff --git a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala index a7bc7f027517..1037ba02a0f2 100644 --- a/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala +++ b/compiler/src/dotty/tools/dotc/reporting/ErrorMessageID.scala @@ -187,6 +187,7 @@ enum ErrorMessageID(val isActive: Boolean = true) extends java.lang.Enum[ErrorMe case MissingArgumentID // errorNumer 171 case MissingImplicitArgumentID // errorNumber 172 case CannotBeAccessedID // errorNumber 173 + case InlineGivenCannotBeFunctionID // errorNumber 174 def errorNumber = ordinal - 1 diff --git a/compiler/src/dotty/tools/dotc/reporting/messages.scala b/compiler/src/dotty/tools/dotc/reporting/messages.scala index a3356c1f7021..02e3ae41182c 100644 --- a/compiler/src/dotty/tools/dotc/reporting/messages.scala +++ b/compiler/src/dotty/tools/dotc/reporting/messages.scala @@ -2769,4 +2769,23 @@ extends ReferenceMsg(CannotBeAccessedID): i"$whatCanNot be accessed as a member of $pre$where.$whyNot" def explain(using Context) = "" +class InlineGivenCannotBeFunction()(using Context) +extends SyntaxMsg(InlineGivenCannotBeFunctionID): + def msg(using Context) = + i"""inline given alias cannot have a function value as right-hand side. + |Either drop `inline` or rewrite the given with an explicit `apply` method.""" + def explain(using Context) = + i"""A function value on the right-hand side of an inline given alias would expand to + |an anonymous class. Each application of the inline given would then create a + |fresh copy of that class, which can increase code size in surprising ways. + |For that reason, functions are disallowed as right hand sides of inline given aliases. + |You should either drop `inline` or rewrite to an explicit `apply` method. E.g. + | + | inline given Conversion[A, B] = x => x.toB // error + | + |should be re-formulated as + | + | inline given Conversion[A, B] with + | def apply(x: A) = x.toB + """ diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 1f6516cdfb1c..cc99aa71b2cb 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -2374,6 +2374,8 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer if sym.isInlineMethod then if StagingContext.level > 0 then report.error("inline def cannot be within quotes", sym.sourcePos) + if sym.is(Given) && ddef.rhs.isInstanceOf[untpd.Function] then + report.error(InlineGivenCannotBeFunction(), ddef.rhs.srcPos) val rhsToInline = PrepareInlineable.wrapRHS(ddef, tpt1, rhs1) PrepareInlineable.registerInlineInfo(sym, rhsToInline) diff --git a/tests/neg-macros/i11483/Macro_1.scala b/tests/neg-macros/i11483/Macro_1.scala index 5def3025abe4..26d23162285a 100644 --- a/tests/neg-macros/i11483/Macro_1.scala +++ b/tests/neg-macros/i11483/Macro_1.scala @@ -17,8 +17,8 @@ trait CpsMonad[F[_]]: @compileTimeOnly("await should be inside async block") def await[F[_],T](f:F[T])(using am:CpsMonad[F]):T = ??? -inline given conversion[F[_],T](using CpsMonad[F]): Conversion[F[T],T] = - x => await(x) +inline given conversion[F[_],T](using CpsMonad[F]): Conversion[F[T],T] with + inline def apply(x: F[T]) = await(x) object X { diff --git a/tests/neg/inline-givens.scala b/tests/neg/inline-givens.scala new file mode 100644 index 000000000000..1d2a84b37931 --- /dev/null +++ b/tests/neg/inline-givens.scala @@ -0,0 +1,9 @@ + +class Item(x: String) + +inline given a: Conversion[String, Item] = + Item(_) // error + +inline given b: Conversion[String, Item] with + def apply(x: String) = Item(x) + diff --git a/tests/pos/i13900.scala b/tests/pos/i13900.scala index e6197d7f3f33..b599de283cb8 100644 --- a/tests/pos/i13900.scala +++ b/tests/pos/i13900.scala @@ -3,8 +3,8 @@ import scala.annotation.targetName opaque type Inlined[T] = T object Inlined: extension [T](inlined: Inlined[T]) def value: T = inlined - inline given fromValue[T <: Singleton]: Conversion[T, Inlined[T]] = - value => value + inline given fromValue[T <: Singleton]: Conversion[T, Inlined[T]] with + def apply(value: T) = value @targetName("fromValueWide") given fromValue[Wide]: Conversion[Wide, Inlined[Wide]] = value => value diff --git a/tests/pos/i8276.scala b/tests/pos/i8276.scala index e68cf009bc33..acb68e2e51a1 100644 --- a/tests/pos/i8276.scala +++ b/tests/pos/i8276.scala @@ -1,6 +1,7 @@ object NOTHING -inline given [A]: Conversion[NOTHING.type, Option[A]] = _ => None +inline given [A]: Conversion[NOTHING.type, Option[A]] with + def apply(x: NOTHING.type) = None def apply[A](p: Vector[A], o: Option[A] = NOTHING): Unit = ???