@@ -3,6 +3,8 @@ package dotc
33package core
44
55import Symbols .* , Types .* , Contexts .* , Constants .* , Phases .*
6+ import Decorators .i
7+ import StdNames .nme
68import ast .tpd , tpd .*
79import util .Spans .Span
810import printing .{Showable , Printer }
@@ -106,6 +108,54 @@ object Annotations {
106108 go(metaSyms) || orNoneOf.nonEmpty && ! go(orNoneOf)
107109 }
108110
111+ /** True if this annotation can be used as a type annotation, false otherwise.
112+ *
113+ * An annotation is a valid type annotation if its tree is one a `Literal`.
114+ *
115+ * Can be overridden.
116+ */
117+ def checkValidTypeAnnotation ()(using Context ): Unit =
118+ def isTupleModule (sym : Symbol ): Boolean =
119+ ctx.definitions.isTupleClass(sym.companionClass)
120+
121+ def isFunctionAllowed (t : Tree ): Boolean =
122+ t match
123+ case Select (qual, nme.apply) => qual.symbol == defn.ArrayModule || isTupleModule(qual.symbol)
124+ case TypeApply (fun, _) => isFunctionAllowed(fun)
125+ case _ => false
126+
127+ def check (t : Tree ): Boolean =
128+ t match
129+ case Literal (_) => true
130+ case Typed (expr, _) => check(expr)
131+ case SeqLiteral (elems, _) => elems.forall(check)
132+ case Apply (fun, args) => isFunctionAllowed(fun) && args.forall(check)
133+ case NamedArg (_, arg) => check(arg)
134+ case _ =>
135+ t.tpe.stripped match
136+ case _ : SingletonType => true
137+ // We need to handle type refs for these test cases:
138+ // - tests/pos/dependent-annot.scala
139+ // - tests/pos/i16208.scala
140+ // - tests/run/java-ann-super-class.scala
141+ // - tests/run/java-ann-super-class-separate.scala
142+ // - tests/neg/i19470.scala (@retains)
143+ // Why do we get type refs in these cases?
144+ case _ : TypeRef => true
145+ case _ : TypeParamRef => true
146+ case tp => false
147+
148+ val uncheckedAnnots = Set [Symbol ](defn.RetainsAnnot , defn.RetainsByNameAnnot )
149+ if uncheckedAnnots(symbol) then return
150+
151+ for arg <- arguments if ! check(arg) do
152+ report.error(
153+ s """ Implementation restriction: not a valid type annotation argument.
154+ | Argument: $arg
155+ | Type: ${arg.tpe}""" .stripMargin, arg.srcPos)
156+
157+ ()
158+
109159 /** Operations for hash-consing, can be overridden */
110160 def hash : Int = System .identityHashCode(this )
111161 def eql (that : Annotation ) = this eq that
0 commit comments