From eaac472be1355e796eb0e9e13179a2a49551f5a1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 6 Oct 2021 17:44:36 +0200 Subject: [PATCH] Fix encoding of setters on anonymous classes with structural types Also improve error message when a `var` appears in a refinement. Fixes #13703 --- compiler/src/dotty/tools/dotc/parsing/Parsers.scala | 3 +++ compiler/src/dotty/tools/dotc/typer/Dynamic.scala | 2 +- tests/neg/i13703.check | 5 +++++ tests/neg/i13703.scala | 5 +++++ tests/run/i13703.scala | 5 +++++ 5 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i13703.check create mode 100644 tests/neg/i13703.scala create mode 100644 tests/run/i13703.scala diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index 415899eaed04..e572a5891eda 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -3894,6 +3894,9 @@ object Parsers { val stats = new ListBuffer[Tree] def checkLegal(tree: Tree): List[Tree] = val problem = tree match + case tree: ValDef if tree.mods.is(Mutable) => + i"""refinement cannot be a mutable var. + |You can use an explicit getter ${tree.name} and setter ${tree.name}_= instead""" case tree: MemberDef if !(tree.mods.flags & ModifierFlags).isEmpty => i"refinement cannot be ${(tree.mods.flags & ModifierFlags).flagStrings().mkString("`", "`, `", "`")}" case tree: DefDef if tree.termParamss.nestedExists(!_.rhs.isEmpty) => diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala index 232ad8456c0a..72a0cfe9dcbe 100644 --- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala +++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala @@ -186,7 +186,7 @@ trait Dynamic { val base = untpd.Apply( untpd.TypedSplice(selectable.select(selectorName)).withSpan(fun.span), - (Literal(Constant(name.toString)) :: Nil).map(untpd.TypedSplice(_))) + (Literal(Constant(name.encode.toString)) :: Nil).map(untpd.TypedSplice(_))) val scall = if (vargss.isEmpty) base diff --git a/tests/neg/i13703.check b/tests/neg/i13703.check new file mode 100644 index 000000000000..34f37cc1502f --- /dev/null +++ b/tests/neg/i13703.check @@ -0,0 +1,5 @@ +-- Error: tests/neg/i13703.scala:3:17 ---------------------------------------------------------------------------------- +3 |val f: Foo { var i: Int } = new Foo { var i: Int = 0 } // error + | ^^^^^^^^^^ + | refinement cannot be a mutable var. + | You can use an explicit getter i and setter i_= instead diff --git a/tests/neg/i13703.scala b/tests/neg/i13703.scala new file mode 100644 index 000000000000..c81d1b6e3e0b --- /dev/null +++ b/tests/neg/i13703.scala @@ -0,0 +1,5 @@ +trait Foo extends reflect.Selectable + +val f: Foo { var i: Int } = new Foo { var i: Int = 0 } // error + +val f2: Foo { val i: Int; def i_=(x: Int): Unit } = new Foo { var i: Int = 0 } // OK diff --git a/tests/run/i13703.scala b/tests/run/i13703.scala new file mode 100644 index 000000000000..0483e4ca7dc2 --- /dev/null +++ b/tests/run/i13703.scala @@ -0,0 +1,5 @@ +trait Foo extends reflect.Selectable + +@main def Test: Unit = + val f = new Foo { var i: Int = 0 } + f.i = 1 \ No newline at end of file