Skip to content

Commit

Permalink
SI-5720: Qual block doesn't update sym owner
Browse files Browse the repository at this point in the history
A one-line change to blockWithQualifier. The symptom is
undefined tmp var symbols in the backend; lamba lift thinks
the tmp var is free and adds it to anonfun ctors.
  • Loading branch information
som-snytt committed May 3, 2012
1 parent b27abca commit aabe71f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
Expand Up @@ -155,6 +155,8 @@ trait NamesDefaults { self: Analyzer =>
val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos) setInfo qual.tpe
blockTyper.context.scope enter sym
val vd = atPos(sym.pos)(ValDef(sym, qual) setType NoType)
// it stays in Vegas: SI-5720, SI-5727
qual changeOwner (blockTyper.context.owner -> sym)

var baseFunTransformed = atPos(baseFun.pos.makeTransparent) {
// don't use treeCopy: it would assign opaque position.
Expand Down
56 changes: 56 additions & 0 deletions test/files/pos/t5720-ownerous.scala
@@ -0,0 +1,56 @@

/*
* The block under qual$1 must be owned by it.
* In the sample bug, the first default arg generates x$4,
* the second default arg generates qual$1, hence the maximal
* minimization.
*
<method> <triedcooking> def model: C.this.M = {
val qual$1: C.this.M = scala.Option.apply[C.this.M]({
val x$1: lang.this.String("foo") = "foo";
val x$2: String = C.this.M.apply$default$2("foo");
C.this.M.apply("foo")(x$2)
}).getOrElse[C.this.M]({
val x$3: lang.this.String("bar") = "bar";
val x$4: String = C.this.M.apply$default$2("bar");
C.this.M.apply("bar")(x$4)
});
val x$5: lang.this.String("baz") = "baz";
val x$6: String = qual$1.copy$default$2("baz");
qual$1.copy("baz")(x$6)
}
*/
class C {
case class M(currentUser: String = "anon")(val message: String = "empty")
val m = M("foo")()

// reported
//def model = Option(M("foo")()).getOrElse(M("bar")()).copy(currentUser = "")()

// the bug
def model = Option(m).getOrElse(M("bar")()).copy("baz")()

// style points for this version
def modish = ((null: Option[M]) getOrElse new M()()).copy()()

// various simplifications are too simple
case class N(currentUser: String = "anon")
val n = N("fun")
def nudel = Option(n).getOrElse(N()).copy()
}

object Test {
def main(args: Array[String]) {
val c = new C
println(c.model.currentUser)
println(c.model.message)
}
}
/*
symbol value x$4$1 does not exist in badcopy.C.model
at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:45)
at scala.tools.nsc.Global.abort(Global.scala:202)
at scala.tools.nsc.backend.icode.GenICode$ICodePhase.liftedTree2$1(GenICode.scala:998)
at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$backend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:992)
*/

31 changes: 31 additions & 0 deletions test/files/pos/t5727.scala
@@ -0,0 +1,31 @@

/*
* We like operators, bar none.
*/
object Test {

trait SomeInfo
case object NoInfo extends SomeInfo

sealed abstract class Res[+T]
case object NotRes extends Res[Nothing]


abstract class Base[+T] {
def apply(f: String): Res[T]
// 'i' crashes the compiler, similarly if we use currying
//def |[U >: T](a: => Base[U], i: SomeInfo = NoInfo): Base[U] = null
def bar[U >: T](a: => Base[U], i: SomeInfo = NoInfo): Base[U] = null
}

implicit def fromStringToBase(a: String): Base[String] = new Base[String] { def apply(in: String) = NotRes }

// bug
//def Sample: Base[Any] = ( rep("foo" | "bar") | "sth")
def Sample: Base[Any] = ( rep("foo" bar "bar") bar "sth")

def rep[T](p: => Base[T]): Base[T] = null // whatever

def main(args: Array[String]) {
}
}

0 comments on commit aabe71f

Please sign in to comment.