diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index faf420fcc44c..bd719733be97 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1235,18 +1235,31 @@ object desugar { rhsOK(rhs) } + def checkOpaqueAlias(tree: MemberDef)(using Context): MemberDef = + def check(rhs: Tree): MemberDef = rhs match + case bounds: TypeBoundsTree if bounds.alias.isEmpty => + report.error(i"opaque type must have a right-hand side", tree.srcPos) + tree.withMods(tree.mods.withoutFlags(Opaque)) + case LambdaTypeTree(_, body) => check(body) + case _ => tree + if !tree.mods.is(Opaque) then tree + else tree match + case TypeDef(_, rhs) => check(rhs) + case _ => tree + /** Check that modifiers are legal for the definition `tree`. * Right now, we only check for `opaque`. TODO: Move other modifier checks here. */ def checkModifiers(tree: Tree)(using Context): Tree = tree match { case tree: MemberDef => var tested: MemberDef = tree - def checkApplicable(flag: Flag, test: MemberDefTest): Unit = + def checkApplicable(flag: Flag, test: MemberDefTest): MemberDef = if (tested.mods.is(flag) && !test.applyOrElse(tree, (md: MemberDef) => false)) { report.error(ModifierNotAllowedForDefinition(flag), tree.srcPos) - tested = tested.withMods(tested.mods.withoutFlags(flag)) - } - checkApplicable(Opaque, legalOpaque) + tested.withMods(tested.mods.withoutFlags(flag)) + } else tested + tested = checkOpaqueAlias(tested) + tested = checkApplicable(Opaque, legalOpaque) tested case _ => tree diff --git a/tests/neg/i15266.check b/tests/neg/i15266.check new file mode 100644 index 000000000000..7c525a132c90 --- /dev/null +++ b/tests/neg/i15266.check @@ -0,0 +1,8 @@ +-- [E156] Syntax Error: tests/neg/i15266.scala:5:13 -------------------------------------------------------------------- +5 |opaque class A // error + |^^^^^^^^^^^^^^ + |Modifier opaque is not allowed for this definition +-- Error: tests/neg/i15266.scala:1:12 ---------------------------------------------------------------------------------- +1 |opaque type Type0 // error + |^^^^^^^^^^^^^^^^^ + |opaque type must have a right-hand side diff --git a/tests/neg/i15266.scala b/tests/neg/i15266.scala new file mode 100644 index 000000000000..42c6c45958c3 --- /dev/null +++ b/tests/neg/i15266.scala @@ -0,0 +1,5 @@ +opaque type Type0 // error +opaque type Type1 = Int +opaque type Type2 <: Int = 2 +opaque type Type3 >: 3 <: Int = 3 +opaque class A // error diff --git a/tests/neg/i6055.check b/tests/neg/i6055.check new file mode 100644 index 000000000000..4a96cda73c90 --- /dev/null +++ b/tests/neg/i6055.check @@ -0,0 +1,16 @@ +-- Error: tests/neg/i6055.scala:1:12 ----------------------------------------------------------------------------------- +1 |opaque type i0 // error: opaque type must have a right-hand side + |^^^^^^^^^^^^^^ + |opaque type must have a right-hand side +-- Error: tests/neg/i6055.scala:2:12 ----------------------------------------------------------------------------------- +2 |opaque type i2 <: Int // error: opaque type must have a right-hand side + |^^^^^^^^^^^^^^^^^^^^^ + |opaque type must have a right-hand side +-- Error: tests/neg/i6055.scala:4:12 ----------------------------------------------------------------------------------- +4 |opaque type i1[_] // error: opaque type must have a right-hand side + |^^^^^^^^^^^^^^^^^ + |opaque type must have a right-hand side +-- Error: tests/neg/i6055.scala:5:12 ----------------------------------------------------------------------------------- +5 |opaque type x[_] <: Int // error: opaque type must have a right-hand side + |^^^^^^^^^^^^^^^^^^^^^^^ + |opaque type must have a right-hand side diff --git a/tests/neg/i6055.scala b/tests/neg/i6055.scala index 4c7905e581f6..612906cda78e 100644 --- a/tests/neg/i6055.scala +++ b/tests/neg/i6055.scala @@ -1,5 +1,5 @@ -opaque type i0 // error: opaque type must be an alias type -opaque type i2 <: Int // error: opaque type must be an alias type +opaque type i0 // error: opaque type must have a right-hand side +opaque type i2 <: Int // error: opaque type must have a right-hand side -opaque type i1[_] // error: opaque type must be an alias type -opaque type x[_] <: Int // error: opaque type must be an alias type +opaque type i1[_] // error: opaque type must have a right-hand side +opaque type x[_] <: Int // error: opaque type must have a right-hand side