diff options
author | Martin Odersky <odersky@gmail.com> | 2015-10-21 17:49:27 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-10-22 12:21:26 +0200 |
commit | f1b3859911ee04a90a0b169c5eefa2c64ce5d265 (patch) | |
tree | 0d8d90bc89d62a83c7bd1395ecac1e43f922bd09 /src/dotty/tools/dotc/typer/Checking.scala | |
parent | 54f5899b0888983495f5ff70f561d9634350f3f2 (diff) | |
download | dotty-f1b3859911ee04a90a0b169c5eefa2c64ce5d265.tar.gz dotty-f1b3859911ee04a90a0b169c5eefa2c64ce5d265.tar.bz2 dotty-f1b3859911ee04a90a0b169c5eefa2c64ce5d265.zip |
Add well-formedness checking for created symbols
Enforces various restrictions of definitions.
Diffstat (limited to 'src/dotty/tools/dotc/typer/Checking.scala')
-rw-r--r-- | src/dotty/tools/dotc/typer/Checking.scala | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index 8f4a8b72b..1c0274c84 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -230,6 +230,49 @@ object Checking { } checkTree((), refinement) } + + /** Check that symbol's definition is well-formed. */ + def checkWellFormed(sym: Symbol)(implicit ctx: Context): Unit = { + //println(i"check wf $sym with flags ${sym.flags}") + def fail(msg: String) = ctx.error(msg, sym.pos) + def varNote = + if (sym.is(Mutable)) "\n(Note that variables need to be initialized to be defined)" + else "" + + def checkWithDeferred(flag: FlagSet) = + if (sym.is(flag)) + fail(i"abstract member may not have `$flag' modifier") + def checkNoConflict(flag1: FlagSet, flag2: FlagSet) = + if (sym.is(allOf(flag1, flag2))) + fail(i"illegal combination of modifiers: $flag1 and $flag2 for: $sym") + + if (sym.is(ImplicitCommon)) { + if (sym.owner.is(Package)) + fail(i"`implicit' modifier cannot be used for top-level definitions") + if (sym.isType) + fail(i"`implicit' modifier cannot be used for types or traits") + } + if (!sym.isClass && sym.is(Abstract)) + fail(i"`abstract' modifier can be used only for classes; it should be omitted for abstract members") + if (sym.is(AbsOverride) && !sym.owner.is(Trait)) + fail(i"`abstract override' modifier only allowed for members of traits") + if (sym.is(Trait) && sym.is(Final)) + fail(i"$sym may not be `final'") + if (sym.hasAnnotation(defn.NativeAnnot)) + if (sym.is(Deferred)) sym.resetFlag(Deferred) + else fail(i"`@native' members may not have implementation") + if (sym.is(Deferred, butNot = Param) && !sym.isSelfSym) { + if (!sym.owner.isClass || sym.owner.is(Module) || sym.owner.isAnonymousClass) + fail(i"only classes can have declared but undefined members$varNote") + checkWithDeferred(Private) + checkWithDeferred(Final) + } + if (sym.isValueClass && sym.is(Trait) && !sym.isRefinementClass) + fail(i"$sym cannot extend AnyVal") + checkNoConflict(Final, Sealed) + checkNoConflict(Private, Protected) + checkNoConflict(Abstract, Override) + } } trait Checking { |