From fa64f179155efcc906ee6233e34a1ef42babe8df Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 24 May 2022 18:27:24 +0200 Subject: [PATCH 1/2] Improve opaque type with no RHS error message Fixes #15266 --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 17 +++++++++++++---- tests/neg/i15266.check | 8 ++++++++ tests/neg/i15266.scala | 5 +++++ 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 tests/neg/i15266.check create mode 100644 tests/neg/i15266.scala diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index faf420fcc44c..1e40ece0d1f2 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1235,18 +1235,27 @@ object desugar { rhsOK(rhs) } + def checkOpaqueAlias(tree: MemberDef)(using Context): MemberDef = + if !tree.mods.is(Opaque) then tree + else tree match + case TypeDef(_, 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 _ => 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 From bccacaf0a2b76e6849487c292084e1ce6680813d Mon Sep 17 00:00:00 2001 From: Tom Grigg Date: Tue, 24 May 2022 15:21:57 -0700 Subject: [PATCH 2/2] Check for missing RHS of higher-kinded opaque types --- compiler/src/dotty/tools/dotc/ast/Desugar.scala | 10 +++++++--- tests/neg/i6055.check | 16 ++++++++++++++++ tests/neg/i6055.scala | 8 ++++---- 3 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 tests/neg/i6055.check diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala index 1e40ece0d1f2..bd719733be97 100644 --- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala +++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala @@ -1236,11 +1236,15 @@ object desugar { } def checkOpaqueAlias(tree: MemberDef)(using Context): MemberDef = - if !tree.mods.is(Opaque) then tree - else tree match - case TypeDef(_, bounds: TypeBoundsTree) if bounds.alias.isEmpty => + 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`. 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