Skip to content

Commit 9c18a70

Browse files
committed
Handle abstract givens
Add tests for them. Also, improve error message if a given instance still has abstract members.
1 parent 3692b22 commit 9c18a70

File tree

8 files changed

+59
-6
lines changed

8 files changed

+59
-6
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,10 +800,12 @@ object desugar {
800800
Nil
801801
}
802802
}
803+
val classMods = if mods.is(Given) then mods &~ Given | Synthetic else mods
803804
cpy.TypeDef(cdef: TypeDef)(
804805
name = className,
805806
rhs = cpy.Template(impl)(constr, parents1, clsDerived, self1,
806-
tparamAccessors ::: vparamAccessors ::: normalizedBody ::: caseClassMeths)): TypeDef
807+
tparamAccessors ::: vparamAccessors ::: normalizedBody ::: caseClassMeths)
808+
).withMods(classMods)
807809
}
808810

809811
// install the watch on classTycon

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ object Checking {
443443
fail(ParamsNoInline(sym.owner))
444444
if sym.isInlineMethod && !sym.is(Deferred) && sym.allOverriddenSymbols.nonEmpty then
445445
checkInlineOverrideParameters(sym)
446-
if (sym.isOneOf(GivenOrImplicit)) {
446+
if (sym.is(Implicit)) {
447447
if (sym.owner.is(Package))
448448
fail(TopLevelCantBeImplicit(sym))
449449
if (sym.isType)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ class Namer { typer: Typer =>
241241

242242
tree match {
243243
case tree: TypeDef if tree.isClassDef =>
244-
val flags = checkFlags(tree.mods.flags &~ GivenOrImplicit)
244+
val flags = checkFlags(tree.mods.flags &~ Implicit)
245245
val name = checkNoConflict(tree.name, flags.is(Private), tree.span).asTypeName
246246
val cls =
247247
createOrRefine[ClassSymbol](tree, name, flags, ctx.owner,

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,9 @@ object RefChecks {
503503
def prelude = (
504504
if (clazz.isAnonymousClass || clazz.is(Module)) "object creation impossible"
505505
else if (mustBeMixin) s"$clazz needs to be a mixin"
506-
else s"$clazz needs to be abstract") + ", since"
506+
else if clazz.is(Synthetic) then "instance cannot be created"
507+
else s"$clazz needs to be abstract"
508+
) + ", since"
507509

508510
if (abstractErrors.isEmpty) abstractErrors ++= List(prelude, msg)
509511
else abstractErrors += msg

tests/neg/abstract-givens.check

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
-- Error: tests/neg/abstract-givens.scala:11:8 -------------------------------------------------------------------------
2+
11 | given s[T](using T): Seq[T] with // error
3+
| ^
4+
| instance cannot be created, since def iterator: => Iterator[A] is not defined
5+
-- Error: tests/neg/abstract-givens.scala:8:8 --------------------------------------------------------------------------
6+
8 | given y(using Int): String = summon[Int].toString * 22 // error
7+
| ^
8+
| error overriding method y in trait T of type (using x$1: Int): String;
9+
| method y of type (using x$1: Int): String cannot override final member method y in trait T
10+
-- Error: tests/neg/abstract-givens.scala:9:8 --------------------------------------------------------------------------
11+
9 | given z[T](using T): Seq[T] = List(summon[T]) // error
12+
| ^
13+
| error overriding method z in trait T of type [T](using x$1: T): List[T];
14+
| method z of type [T](using x$1: T): Seq[T] has incompatible type

tests/neg/abstract-givens.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait T:
2+
given x: Int
3+
given y(using Int): String = summon[Int].toString
4+
given z[T](using T): List[T]
5+
6+
object Test extends T:
7+
given x: Int = 22
8+
given y(using Int): String = summon[Int].toString * 22 // error
9+
given z[T](using T): Seq[T] = List(summon[T]) // error
10+
11+
given s[T](using T): Seq[T] with // error
12+
def apply(x: Int) = ???
13+
override def length = ???
14+
15+
end Test
16+

tests/neg/struct-given.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
class C
2-
given c as C with
2+
given c[T]: C with
33
def foo = 1
44

5-
given d as C = new C { def foo = 1 }
5+
given d[T]: C = new C { def foo = 1 }
66

77
def test =
88
c.foo // OK

tests/run/abstract-givens.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
trait T:
2+
given x: Int
3+
given y(using Int): String
4+
given z[T](using T): Seq[T]
5+
6+
object Test extends T, App:
7+
given x: Int = 22
8+
override given y(using Int): String = summon[Int].toString
9+
given z[T](using T): Seq[T] with
10+
override def apply(x: Int) = ???
11+
override def length = ???
12+
override def iterator = ???
13+
override def toString = s"seq $x"
14+
15+
assert(summon[Int] == 22)
16+
assert(summon[String] == "22")
17+
assert(summon[Seq[Int]].toString == "seq 22")
18+
19+

0 commit comments

Comments
 (0)