Skip to content

Commit 9d8aa71

Browse files
committed
Base implementation on internal alias type
Base implementation on internal alias type instead of annotation. This makes convertibleTo handling unforgeable. It also avoids the need to create a new class.
1 parent 0f113da commit 9d8aa71

File tree

8 files changed

+30
-25
lines changed

8 files changed

+30
-25
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,9 @@ class Definitions {
615615

616616
@tu lazy val RepeatedParamClass: ClassSymbol = enterSpecialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, Seq(ObjectType, SeqType))
617617

618+
@tu lazy val ConvertibleToType: TypeSymbol = enterAliasType(
619+
tpnme.CONVERTIBLE_TO, HKTypeLambda(TypeBounds.empty :: Nil)(_.paramRefs(0)))
620+
618621
// fundamental classes
619622
@tu lazy val StringClass: ClassSymbol = requiredClass("java.lang.String")
620623
def StringType: Type = StringClass.typeRef
@@ -902,7 +905,6 @@ class Definitions {
902905
@tu lazy val BodyAnnot: ClassSymbol = requiredClass("scala.annotation.internal.Body")
903906
@tu lazy val ChildAnnot: ClassSymbol = requiredClass("scala.annotation.internal.Child")
904907
@tu lazy val ContextResultCountAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ContextResultCount")
905-
@tu lazy val ConvertibleAnnot: ClassSymbol = requiredClass("scala.annotation.internal.$convertible")
906908
@tu lazy val ProvisionalSuperClassAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ProvisionalSuperClass")
907909
@tu lazy val DeprecatedAnnot: ClassSymbol = requiredClass("scala.deprecated")
908910
@tu lazy val ImplicitAmbiguousAnnot: ClassSymbol = requiredClass("scala.annotation.implicitAmbiguous")
@@ -1816,6 +1818,7 @@ class Definitions {
18161818
orType,
18171819
RepeatedParamClass,
18181820
ByNameParamClass2x,
1821+
ConvertibleToType,
18191822
AnyValClass,
18201823
NullClass,
18211824
NothingClass,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ object StdNames {
286286
val COMPANION: N = "<companion>"
287287
val CONSTRUCTOR: N = "<init>"
288288
val STATIC_CONSTRUCTOR: N = "<clinit>"
289+
val CONVERTIBLE_TO: N = "<convertible-to>"
289290
val DEFAULT_CASE: N = "defaultCase$"
290291
val EVT2U: N = "evt2u$"
291292
val EQEQ_LOCAL_VAR: N = "eqEqTemp$"
@@ -453,7 +454,6 @@ object StdNames {
453454
val common: N = "common"
454455
val compiletime : N = "compiletime"
455456
val conforms_ : N = "$conforms"
456-
val convertible_ : N = "$convertible"
457457
val convertibleTo: N = "convertibleTo"
458458
val copy: N = "copy"
459459
val currentMirror: N = "currentMirror"

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

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,10 @@ object Types {
401401
def isRepeatedParam(using Context): Boolean =
402402
typeSymbol eq defn.RepeatedParamClass
403403

404+
/** Is this a parameter type that allows implicit argument converson? */
405+
def isConvertibleParam(using Context): Boolean =
406+
typeSymbol eq defn.ConvertibleToType
407+
404408
/** Is this the type of a method that has a repeated parameter type as
405409
* last parameter type?
406410
*/
@@ -3779,23 +3783,26 @@ object Types {
37793783
* - add @$convertibe to parameters that have an @allowConversions annotation
37803784
*/
37813785
def fromSymbols(params: List[Symbol], resultType: Type)(using Context): MethodType =
3782-
def addAnnotation(tp: Type, cls: ClassSymbol, underStar: Boolean): Type = tp match
3786+
def addAnnotation(tp: Type, cls: ClassSymbol): Type = tp match
3787+
case ExprType(resType) => ExprType(addAnnotation(resType, cls))
3788+
case _ => AnnotatedType(tp, Annotation(cls))
3789+
3790+
def addConvertibleTo(tp: Type): Type = tp match
37833791
case ExprType(resType) =>
3784-
ExprType(addAnnotation(resType, cls, underStar))
3785-
case tp @ AppliedType(tycon, arg :: Nil)
3786-
if tycon.typeSymbol == defn.RepeatedParamClass && underStar =>
3787-
tp.derivedAppliedType(tycon, addAnnotation(arg, cls, underStar) :: Nil)
3792+
ExprType(addConvertibleTo(resType))
3793+
case tp @ AppliedType(tycon, arg :: Nil) if tycon.typeSymbol == defn.RepeatedParamClass =>
3794+
tp.derivedAppliedType(tycon, addConvertibleTo(arg) :: Nil)
37883795
case _ =>
3789-
AnnotatedType(tp, Annotation(cls))
3796+
AppliedType(defn.ConvertibleToType.typeRef, tp :: Nil)
37903797

37913798
def paramInfo(param: Symbol) =
37923799
var paramType = param.info.annotatedToRepeated
37933800
if param.is(Inline) then
3794-
paramType = addAnnotation(paramType, defn.InlineParamAnnot, underStar = false)
3801+
paramType = addAnnotation(paramType, defn.InlineParamAnnot)
37953802
if param.is(Erased) then
3796-
paramType = addAnnotation(paramType, defn.ErasedParamAnnot, underStar = false)
3803+
paramType = addAnnotation(paramType, defn.ErasedParamAnnot)
37973804
if param.hasAnnotation(defn.AllowConversionsAnnot) then
3798-
paramType = addAnnotation(paramType, defn.ConvertibleAnnot, underStar = true)
3805+
paramType = addConvertibleTo(paramType)
37993806
paramType
38003807

38013808
apply(params.map(_.name.asTermName))(

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
219219
case tp @ AppliedType(tycon, args) =>
220220
val cls = tycon.typeSymbol
221221
if tycon.isRepeatedParam then toTextLocal(args.head) ~ "*"
222+
else if tp.isConvertibleParam then "convertibleTo " ~ toText(args.head)
222223
else if defn.isFunctionClass(cls) then toTextFunction(args, cls.name.isContextFunction, cls.name.isErasedFunction)
223224
else if tp.tupleArity >= 2 && !printDebug then toTextTuple(tp.tupleElementTypes)
224225
else if isInfixType(tp) then

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -927,13 +927,10 @@ trait Checking {
927927
*/
928928
def checkImplicitConversionUseOK(tree: Tree, expected: Type)(using Context): Unit =
929929
val sym = tree.symbol
930-
def isConvertibleParam(tp: Type) = tp match
931-
case AnnotatedType(_, annot) => annot.symbol == defn.ConvertibleAnnot
932-
case _ => false
933930
if sym.name == nme.apply
934931
&& sym.owner.derivesFrom(defn.ConversionClass)
935932
&& !sym.info.isErroneous
936-
&& !isConvertibleParam(expected)
933+
&& !expected.isConvertibleParam
937934
then
938935
def conv = methPart(tree) match
939936
case Select(qual, _) => qual.symbol.orElse(sym.owner)

library/src/scala/annotation/internal/$convertible.scala

Lines changed: 0 additions & 7 deletions
This file was deleted.

project/MiMaFilters.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ object MiMaFilters {
1717
ProblemFilters.exclude[MissingClassProblem]("scala.compiletime.ops.long$"),
1818
ProblemFilters.exclude[ReversedMissingMethodProblem]("scala.quoted.Quotes#reflectModule#CompilationInfoModule.XmacroSettings"),
1919
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.quoted.Quotes#reflectModule#CompilationInfoModule.XmacroSettings"),
20+
ProblemFilters.exclude[MissingClassProblem]("scala.annotation.allowConversions"),
2021

2122
// Private to the compiler - needed for forward binary compatibility
2223
ProblemFilters.exclude[MissingClassProblem]("scala.annotation.since")

tests/run/Parser.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ class ParserOps[T](p: Parser[T]):
2828
case Success(x, in1) => Success(f(x), in1)
2929
case fail: Failure => fail
3030
)
31+
def ~> [U](q: => convertibleTo Parser[U]): Parser[U] =
32+
(p ~ q).map(_(1))
33+
def <~ [U](q: => convertibleTo Parser[U]): Parser[T] =
34+
(p ~ q).map(_(0))
3135
def parseAll(in: Input): ParseResult[T] =
3236
p.parse(in) match
3337
case succ @ Success(x, in1) =>
@@ -80,12 +84,11 @@ def Expr: Parser[Double] =
8084
def Term: Parser[Double] =
8185
(Factor ~ rep("*" ~ Factor | "/" ~ Factor)).map(reduce)
8286
def Factor: Parser[Double] =
83-
Number
84-
| ("(" ~ Expr ~ ")").map{ case "(" ~~ e ~~ ")" => e }
87+
Number | "(" ~> Expr <~ ")"
8588
def Number: Parser[Double] =
8689
token(_.toDoubleOption.isDefined, "number").map(_.toDouble)
8790

88-
def ops: Parser[String] = "+" | "-"
91+
def ops: Parser[String] = "+" | "-" | "*" | "/"
8992

9093
@main def Test =
9194
println(Expr.parseAll("2 * ( 3 + 4 - 2 / 1 )".split(" ").toList))

0 commit comments

Comments
 (0)