aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala8
-rw-r--r--src/dotty/tools/dotc/typer/Mode.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala24
-rw-r--r--test/dotc/tests.scala2
-rw-r--r--tests/neg/assignments.scala23
-rw-r--r--tests/pos/assignments.scala25
6 files changed, 66 insertions, 18 deletions
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index ddd95fde1..cb22e8e88 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -46,7 +46,7 @@ object Inferencing {
*
* [ ].name: proto
*/
- class SelectionProto(name: Name, proto: Type)
+ class SelectionProto(val name: Name, proto: Type)
extends RefinedType(WildcardType, name)(_ => proto) with ProtoType with Compatibility {
override def viewExists(tp: Type, pt: Type)(implicit ctx: Context): Boolean = false
override def isMatchedBy(tp1: Type)(implicit ctx: Context) =
@@ -232,10 +232,8 @@ object Inferencing {
/** Check that type `tp` is stable.
* @return The type itself
*/
- def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Type = {
- if (!tp.isStable) ctx.error(i"Prefix $tp is not stable", pos)
- tp
- }
+ def checkStable(tp: Type, pos: Position)(implicit ctx: Context): Unit =
+ if (!tp.isStable) ctx.error(i"Prefix of type ${tp.widenIfUnstable} is not stable", pos)
/** Check that `tp` is a class type with a stable prefix.
* @return Underlying class symbol if type checks out OK, ObjectClass if not.
diff --git a/src/dotty/tools/dotc/typer/Mode.scala b/src/dotty/tools/dotc/typer/Mode.scala
index 1890822b6..8b8b74b84 100644
--- a/src/dotty/tools/dotc/typer/Mode.scala
+++ b/src/dotty/tools/dotc/typer/Mode.scala
@@ -16,7 +16,6 @@ case class Mode(val bits: Int) extends AnyVal {
}
object Mode {
-// val None = Mode(1 << 0)
val None = Mode(0)
private var modeName = new Array[String](32)
@@ -30,7 +29,6 @@ object Mode {
val Type = newMode(1, "Type")
val ImplicitsEnabled = newMode(2, "ImplicitsEnabled")
- val InSuperInit = newMode(3, "InSuperInit")
val PatternOrType = Pattern | Type
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 2abea02cb..b2796f62f 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -360,7 +360,7 @@ class Typer extends Namer with Applications with Implicits {
tree.withType(cls.thisType)
}
- def typedSuper(tree: untpd.Super)(implicit ctx: Context): Tree = track("typedSuper") {
+ def typedSuper(tree: untpd.Super, pt: Type)(implicit ctx: Context): Tree = track("typedSuper") {
val mix = tree.mix
val qual1 = typed(tree.qual)
val cls = qual1.tpe.typeSymbol
@@ -375,9 +375,10 @@ class Typer extends Namer with Applications with Implicits {
}
val owntype =
if (!mix.isEmpty) findMixinSuper(cls.info)
- else if (ctx.mode is Mode.InSuperInit) cls.info.firstParent
- else cls.info.parents.reduceLeft((x: Type, y: Type) => AndType(x, y))
-
+ else pt match {
+ case pt: SelectionProto if pt.name == nme.CONSTRUCTOR => cls.info.firstParent
+ case _ => cls.info.parents.reduceLeft((x: Type, y: Type) => AndType(x, y))
+ }
cpy.Super(tree, qual1, mix).withType(SuperType(cls.thisType, owntype))
}
@@ -448,9 +449,9 @@ class Typer extends Namer with Applications with Implicits {
tree.lhs match {
case lhs @ Apply(fn, args) =>
typed(cpy.Apply(lhs, untpd.Select(fn, nme.update), args :+ tree.rhs), pt)
- case untpd.TypedSplice(Apply(Select(lhs, app), args)) if app == nme.apply =>
- typed(cpy.Apply(lhs,
- untpd.Select(untpd.TypedSplice(lhs), nme.update),
+ case untpd.TypedSplice(Apply(Select(fn, app), args)) if app == nme.apply =>
+ typed(cpy.Apply(fn,
+ untpd.Select(untpd.TypedSplice(fn), nme.update),
(args map untpd.TypedSplice) :+ tree.rhs), pt)
case lhs =>
val lhs1 = typed(lhs)
@@ -458,7 +459,7 @@ class Typer extends Namer with Applications with Implicits {
errorTree(cpy.Assign(tree, lhs1, typed(tree.rhs, lhs1.tpe.widen)),
"reassignment to val")
lhs1.tpe match {
- case ref: TermRef if ref.symbol is Mutable =>
+ case ref: TermRef if ref.symbol is (Mutable, butNot = Accessor) =>
cpy.Assign(tree, lhs1, typed(tree.rhs, ref.info)).withType(defn.UnitType)
case ref: TermRef if ref.info.isParameterless =>
val pre = ref.prefix
@@ -466,8 +467,8 @@ class Typer extends Namer with Applications with Implicits {
val setter = pre.member(setterName)
lhs1 match {
case lhs1: RefTree if setter.exists =>
- val setterTypeRaw = TermRef(pre, setterName).withDenot(setter)
- val setterType = checkAccessible(setterTypeRaw, isSuperSelection(tree), tree.pos)
+ val setterTypeRaw = pre select (setterName, setter)
+ val setterType = checkAccessible(setterTypeRaw, isSuperSelection(lhs1), tree.pos)
val lhs2 = lhs1.withName(setterName).withType(setterType)
typed(cpy.Apply(tree, untpd.TypedSplice(lhs2), tree.rhs :: Nil))
case _ =>
@@ -789,6 +790,7 @@ class Typer extends Namer with Applications with Implicits {
def typedImport(imp: untpd.Import, sym: Symbol)(implicit ctx: Context): Import = track("typedImport") {
val expr1 = typedExpr(imp.expr, AnySelectionProto)
+ checkStable(expr1.tpe, imp.expr.pos)
cpy.Import(imp, expr1, imp.selectors).withType(sym.termRef)
}
@@ -862,7 +864,7 @@ class Typer extends Namer with Applications with Implicits {
case tree: untpd.Try => typedTry(tree, pt)
case tree: untpd.Throw => typedThrow(tree)
case tree: untpd.TypeApply => typedTypeApply(tree, pt)
- case tree: untpd.Super => typedSuper(tree)
+ case tree: untpd.Super => typedSuper(tree, pt)
case tree: untpd.SeqLiteral => typedSeqLiteral(tree, pt)
case tree: untpd.TypeTree => typedTypeTree(tree, pt)
case tree: untpd.SingletonTypeTree => typedSingletonTypeTree(tree)
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index eb7aede1c..acaa58068 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -28,8 +28,10 @@ class tests extends CompilerTest {
@Test def pos_sigs() = compileFile(posDir, "sigs")
@Test def pos_typers() = compileFile(posDir, "typers")
@Test def pos_typedidents() = compileFile(posDir, "typedidents")
+ @Test def pos_assignments() = compileFile(posDir, "assignments")
@Test def neg_blockescapes() = compileFile(negDir, "blockescapesNeg", xerrors = 2)
@Test def neg_typedapply() = compileFile(negDir, "typedapply", xerrors = 4)
@Test def neg_typedidents() = compileFile(negDir, "typedidents", xerrors = 2)
+ @Test def nef_assignments() = compileFile(negDir, "assignments", xerrors = 3)
} \ No newline at end of file
diff --git a/tests/neg/assignments.scala b/tests/neg/assignments.scala
new file mode 100644
index 000000000..2f7db275a
--- /dev/null
+++ b/tests/neg/assignments.scala
@@ -0,0 +1,23 @@
+object assignments {
+
+ var a = Array(1, 2, 3)
+ var i = 0
+ a(i) = a(i) * 2
+ a(i+1) += 1
+
+ class C {
+ var myX = 0
+ def x = myX
+ def x_=(x: Int) = myX = x
+
+ x = x + 1
+ x *= 2
+
+ x_= = 2 // should give missing arguments + reassignment to val
+ }
+
+ var c = new C
+ import c._ // should give: prefix is not stable
+ x = x + 1
+ x *= 2
+}
diff --git a/tests/pos/assignments.scala b/tests/pos/assignments.scala
new file mode 100644
index 000000000..94223b62c
--- /dev/null
+++ b/tests/pos/assignments.scala
@@ -0,0 +1,25 @@
+object assignments {
+
+ var a = Array(1, 2, 3)
+ var i = 0
+ a(i) = a(i) * 2
+ a(i+1) += 1
+
+ class C {
+ var myX = 0
+ def x = myX
+ def x_=(x: Int) = myX = x
+
+ x = x + 1
+ x *= 2
+ }
+
+ var c = new C
+ c.x =c.x + 1
+ c.x *= 2
+
+ val cc = c
+ import cc._
+ x = x + 1
+ x *= 2
+}