diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index c402f4aafccf..7cb144adb025 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -315,7 +315,10 @@ object Checking { fail(AbstractMemberMayNotHaveModifier(sym, flag)) def checkNoConflict(flag1: FlagSet, flag2: FlagSet) = if (sym.is(allOf(flag1, flag2))) - fail(i"illegal combination of modifiers: $flag1 and $flag2 for: $sym") + fail(i"illegal combination of modifiers: `$flag1` and `$flag2` for: $sym") + def checkApplicable(flag: FlagSet, ok: Boolean) = + if (!ok && !sym.is(Synthetic)) + fail(i"modifier `$flag` is not allowed for this definition") if (sym.is(ImplicitCommon)) { if (sym.owner.is(Package)) @@ -345,6 +348,9 @@ object Checking { checkNoConflict(Final, Sealed) checkNoConflict(Private, Protected) checkNoConflict(Abstract, Override) + checkNoConflict(Lazy, Inline) + if (sym.is(Inline)) checkApplicable(Inline, sym.isTerm && !sym.is(Mutable | Module)) + if (sym.is(Lazy)) checkApplicable(Lazy, !sym.is(Method | Mutable)) if (sym.isType && !sym.is(Deferred)) for (cls <- sym.allOverriddenSymbols.filter(_.isClass)) { fail(CannotHaveSameNameAs(sym, cls, CannotHaveSameNameAs.CannotBeOverridden)) diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala index 74cfffbcd6a1..5038007b4ec0 100644 --- a/compiler/src/dotty/tools/dotc/typer/Namer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala @@ -243,6 +243,10 @@ class Namer { typer: Typer => def privateWithinClass(mods: Modifiers) = enclosingClassNamed(mods.privateWithin, mods.pos) + /** Check that flags are OK for symbol. This is done early to avoid + * catastrophic failure when we create a TermSymbol with TypeFlags, or vice versa. + * A more complete check is done in checkWellformed. + */ def checkFlags(flags: FlagSet) = if (flags.isEmpty) flags else { diff --git a/tests/neg/i2421.scala b/tests/neg/i2421.scala new file mode 100644 index 000000000000..c09da6a8a3f2 --- /dev/null +++ b/tests/neg/i2421.scala @@ -0,0 +1,10 @@ +inline object Foo // error: modifier(s) `inline' incompatible with type definition +inline class Bar // error: modifier(s) `inline' incompatible with type definition +inline abstract class Baz // error: modifier(s) `inline' incompatible with type definition +inline trait Qux // error: modifier(s) `inline' incompatible with type definition + +object Quux { + inline type T // error: modifier(s) `inline' incompatible with type definition + inline var x: Int = 42 // error: modifier(s) `inline' incompatible with var definition + inline lazy val y: Int = 43 // error: modifier(s) `inline' incompatible with lazy val definition +} diff --git a/tests/neg/i2712.scala b/tests/neg/i2712.scala new file mode 100644 index 000000000000..59fb0a1ebf14 --- /dev/null +++ b/tests/neg/i2712.scala @@ -0,0 +1,12 @@ +object Foo { + lazy var x: Int = 42 // error: modifier(s) `lazy' incompatible with var definition + lazy def y: Int = 42 // error: modifier(s) `lazy' incompatible with def definition +} + +lazy class Bar // error: modifier(s) `lazy' incompatible with type definition +lazy abstract class Baz // error: modifier(s) `lazy abstract' incompatible with type definition +lazy trait Qux // error: modifier(s) `lazy' not allowed for trait + +object Quux { + lazy type T // error: modifier(s) `lazy' incompatible with type definition +}