Skip to content

Commit 86acb56

Browse files
committed
Check @main annotations for applicability
Check applicability of annotations only once they are completed
1 parent 8b2737d commit 86acb56

File tree

4 files changed

+26
-14
lines changed

4 files changed

+26
-14
lines changed

compiler/src/dotty/tools/dotc/reporting/Reporter.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,14 @@ abstract class Reporter extends interfaces.ReporterResult {
250250
*/
251251
def errorsReported: Boolean = hasErrors
252252

253+
/** Run `op` and return `true` if errors were reported by this reporter.
254+
*/
255+
def reportsErrorsFor(op: given Context => Unit) given Context : Boolean = {
256+
val initial = errorCount
257+
op
258+
errorCount > initial
259+
}
260+
253261
private[this] var reportedFeaturesUseSites = Set[Symbol]()
254262

255263
def isReportedFeatureUseSite(featureTrait: Symbol): Boolean =

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,19 @@ trait Checking {
11361136
}
11371137
}
11381138

1139+
/** check that annotation `annot` is applicable to symbol `sym` */
1140+
def checkAnnotApplicable(annot: Tree, sym: Symbol) given (ctx: Context): Boolean =
1141+
!ctx.reporter.reportsErrorsFor {
1142+
val pos = annot.sourcePos
1143+
if (annot.symbol == defn.MainAnnot) {
1144+
if (!sym.isRealMethod)
1145+
ctx.error(em"@main annotation cannot be applied to $sym", pos)
1146+
if (!sym.owner.is(Module) || !sym.owner.isStatic)
1147+
ctx.error(em"$sym cannot be a @main method since it cannot be accessed statically", pos)
1148+
}
1149+
// TODO: Add more checks here
1150+
}
1151+
11391152
/** Check that symbol's external name does not clash with symbols defined in the same scope */
11401153
def checkNoAlphaConflict(stats: List[Tree])(implicit ctx: Context): Unit = {
11411154
var seen = Set[Name]()
@@ -1157,6 +1170,7 @@ trait ReChecking extends Checking {
11571170
override def checkEnum(cdef: untpd.TypeDef, cls: Symbol, firstParent: Symbol)(implicit ctx: Context): Unit = ()
11581171
override def checkRefsLegal(tree: tpd.Tree, badOwner: Symbol, allowed: (Name, Symbol) => Boolean, where: String)(implicit ctx: Context): Unit = ()
11591172
override def checkEnumCaseRefsLegal(cdef: TypeDef, enumCtx: Context)(implicit ctx: Context): Unit = ()
1173+
override def checkAnnotApplicable(annot: Tree, sym: Symbol) given (ctx: Context): Boolean = true
11601174
}
11611175

11621176
trait NoChecking extends ReChecking {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1458,7 +1458,8 @@ class Typer extends Namer
14581458
sym.annotations.foreach(_.ensureCompleted)
14591459
lazy val annotCtx = annotContext(mdef, sym)
14601460
// necessary in order to mark the typed ahead annotations as definitely typed:
1461-
untpd.modsDeco(mdef).mods.annotations.foreach(typedAnnotation(_)(annotCtx))
1461+
for annot <- untpd.modsDeco(mdef).mods.annotations do
1462+
checkAnnotApplicable(typedAnnotation(annot)(annotCtx), sym)
14621463
}
14631464

14641465
def typedAnnotation(annot: untpd.Tree)(implicit ctx: Context): Tree = track("typedAnnotation") {

tests/neg/main-functions.scala

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,4 @@
1+
class TC
12
object Test1 {
2-
@main def f(x: Foo) = () // error: no implicit argument of type util.FromString[Foo] was found
3+
@main def f(x: TC) = () // error: no implicit argument of type util.FromString[TC] was found
34
}
4-
5-
object Test2 {
6-
@main val x = 2 // does nothing, should this be made an error?
7-
}
8-
9-
class Foo {
10-
@main def f = () // does nothing, should this be made an error?
11-
}
12-
13-
@main def g(x: Int*)(y: Int*) = () // error: varargs parameter of @main method must come last
14-
15-
@main def h[T: util.FromString](x: T) = () // error: @main method cannot have type parameters

0 commit comments

Comments
 (0)