@@ -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,51 @@ object Annotations {
106108 go(metaSyms) || orNoneOf.nonEmpty && ! go(orNoneOf)
107109 }
108110
111+ /** Checks if this annotation can be used as a type annotation. Reports one
112+ * or more errors if it cannot.
113+ */
114+ final def checkValidTypeAnnotation ()(using Context ): Unit =
115+ def isTupleModule (sym : Symbol ): Boolean =
116+ ctx.definitions.isTupleClass(sym.companionClass)
117+
118+ def isFunctionAllowed (t : Tree ): Boolean =
119+ t match
120+ case Select (qual, nme.apply) => qual.symbol == defn.ArrayModule || isTupleModule(qual.symbol)
121+ case TypeApply (fun, _) => isFunctionAllowed(fun)
122+ case _ => false
123+
124+ def check (t : Tree ): Boolean =
125+ t match
126+ case Literal (_) => true
127+ case Apply (fun, args) => isFunctionAllowed(fun) && args.forall(check)
128+ case SeqLiteral (elems, _) => elems.forall(check)
129+ case Typed (expr, _) => check(expr)
130+ case NamedArg (_, arg) => check(arg)
131+ case _ =>
132+ t.tpe.stripped match
133+ case _ : SingletonType => true
134+ // We need to handle type refs for these test cases:
135+ // - tests/pos/dependent-annot.scala
136+ // - tests/pos/i16208.scala
137+ // - tests/run/java-ann-super-class
138+ // - tests/run/java-ann-super-class-separate
139+ // - tests/neg/i19470.scala (@retains)
140+ // Why do we get type refs in these cases?
141+ case _ : TypeRef => true
142+ case _ : TypeParamRef => true
143+ case tp => false
144+
145+ val uncheckedAnnots = Set [Symbol ](defn.RetainsAnnot , defn.RetainsByNameAnnot )
146+ if uncheckedAnnots(symbol) then return
147+
148+ for arg <- arguments if ! check(arg) do
149+ report.error(
150+ s """ Implementation restriction: not a valid type annotation argument.
151+ | Argument: $arg
152+ | Type: ${arg.tpe}""" .stripMargin, arg.srcPos)
153+
154+ ()
155+
109156 /** Operations for hash-consing, can be overridden */
110157 def hash : Int = System .identityHashCode(this )
111158 def eql (that : Annotation ) = this eq that
0 commit comments