diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 70eebc750521..5361bce972da 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -890,6 +890,7 @@ class Definitions { @tu lazy val ImplicitAmbiguousAnnot: ClassSymbol = requiredClass("scala.annotation.implicitAmbiguous") @tu lazy val ImplicitNotFoundAnnot: ClassSymbol = requiredClass("scala.annotation.implicitNotFound") @tu lazy val InlineParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InlineParam") + @tu lazy val ErasedParamAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ErasedParam") @tu lazy val InvariantBetweenAnnot: ClassSymbol = requiredClass("scala.annotation.internal.InvariantBetween") @tu lazy val MainAnnot: ClassSymbol = requiredClass("scala.main") @tu lazy val MigrationAnnot: ClassSymbol = requiredClass("scala.annotation.migration") diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index f9cbf932f9c8..d0a536b92d13 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -3640,9 +3640,15 @@ object Types { case ExprType(resType) => ExprType(AnnotatedType(resType, Annotation(defn.InlineParamAnnot))) case _ => AnnotatedType(tp, Annotation(defn.InlineParamAnnot)) } + def translateErased(tp: Type): Type = tp match { + case ExprType(resType) => ExprType(AnnotatedType(resType, Annotation(defn.ErasedParamAnnot))) + case _ => AnnotatedType(tp, Annotation(defn.ErasedParamAnnot)) + } def paramInfo(param: Symbol) = { - val paramType = param.info.annotatedToRepeated - if (param.is(Inline)) translateInline(paramType) else paramType + var paramType = param.info.annotatedToRepeated + if (param.is(Inline)) paramType = translateInline(paramType) + if (param.is(Erased)) paramType = translateErased(paramType) + paramType } apply(params.map(_.name.asTermName))( diff --git a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala index 618f7be6dac3..7841d1a06cc6 100644 --- a/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -219,7 +219,7 @@ class PlainPrinter(_ctx: Context) extends Printer { toTextGlobal(tp.resultType) } case AnnotatedType(tpe, annot) => - if annot.symbol == defn.InlineParamAnnot then toText(tpe) + if annot.symbol == defn.InlineParamAnnot || annot.symbol == defn.ErasedParamAnnot then toText(tpe) else toTextLocal(tpe) ~ " " ~ toText(annot) case tp: TypeVar => if (tp.isInstantiated) diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala index d5893f44f631..0c0de55daa58 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala @@ -467,6 +467,8 @@ class Inliner(call: tpd.Tree, rhsToInline: tpd.Tree)(using Context) { var bindingFlags: FlagSet = InlineProxy if formal.widenExpr.hasAnnotation(defn.InlineParamAnnot) then bindingFlags |= Inline + if formal.widenExpr.hasAnnotation(defn.ErasedParamAnnot) then + bindingFlags |= Erased if isByName then bindingFlags |= Method val boundSym = newSym(InlineBinderName.fresh(name.asTermName), bindingFlags, bindingType).asTerm diff --git a/library/src/scala/annotation/internal/ErasedParam.scala b/library/src/scala/annotation/internal/ErasedParam.scala new file mode 100644 index 000000000000..8145712a52da --- /dev/null +++ b/library/src/scala/annotation/internal/ErasedParam.scala @@ -0,0 +1,6 @@ +package scala.annotation.internal + +import scala.annotation.Annotation + +/** An annotation produced by Namer to indicate an erased parameter */ +final class ErasedParam() extends Annotation diff --git a/library/src/scala/annotation/internal/TransparentParam.scala b/library/src/scala/annotation/internal/InlineParam.scala similarity index 100% rename from library/src/scala/annotation/internal/TransparentParam.scala rename to library/src/scala/annotation/internal/InlineParam.scala diff --git a/tests/run-custom-args/erased/i11996.scala b/tests/run-custom-args/erased/i11996.scala new file mode 100644 index 000000000000..050d36370ef0 --- /dev/null +++ b/tests/run-custom-args/erased/i11996.scala @@ -0,0 +1,23 @@ +final class UnivEq[A] + +object UnivEq: + erased def force[A]: UnivEq[A] = + compiletime.erasedValue + +extension [A](a: A) + inline def ==*[B >: A](b: B)(using erased UnivEq[B]): Boolean = a == b + inline def !=*[B >: A](b: B)(using erased UnivEq[B]): Boolean = a != b + +case class I(i: Int) + +@main def Test = { + def test[A](a: A, b: A): Unit = { + erased given UnivEq[A] = UnivEq.force[A] + println(a ==* a) + println(a !=* b) + } + println("Test starting...") + test(I(1), I(2)) // error + test(1, 2) + test(true, false) +}