diff --git a/bench/tests/Vector.scala b/bench/tests/Vector.scala index 1572e12a7165..eb9ed309f179 100644 --- a/bench/tests/Vector.scala +++ b/bench/tests/Vector.scala @@ -14,6 +14,7 @@ import scala.annotation.unchecked.uncheckedVariance import scala.compat.Platform import scala.collection.generic._ import scala.collection.mutable.Builder +import compiletime.uninitialized /** Companion object to the Vector class */ @@ -741,13 +742,13 @@ final class VectorBuilder[A]() extends Builder[A,Vector[A]] with VectorPointer[A private[immutable] trait VectorPointer[T] { - private[immutable] var depth: Int = _ - private[immutable] var display0: Array[AnyRef] = _ - private[immutable] var display1: Array[AnyRef] = _ - private[immutable] var display2: Array[AnyRef] = _ - private[immutable] var display3: Array[AnyRef] = _ - private[immutable] var display4: Array[AnyRef] = _ - private[immutable] var display5: Array[AnyRef] = _ + private[immutable] var depth: Int = uninitialized + private[immutable] var display0: Array[AnyRef] = uninitialized + private[immutable] var display1: Array[AnyRef] = uninitialized + private[immutable] var display2: Array[AnyRef] = uninitialized + private[immutable] var display3: Array[AnyRef] = uninitialized + private[immutable] var display4: Array[AnyRef] = uninitialized + private[immutable] var display5: Array[AnyRef] = uninitialized // used private[immutable] final def initFrom[U](that: VectorPointer[U]): Unit = initFrom(that, that.depth) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 07ac87b15a48..0f96fa4df3fb 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -226,8 +226,9 @@ class Definitions { @tu lazy val CompiletimePackageObject: Symbol = requiredModule("scala.compiletime.package") @tu lazy val Compiletime_codeOf: Symbol = CompiletimePackageObject.requiredMethod("codeOf") @tu lazy val Compiletime_erasedValue : Symbol = CompiletimePackageObject.requiredMethod("erasedValue") + @tu lazy val Compiletime_uninitialized: Symbol = CompiletimePackageObject.requiredMethod("uninitialized") @tu lazy val Compiletime_error : Symbol = CompiletimePackageObject.requiredMethod(nme.error) - @tu lazy val Compiletime_requireConst: Symbol = CompiletimePackageObject.requiredMethod("requireConst") + @tu lazy val Compiletime_requireConst : Symbol = CompiletimePackageObject.requiredMethod("requireConst") @tu lazy val Compiletime_constValue : Symbol = CompiletimePackageObject.requiredMethod("constValue") @tu lazy val Compiletime_constValueOpt: Symbol = CompiletimePackageObject.requiredMethod("constValueOpt") @tu lazy val Compiletime_summonFrom : Symbol = CompiletimePackageObject.requiredMethod("summonFrom") diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala index ee55bf910f9f..21727c7ec2be 100644 --- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala @@ -3201,7 +3201,8 @@ object Parsers { /** PatDef ::= ids [‘:’ Type] ‘=’ Expr * | Pattern2 [‘:’ Type] ‘=’ Expr - * VarDef ::= PatDef | id {`,' id} `:' Type `=' `_' + * VarDef ::= PatDef + * | id {`,' id} `:' Type `=' `_' (deprecated in 3.1) * ValDcl ::= id {`,' id} `:' Type * VarDcl ::= id {`,' id} `:' Type */ @@ -3224,9 +3225,14 @@ object Parsers { val rhs = if tpt.isEmpty || in.token == EQUALS then accept(EQUALS) + val rhsOffset = in.offset subExpr() match case rhs0 @ Ident(name) if placeholderParams.nonEmpty && name == placeholderParams.head.name && !tpt.isEmpty && mods.is(Mutable) && lhs.forall(_.isInstanceOf[Ident]) => + if sourceVersion.isAtLeast(`3.1`) then + deprecationWarning( + em"""`= _` has been deprecated; use `= uninitialized` instead. + |`uninitialized` can be imported with `scala.compiletime.uninitialized`.""", rhsOffset) placeholderParams = placeholderParams.tail atSpan(rhs0.span) { Ident(nme.WILDCARD) } case rhs0 => rhs0 diff --git a/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala b/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala index 4833421cb298..121b2f664c6e 100644 --- a/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala +++ b/compiler/src/dotty/tools/dotc/transform/PruneErasedDefs.scala @@ -10,6 +10,7 @@ import Symbols._ import Types._ import typer.RefChecks import MegaPhase.MiniPhase +import StdNames.nme import ast.tpd /** This phase makes all erased term members of classes private so that they cannot @@ -18,6 +19,10 @@ import ast.tpd * The phase also replaces all expressions that appear in an erased context by * default values. This is necessary so that subsequent checking phases such * as IsInstanceOfChecker don't give false negatives. + * Finally, the phase replaces `compiletime.uninitialized` on the right hand side + * of a mutable field definition by `_`. This avoids a "is declared erased, but is + * in fact used" error in Erasure and communicates to Constructors that the + * variable does not have an initializer. */ class PruneErasedDefs extends MiniPhase with SymTransformer { thisTransform => import tpd._ @@ -38,10 +43,25 @@ class PruneErasedDefs extends MiniPhase with SymTransformer { thisTransform => cpy.Apply(tree)(tree.fun, tree.args.map(trivialErasedTree)) else tree + private def hasUninitializedRHS(tree: ValOrDefDef)(using Context): Boolean = + def recur(rhs: Tree): Boolean = rhs match + case rhs: RefTree => + rhs.symbol == defn.Compiletime_uninitialized + && tree.symbol.is(Mutable) && tree.symbol.owner.isClass + case closureDef(ddef) if defn.isContextFunctionType(tree.tpt.tpe.dealias) => + recur(ddef.rhs) + case _ => + false + recur(tree.rhs) + override def transformValDef(tree: ValDef)(using Context): Tree = - if (tree.symbol.isEffectivelyErased && !tree.rhs.isEmpty) + val sym = tree.symbol + if tree.symbol.isEffectivelyErased && !tree.rhs.isEmpty then cpy.ValDef(tree)(rhs = trivialErasedTree(tree)) - else tree + else if hasUninitializedRHS(tree) then + cpy.ValDef(tree)(rhs = cpy.Ident(tree.rhs)(nme.WILDCARD).withType(tree.tpt.tpe)) + else + tree override def transformDefDef(tree: DefDef)(using Context): Tree = if (tree.symbol.isEffectivelyErased && !tree.rhs.isEmpty) diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index f2df0f534b48..0506eefa89a3 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -119,7 +119,7 @@ class CompilationTests { aggregateTests( compileFilesInDir("tests/neg", defaultOptions), compileFilesInDir("tests/neg-tailcall", defaultOptions), - compileFilesInDir("tests/neg-strict", defaultOptions.and("-source", "3.1", "-Xfatal-warnings")), + compileFilesInDir("tests/neg-strict", defaultOptions.and("-source", "3.1", "-deprecation", "-Xfatal-warnings")), compileFilesInDir("tests/neg-no-kind-polymorphism", defaultOptions and "-Yno-kind-polymorphism"), compileFilesInDir("tests/neg-custom-args/deprecation", defaultOptions.and("-Xfatal-warnings", "-deprecation")), compileFilesInDir("tests/neg-custom-args/fatal-warnings", defaultOptions.and("-Xfatal-warnings")), diff --git a/docs/docs/internals/syntax.md b/docs/docs/internals/syntax.md index 447587c16699..670d46ff0568 100644 --- a/docs/docs/internals/syntax.md +++ b/docs/docs/internals/syntax.md @@ -384,14 +384,12 @@ TypeDcl ::= id [TypeParamClause] {FunParamClause} TypeBounds [‘=’ Type] Def ::= ‘val’ PatDef - | ‘var’ VarDef + | ‘var’ PatDef | ‘def’ DefDef | ‘type’ {nl} TypeDcl | TmplDef PatDef ::= ids [‘:’ Type] ‘=’ Expr - | Pattern2 [‘:’ Type] ‘=’ Expr PatDef(_, pats, tpe?, expr) -VarDef ::= PatDef - | ids ‘:’ Type ‘=’ ‘_’ + | Pattern2 [‘:’ Type] ‘=’ Expr PatDef(_, pats, tpe?, expr) DefDef ::= DefSig [‘:’ Type] ‘=’ Expr DefDef(_, name, tparams, vparamss, tpe, expr) | ‘this’ DefParamClause DefParamClauses ‘=’ ConstrExpr DefDef(_, , Nil, vparamss, EmptyTree, expr | Block) diff --git a/docs/docs/reference/dropped-features/wildcard-init.md b/docs/docs/reference/dropped-features/wildcard-init.md new file mode 100644 index 000000000000..0241d07651ee --- /dev/null +++ b/docs/docs/reference/dropped-features/wildcard-init.md @@ -0,0 +1,18 @@ +--- +layout: doc-page +title: "Dropped: wildcard initializer" +--- + +The syntax +```scala + var x: A = _ +``` +that was used to indicate an uninitialized field, has been dropped. +At its place there is a special value `uninitialized` in the `scala.compiletime` package. To get an uninitialized field, you now write +```scala +import scala.compiletime.uninitialized + +var x: A = uninitialized +``` +To enable cross-compilation, `_` is still supported, but it will be dropped in a future 3.x version. + diff --git a/docs/docs/reference/syntax.md b/docs/docs/reference/syntax.md index 9ad9ecc49857..b2de66272ddf 100644 --- a/docs/docs/reference/syntax.md +++ b/docs/docs/reference/syntax.md @@ -374,14 +374,12 @@ DefSig ::= id [DefTypeParamClause] DefParamClauses TypeDcl ::= id [TypeParamClause] {FunParamClause} TypeBounds [‘=’ Type] Def ::= ‘val’ PatDef - | ‘var’ VarDef + | ‘var’ PatDef | ‘def’ DefDef | ‘type’ {nl} TypeDcl | TmplDef PatDef ::= ids [‘:’ Type] ‘=’ Expr | Pattern2 [‘:’ Type] ‘=’ Expr -VarDef ::= PatDef - | ids ‘:’ Type ‘=’ ‘_’ DefDef ::= DefSig [‘:’ Type] ‘=’ Expr | ‘this’ DefParamClause DefParamClauses ‘=’ ConstrExpr diff --git a/docs/sidebar.yml b/docs/sidebar.yml index 9450d3b41eb7..35d1c79aedcb 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -189,6 +189,8 @@ sidebar: url: docs/reference/dropped-features/nonlocal-returns.html - title: "[this] Qualifier" url: docs/reference/dropped-features/this-qualifier.html + - title: Wildcard initializers + url: docs/reference/dropped-features/wildcard-init.html - title: Syntax Summary url: docs/reference/syntax.html - title: Contributing diff --git a/library/src/scala/compiletime/package.scala b/library/src/scala/compiletime/package.scala index ac0f03431b6e..8ebaf801f3e1 100644 --- a/library/src/scala/compiletime/package.scala +++ b/library/src/scala/compiletime/package.scala @@ -1,6 +1,5 @@ package scala - -import scala.quoted._ +import annotation.compileTimeOnly package object compiletime { @@ -18,6 +17,17 @@ package object compiletime { */ erased def erasedValue[T]: T = ??? + /** Used as the initializer of a mutable class or object field, like this: + * + * var x: T = uninitialized + * + * This signifies that the field is not initialized on its own. It is still initialized + * as part of the bulk initialization of the object it belongs to, which assigns zero + * values such as `null`, `0`, `0.0`, `false` to all object fields. + */ + @compileTimeOnly("`uninitialized` can only be used as the right hand side of a mutable field definition") + def uninitialized: Nothing = ??? + /** The error method is used to produce user-defined compile errors during inline expansion. * If an inline expansion results in a call error(msgStr) the compiler produces an error message containing the given msgStr. * diff --git a/tests/fuzzy/471d33abf565d5dd3691679237f148638f4ff115.scala b/tests/fuzzy/471d33abf565d5dd3691679237f148638f4ff115.scala index ac1454aaf04c..da61389c21cc 100644 --- a/tests/fuzzy/471d33abf565d5dd3691679237f148638f4ff115.scala +++ b/tests/fuzzy/471d33abf565d5dd3691679237f148638f4ff115.scala @@ -24,7 +24,7 @@ def i10(i2: i4): i3 = new i4(i5) object i10 { def main(i12: Array[String]): Unit = { val i10: Array[String] = null -var i2 = _ +var i2 = compiletime.uninitialized def i3(i2: Int) = i2 } object i0 { diff --git a/tests/init/crash/i2468.scala b/tests/init/crash/i2468.scala index 801d92ea6fa6..ed3c31a8551c 100644 --- a/tests/init/crash/i2468.scala +++ b/tests/init/crash/i2468.scala @@ -1,8 +1,9 @@ +import compiletime.uninitialized object Test { class A { - private[this] var x: String = _ + private[this] var x: String = uninitialized } class B { @@ -11,16 +12,16 @@ object Test { } class C { - private[this] var x1: Int = _ - private[this] var x2: Unit = _ - private[this] var x3: Char = _ - private[this] var x4: Boolean = _ - private[this] var x5: Float = _ - private[this] var x6: Double = _ - private[this] var x7: Char = _ - private[this] var x8: Byte = _ - private[this] var x9: AnyVal = _ - private[this] var x10: D = _ + private[this] var x1: Int = uninitialized + private[this] var x2: Unit = uninitialized + private[this] var x3: Char = uninitialized + private[this] var x4: Boolean = uninitialized + private[this] var x5: Float = uninitialized + private[this] var x6: Double = uninitialized + private[this] var x7: Char = uninitialized + private[this] var x8: Byte = uninitialized + private[this] var x9: AnyVal = uninitialized + private[this] var x10: D = uninitialized } class D(x: Int) extends AnyVal diff --git a/tests/init/crash/opassign.scala b/tests/init/crash/opassign.scala index 8f6cad903a27..64984217502d 100644 --- a/tests/init/crash/opassign.scala +++ b/tests/init/crash/opassign.scala @@ -12,7 +12,7 @@ object opassign { } class Ref { - var x: Int = _ + var x: Int = compiletime.uninitialized } val r = new Ref r.x += 1 diff --git a/tests/neg-strict/i1050.scala b/tests/neg-strict/i1050.scala index fa3a84625f2a..6962dd44f826 100644 --- a/tests/neg-strict/i1050.scala +++ b/tests/neg-strict/i1050.scala @@ -74,7 +74,7 @@ object Tiark3 { def brand(x: Any): p.L = x // error: underlying not concrete } trait V extends U { - type X = B with A + type X = B & A def p2: X = ??? } val v = new V {} diff --git a/tests/neg-strict/i11225.scala b/tests/neg-strict/i11225.scala new file mode 100644 index 000000000000..2a7e3ec57561 --- /dev/null +++ b/tests/neg-strict/i11225.scala @@ -0,0 +1,10 @@ +import compiletime.uninitialized + +class Memo[A](x: => A): + private var cached: A = _ // error + private var known: Boolean = false + def force = + if !known then + known = true + cached = x + cached diff --git a/tests/neg-strict/nullless.scala b/tests/neg-strict/nullless.scala index 38845f5c3d8b..7545d840db83 100644 --- a/tests/neg-strict/nullless.scala +++ b/tests/neg-strict/nullless.scala @@ -29,8 +29,8 @@ object bar { type U = UU } final lazy val nothing: Nothing = nothing - final lazy val sub: S2 with Sub = nothing - final lazy val box : Box[S2 with Sub] = new Box(nothing) + final lazy val sub: S2 & Sub = nothing + final lazy val box : Box[S2 & Sub] = new Box(nothing) def upcast(t: box.v.M2): box.v.M2 = t // error // error under -strict } def main(args : Array[String]) : Unit = { diff --git a/tests/neg/i11225.check b/tests/neg/i11225.check new file mode 100644 index 000000000000..60805a27b22d --- /dev/null +++ b/tests/neg/i11225.check @@ -0,0 +1,45 @@ +-- Error: tests/neg/i11225.scala:5:16 ---------------------------------------------------------------------------------- +5 | val x1: Int = uninitialized // error + | ^^^^^^^^^^^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition +-- Error: tests/neg/i11225.scala:6:28 ---------------------------------------------------------------------------------- +6 | var x2: Int = if ??? then uninitialized else uninitialized // error // error + | ^^^^^^^^^^^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition +-- Error: tests/neg/i11225.scala:6:47 ---------------------------------------------------------------------------------- +6 | var x2: Int = if ??? then uninitialized else uninitialized // error // error + | ^^^^^^^^^^^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition +-- Error: tests/neg/i11225.scala:9:28 ---------------------------------------------------------------------------------- +9 | var x5: () => Int = () => uninitialized // error + | ^^^^^^^^^^^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition +-- Error: tests/neg/i11225.scala:10:18 --------------------------------------------------------------------------------- +10 | var x6: Int = { uninitialized } // error + | ^^^^^^^^^^^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition +-- Error: tests/neg/i11225.scala:13:22 --------------------------------------------------------------------------------- +13 | var cached: Int = uninitialized // error + | ^^^^^^^^^^^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition +-- Error: tests/neg/i11225.scala:14:30 --------------------------------------------------------------------------------- +14 | cached = if x then 1 else uninitialized // error + | ^^^^^^^^^^^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition +-- Error: tests/neg/i11225.scala:17:4 ---------------------------------------------------------------------------------- +17 | uninitialized // error + | ^^^^^^^^^^^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition +-- Error: tests/neg/i11225.scala:18:4 ---------------------------------------------------------------------------------- +18 | uninitialized // error + | ^^^^^^^^^^^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition +-- Error: tests/neg/i11225.scala:23:4 ---------------------------------------------------------------------------------- +23 | uninitialized // error + | ^^^^^^^^^^^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition +-- Error: tests/neg/i11225.scala:30:16 --------------------------------------------------------------------------------- +30 | var x7: Int = uni // error + | ^^^ + | `uninitialized` can only be used as the right hand side of a mutable field definition + | This location contains code that was inlined from i11225.scala:25 diff --git a/tests/neg/i11225.scala b/tests/neg/i11225.scala new file mode 100644 index 000000000000..0d61e769665b --- /dev/null +++ b/tests/neg/i11225.scala @@ -0,0 +1,30 @@ +import compiletime.uninitialized + +class Test: + + val x1: Int = uninitialized // error + var x2: Int = if ??? then uninitialized else uninitialized // error // error + var x3: Int = if true then uninitialized else 1 // ok + var x4: Int = if false then uninitialized else 1 // ok + var x5: () => Int = () => uninitialized // error + var x6: Int = { uninitialized } // error + + def f(x: Boolean) = + var cached: Int = uninitialized // error + cached = if x then 1 else uninitialized // error + + var c: Int = + uninitialized // error + uninitialized // error + 2 + + var d: Int = + println("pseudo init") + uninitialized // error + + transparent inline def uni = uninitialized + + inline def g(inline x: Int): Unit = () + def f2 = g(uninitialized) // this one is ok since `uninitialized` is inlined away + + var x7: Int = uni // error diff --git a/tests/neg/i8427.scala b/tests/neg/i8427.scala index 314c6664fe87..a5bdd68567c1 100644 --- a/tests/neg/i8427.scala +++ b/tests/neg/i8427.scala @@ -2,6 +2,6 @@ trait T object Test { - var t: T = _ + var t: T = compiletime.uninitialized def main(args: Array[String]) = println("hi") } diff --git a/tests/neg/refinedSubtyping.scala b/tests/neg/refinedSubtyping.scala index dba489f3e7f2..42351d08786d 100644 --- a/tests/neg/refinedSubtyping.scala +++ b/tests/neg/refinedSubtyping.scala @@ -13,7 +13,7 @@ class Test3 { type U1 = C { type T <: B } type U2 = C { type T <: A } - var x: T2 = _ + var x: T2 = compiletime.uninitialized val y1: U1 = ??? val y2: U2 = ??? diff --git a/tests/neg/t11437.scala b/tests/neg/t11437.scala index 603a692bcfe8..be100b116e77 100644 --- a/tests/neg/t11437.scala +++ b/tests/neg/t11437.scala @@ -1,6 +1,6 @@ class Regress { - var v: Int = _ + var v: Int = compiletime.uninitialized def f = 42 var w: Int = (_) // error: not default value syntax } diff --git a/tests/neg/tcpoly_variance_enforce.scala b/tests/neg/tcpoly_variance_enforce.scala index ddff0e9f9438..ef0d22cb325e 100644 --- a/tests/neg/tcpoly_variance_enforce.scala +++ b/tests/neg/tcpoly_variance_enforce.scala @@ -32,7 +32,7 @@ object fcoll4_2 extends coll4[FooString, Any] // error object test { - var ok: coll[FooCov] = _ + var ok: coll[FooCov] = compiletime.uninitialized def x: coll[FooInvar] = sys.error("foo") // error def y: coll[FooContra] = sys.error("foo") // error diff --git a/tests/neg/variances-constr.scala b/tests/neg/variances-constr.scala index a5259c4da1f0..2c3b45b04fd8 100644 --- a/tests/neg/variances-constr.scala +++ b/tests/neg/variances-constr.scala @@ -1,6 +1,6 @@ class C[+A] { - private[this] var y: A = _ + private[this] var y: A = compiletime.uninitialized def getY: A = y class Inner(x: A) { // error A appears contravariantly diff --git a/tests/pos-java-interop/t294/Test_1.scala b/tests/pos-java-interop/t294/Test_1.scala index ff1f34b10e0a..18aeb6f8e1df 100644 --- a/tests/pos-java-interop/t294/Test_1.scala +++ b/tests/pos-java-interop/t294/Test_1.scala @@ -1,7 +1,7 @@ // also test pickling of java annotations; Test_2.scala will // read this class file @Ann(nested = Array(new Ann2(10))) class Test { - @Ann2(100) var ctx: Object = _ + @Ann2(100) var ctx: Object = compiletime.uninitialized @Ann(nested = Array()) def foo = 10 @Ann(nested = Array(new Ann2(10), new Ann2(23))) val bam = -3 } diff --git a/tests/pos-special/strawman-collections/CollectionStrawMan4.scala b/tests/pos-special/strawman-collections/CollectionStrawMan4.scala index 2ec8486ba2e4..5383acc02293 100644 --- a/tests/pos-special/strawman-collections/CollectionStrawMan4.scala +++ b/tests/pos-special/strawman-collections/CollectionStrawMan4.scala @@ -463,7 +463,7 @@ object CollectionStrawMan4 { -1 } def filter(p: A => Boolean): Iterator[A] = new Iterator[A] { - private var hd: A = _ + private var hd: A = compiletime.uninitialized private var hdDefined: Boolean = false def hasNext: Boolean = hdDefined || { diff --git a/tests/pos-special/strawman-collections/CollectionStrawMan5.scala b/tests/pos-special/strawman-collections/CollectionStrawMan5.scala index 4d9fa8ac533f..2296b29c82f1 100644 --- a/tests/pos-special/strawman-collections/CollectionStrawMan5.scala +++ b/tests/pos-special/strawman-collections/CollectionStrawMan5.scala @@ -445,7 +445,7 @@ object CollectionStrawMan5 { -1 } def filter(p: A => Boolean): Iterator[A] = new Iterator[A] { - private var hd: A = _ + private var hd: A = compiletime.uninitialized private var hdDefined: Boolean = false def hasNext: Boolean = hdDefined || { diff --git a/tests/pos-special/strawman-collections/CollectionStrawMan6.scala b/tests/pos-special/strawman-collections/CollectionStrawMan6.scala index 6379d7efd4c6..f13c19dad04e 100644 --- a/tests/pos-special/strawman-collections/CollectionStrawMan6.scala +++ b/tests/pos-special/strawman-collections/CollectionStrawMan6.scala @@ -4,6 +4,7 @@ import Predef.{augmentString => _, wrapString => _, _} import scala.reflect.ClassTag import annotation.unchecked.uncheckedVariance import annotation.tailrec +import compiletime.uninitialized class LowPriority { import CollectionStrawMan6._ @@ -606,7 +607,7 @@ object CollectionStrawMan6 extends LowPriority { class LazyList[+A](expr: => LazyList.Evaluated[A]) extends LinearSeq[A] with LinearSeqLike[A, LazyList] { private[this] var evaluated = false - private[this] var result: LazyList.Evaluated[A] = _ + private[this] var result: LazyList.Evaluated[A] = uninitialized def force: LazyList.Evaluated[A] = { if (!evaluated) { @@ -960,7 +961,7 @@ object CollectionStrawMan6 extends LowPriority { len } def filter(p: A => Boolean): Iterator[A] = new Iterator[A] { - private var hd: A = _ + private var hd: A = uninitialized private var hdDefined: Boolean = false def hasNext: Boolean = hdDefined || { diff --git a/tests/pos/Transactions.scala b/tests/pos/Transactions.scala index dc33e8c377a2..a765f518bbde 100644 --- a/tests/pos/Transactions.scala +++ b/tests/pos/Transactions.scala @@ -20,7 +20,7 @@ object Transaction { } class Transaction { - var status: Int = _ + var status: Int = compiletime.uninitialized var id: Long = _ // only for real transactions diff --git a/tests/pos/apply-equiv.scala b/tests/pos/apply-equiv.scala index f53b8b5abd2d..633ed737eabf 100644 --- a/tests/pos/apply-equiv.scala +++ b/tests/pos/apply-equiv.scala @@ -1,12 +1,13 @@ class Test { + import compiletime.uninitialized class Lambda { type Arg; type Apply } type T1 = (Lambda { type Arg = Int } { type Apply = List[Arg] }) # Apply type T2 = List[Int] - var x: T1 = _ - var y: T2 = _ + var x: T1 = uninitialized + var y: T2 = uninitialized x = y y = x diff --git a/tests/pos/capturedVars.scala b/tests/pos/capturedVars.scala index 2cbcf111ae99..267068162a3d 100644 --- a/tests/pos/capturedVars.scala +++ b/tests/pos/capturedVars.scala @@ -1,6 +1,6 @@ class Test { - var field: Int = _ + var field: Int = compiletime.uninitialized def foo() = { diff --git a/tests/pos/constrs.scala b/tests/pos/constrs.scala index dc0e1a369305..88502105457e 100644 --- a/tests/pos/constrs.scala +++ b/tests/pos/constrs.scala @@ -2,7 +2,7 @@ class Foo(x: Int, var y: Int) { val z: Int = 0 - var u: Int = _ + var u: Int = compiletime.uninitialized def f = x diff --git a/tests/pos/hklower.scala b/tests/pos/hklower.scala index 90aa343baff4..0d17ead9ed4c 100644 --- a/tests/pos/hklower.scala +++ b/tests/pos/hklower.scala @@ -34,7 +34,7 @@ class Test2 { f[V](t) - var x: V[Int] = _ + var x: V[Int] = compiletime.uninitialized x = t diff --git a/tests/pos/i11225.scala b/tests/pos/i11225.scala new file mode 100644 index 000000000000..f6233731460c --- /dev/null +++ b/tests/pos/i11225.scala @@ -0,0 +1,12 @@ +import compiletime.uninitialized + +class Memo[A](x: => A): + private var cached1: A = uninitialized + private var cached: A = uninitialized + private var known: Boolean = false + def force = + if !known then + known = true + cached = x + val y = cached1 + cached diff --git a/tests/pos/i2468.scala b/tests/pos/i2468.scala index dc5da96b1cf0..99b891feff43 100644 --- a/tests/pos/i2468.scala +++ b/tests/pos/i2468.scala @@ -1,26 +1,27 @@ +import compiletime.uninitialized object Test { class A { - private[this] var x: String = _ + private[this] var x: String = uninitialized } class B { - private[this] var x: String = _ + private[this] var x: String = uninitialized x = "foo" } class C { - private[this] var x1: Int = _ - private[this] var x2: Unit = _ - private[this] var x3: Char = _ - private[this] var x4: Boolean = _ - private[this] var x5: Float = _ - private[this] var x6: Double = _ - private[this] var x7: Char = _ - private[this] var x8: Byte = _ - private[this] var x9: AnyVal = _ - private[this] var x10: D = _ + private[this] var x1: Int = uninitialized + private[this] var x2: Unit = uninitialized + private[this] var x3: Char = uninitialized + private[this] var x4: Boolean = uninitialized + private[this] var x5: Float = uninitialized + private[this] var x6: Double = uninitialized + private[this] var x7: Char = uninitialized + private[this] var x8: Byte = uninitialized + private[this] var x9: AnyVal = uninitialized + private[this] var x10: D = uninitialized } class D(x: Int) extends AnyVal diff --git a/tests/pos/i9307.scala b/tests/pos/i9307.scala index a795f1d3fc62..5cf3ee9ff2f8 100644 --- a/tests/pos/i9307.scala +++ b/tests/pos/i9307.scala @@ -1,7 +1,8 @@ +import compiletime.uninitialized class Foo: - private var foo1: Int = _ - private var foo2: Array[Int] = _ - private[this] var foo3: Array[Int] = _ - private var foo4: Array[Object] = _ - private var foo5: Array[Array[Int]] = _ - private var foo6: List[Int] = _ + private var foo1: Int = uninitialized + private var foo2: Array[Int] = uninitialized + private[this] var foo3: Array[Int] = uninitialized + private var foo4: Array[Object] = uninitialized + private var foo5: Array[Array[Int]] = uninitialized + private var foo6: List[Int] = uninitialized diff --git a/tests/pos/isApplicableSafe.scala b/tests/pos/isApplicableSafe.scala index c54df1f22985..dfe855814680 100644 --- a/tests/pos/isApplicableSafe.scala +++ b/tests/pos/isApplicableSafe.scala @@ -1,5 +1,5 @@ import reflect.ClassTag - +import compiletime.uninitialized // The same problems arise in real arrays. class A { @@ -10,8 +10,8 @@ class A { } // Any of Array[List[Symbol]], List[Array[Symbol]], or List[List[Symbol]] compile. - var xs: Array[Array[Symbol]] = _ - var ys: Array[Map[Symbol, Set[Symbol]]] = _ + var xs: Array[Array[Symbol]] = uninitialized + var ys: Array[Map[Symbol, Set[Symbol]]] = uninitialized //xs = Array(Array()) // gives: diff --git a/tests/pos/opassign.scala b/tests/pos/opassign.scala index 8f6cad903a27..64984217502d 100644 --- a/tests/pos/opassign.scala +++ b/tests/pos/opassign.scala @@ -12,7 +12,7 @@ object opassign { } class Ref { - var x: Int = _ + var x: Int = compiletime.uninitialized } val r = new Ref r.x += 1 diff --git a/tests/pos/projections.scala b/tests/pos/projections.scala index 894a00bcf7f4..87682673a745 100644 --- a/tests/pos/projections.scala +++ b/tests/pos/projections.scala @@ -1,13 +1,14 @@ +import compiletime.uninitialized class projections { class Lambda { type Arg; type Apply } - var x: (Lambda { type Apply = Int; type Arg = String }) # Apply = _ - var y: Int = _ + var x: (Lambda { type Apply = Int; type Arg = String }) # Apply = uninitialized + var y: Int = uninitialized x = y y = x - var xx: (Lambda { type Apply = Arg } { type Arg = Int }) # Apply = _ + var xx: (Lambda { type Apply = Arg } { type Arg = Int }) # Apply = uninitialized xx = y y = xx diff --git a/tests/pos/refinedSubtyping.scala b/tests/pos/refinedSubtyping.scala index e6a972e1c6a8..aa807468f1e4 100644 --- a/tests/pos/refinedSubtyping.scala +++ b/tests/pos/refinedSubtyping.scala @@ -1,3 +1,4 @@ +import compiletime.uninitialized class Test { class C { type T; type Coll } @@ -10,8 +11,8 @@ class Test { type T22 = T2 { type T = Int } - var x: T11 = _ - var y: T22 = _ + var x: T11 = uninitialized + var y: T22 = uninitialized x = y y = x @@ -29,8 +30,8 @@ class Test2 { type U1 = C { type T <: B } { type T <: A } - var x: T1 = _ - var y: U1 = _ + var x: T1 = uninitialized + var y: U1 = uninitialized x = y y = x @@ -50,8 +51,8 @@ class Test3 { type U1 = C { type T <: B } type U2 = U1 { type T <: A } - var x: T2 = _ - var y: U2 = _ + var x: T2 = uninitialized + var y: U2 = uninitialized val x1 = x val y1 = y diff --git a/tests/pos/spec-simple.scala b/tests/pos/spec-simple.scala index 19b660688f34..b8232b62a2a6 100644 --- a/tests/pos/spec-simple.scala +++ b/tests/pos/spec-simple.scala @@ -1,5 +1,5 @@ class Foo[@specialized T] { - var v: T = _ + var v: T = compiletime.uninitialized def foo(x: T): T = x diff --git a/tests/pos/t1035.scala b/tests/pos/t1035.scala index 9acf290b690d..e2dca3c6cc05 100644 --- a/tests/pos/t1035.scala +++ b/tests/pos/t1035.scala @@ -4,7 +4,7 @@ // 7/10/2008 class A { - var name:String = _ + var name:String = compiletime.uninitialized def getName() = name def this(name:String, age:Int) = {this(); this.name = name} diff --git a/tests/pos/t11437.scala b/tests/pos/t11437.scala index 4fe4ed518c5d..69166ebf5241 100644 --- a/tests/pos/t11437.scala +++ b/tests/pos/t11437.scala @@ -5,7 +5,7 @@ trait T { var adder2: Int => Int = _ + 3 // was: Error } class Regress { - var v: Int = _ + var v: Int = compiletime.uninitialized def f = 42 //var w: Int = (_) //Unbound placeholder parameter; incorrect use of _ } diff --git a/tests/pos/t2368.scala b/tests/pos/t2368.scala index 55affb2f84cd..33bbe182721a 100644 --- a/tests/pos/t2368.scala +++ b/tests/pos/t2368.scala @@ -1,4 +1,4 @@ class C { // A `var` field can be left uninitialized. - var x: String = _ + var x: String = compiletime.uninitialized } diff --git a/tests/pos/t2399.scala b/tests/pos/t2399.scala index a99998a0a959..72e612831791 100644 --- a/tests/pos/t2399.scala +++ b/tests/pos/t2399.scala @@ -4,7 +4,7 @@ trait That2[A, R <: That2[A, R]] trait T[A, This >: Null <: That1[A] with T[A, This]] extends That2[A, This] { self: This => - private var next: This = _ + private var next: This = compiletime.uninitialized def isEmpty = next eq null def length: Int = { diff --git a/tests/pos/t2698.scala b/tests/pos/t2698.scala index b97bdeeb136d..497b4f21e68b 100644 --- a/tests/pos/t2698.scala +++ b/tests/pos/t2698.scala @@ -9,6 +9,6 @@ abstract class S2 { val lang: WordExp type __labelT = lang._labelT - var deltaq: Array[__labelT] = _ + var deltaq: Array[__labelT] = compiletime.uninitialized def delta1 = immutable.Map(deltaq.zipWithIndex*) } diff --git a/tests/pos/tcpoly_seq.scala b/tests/pos/tcpoly_seq.scala index 312ba7405818..6fb8d0ced452 100644 --- a/tests/pos/tcpoly_seq.scala +++ b/tests/pos/tcpoly_seq.scala @@ -53,7 +53,7 @@ trait HOSeq { final class ListBuffer[A] { private var start: List[A] = Nil - private var last: ::[A] = _ + private var last: ::[A] = compiletime.uninitialized private var exported: Boolean = false /** Appends a single element to this buffer. diff --git a/tests/pos/tcpoly_seq_typealias.scala b/tests/pos/tcpoly_seq_typealias.scala index 25ec38065668..2e61e32bee13 100644 --- a/tests/pos/tcpoly_seq_typealias.scala +++ b/tests/pos/tcpoly_seq_typealias.scala @@ -55,7 +55,7 @@ trait HOSeq { final class ListBuffer[A] { private var start: List[A] = Nil - private var last: ::[A] = _ + private var last: ::[A] = compiletime.uninitialized private var exported: Boolean = false /** Appends a single element to this buffer. diff --git a/tests/pos/variances-constr.scala b/tests/pos/variances-constr.scala index e526b18414d2..0b475a5a3499 100644 --- a/tests/pos/variances-constr.scala +++ b/tests/pos/variances-constr.scala @@ -2,7 +2,7 @@ import language.`3.0-migration` class C[+A] { - private[this] var y: A = _ + private[this] var y: A = compiletime.uninitialized def getY: A = y class Inner(x: A) { diff --git a/tests/run-deep-subtype/colltest4/CollectionStrawMan4_1.scala b/tests/run-deep-subtype/colltest4/CollectionStrawMan4_1.scala index d5cb8a940eb2..c3f7d39bc3de 100644 --- a/tests/run-deep-subtype/colltest4/CollectionStrawMan4_1.scala +++ b/tests/run-deep-subtype/colltest4/CollectionStrawMan4_1.scala @@ -462,7 +462,7 @@ object CollectionStrawMan4 { -1 } def filter(p: A => Boolean): Iterator[A] = new Iterator[A] { - private var hd: A = _ + private var hd: A = compiletime.uninitialized private var hdDefined: Boolean = false def hasNext: Boolean = hdDefined || { diff --git a/tests/run/CollectionTests.scala b/tests/run/CollectionTests.scala index 4478c4160265..cba6725d676f 100644 --- a/tests/run/CollectionTests.scala +++ b/tests/run/CollectionTests.scala @@ -444,7 +444,7 @@ object CollectionStrawMan5 { -1 } def filter(p: A => Boolean): Iterator[A] = new Iterator[A] { - private var hd: A = _ + private var hd: A = compiletime.uninitialized private var hdDefined: Boolean = false def hasNext: Boolean = hdDefined || { diff --git a/tests/run/LazyLists.scala b/tests/run/LazyLists.scala index 6cf8c8cf8e50..d5d533fc64fd 100644 --- a/tests/run/LazyLists.scala +++ b/tests/run/LazyLists.scala @@ -1,10 +1,11 @@ package xcollections: import annotation.unchecked.uncheckedVariance + import compiletime.uninitialized abstract class LazyList[+T]: - private var myHead: T = _ - private var myTail: LazyList[T] = _ + private var myHead: T = uninitialized + private var myTail: LazyList[T] = uninitialized private var myForced: LazyList[T] | Null = null protected def force(): LazyList[T] diff --git a/tests/run/Signals.scala b/tests/run/Signals.scala index 18a1947dcaf0..1246896e940b 100644 --- a/tests/run/Signals.scala +++ b/tests/run/Signals.scala @@ -1,10 +1,11 @@ import annotation.unchecked._ +import compiletime.uninitialized package frp: sealed class Signal[+T](expr: Signal.Caller ?=> T): - private var myExpr: Signal.Caller => T = _ - private var myValue: T = _ + private var myExpr: Signal.Caller => T = uninitialized + private var myValue: T = uninitialized private var observers: Set[Signal.Caller] = Set() changeTo(expr) diff --git a/tests/run/Signals1.scala b/tests/run/Signals1.scala index 129965b4c2a5..cc83d4730152 100644 --- a/tests/run/Signals1.scala +++ b/tests/run/Signals1.scala @@ -8,7 +8,7 @@ package frp: object Signal: abstract class AbstractSignal[+T] extends Signal[T]: - private var currentValue: T = _ + private var currentValue: T = compiletime.uninitialized private var observers: Set[Caller] = Set() protected def eval: Caller => T diff --git a/tests/run/colltest5/CollectionStrawMan5_1.scala b/tests/run/colltest5/CollectionStrawMan5_1.scala index 3be18817b597..2ab82377d363 100644 --- a/tests/run/colltest5/CollectionStrawMan5_1.scala +++ b/tests/run/colltest5/CollectionStrawMan5_1.scala @@ -437,7 +437,7 @@ object CollectionStrawMan5 { -1 } def filter(p: A => Boolean): Iterator[A] = new Iterator[A] { - private var hd: A = _ + private var hd: A = compiletime.uninitialized private var hdDefined: Boolean = false def hasNext: Boolean = hdDefined || { diff --git a/tests/run/colltest6/CollectionStrawMan6_1.scala b/tests/run/colltest6/CollectionStrawMan6_1.scala index 16e404d3941b..91f77f553cce 100644 --- a/tests/run/colltest6/CollectionStrawMan6_1.scala +++ b/tests/run/colltest6/CollectionStrawMan6_1.scala @@ -5,6 +5,7 @@ import Predef.{augmentString => _, wrapString => _, _} import scala.reflect.ClassTag import annotation.unchecked.uncheckedVariance import annotation.tailrec +import compiletime.uninitialized class LowPriority { import CollectionStrawMan6._ @@ -607,7 +608,7 @@ object CollectionStrawMan6 extends LowPriority { class LazyList[+A](expr: => LazyList.Evaluated[A]) extends LinearSeq[A] with LinearSeqLike[A, LazyList] { private[this] var evaluated = false - private[this] var result: LazyList.Evaluated[A] = _ + private[this] var result: LazyList.Evaluated[A] = uninitialized def force: LazyList.Evaluated[A] = { if (!evaluated) { @@ -961,7 +962,7 @@ object CollectionStrawMan6 extends LowPriority { len } def filter(p: A => Boolean): Iterator[A] = new Iterator[A] { - private var hd: A = _ + private var hd: A = uninitialized private var hdDefined: Boolean = false def hasNext: Boolean = hdDefined || { diff --git a/tests/run/context-functions.scala b/tests/run/context-functions.scala index e71f0de10378..e2ed5bce00e7 100644 --- a/tests/run/context-functions.scala +++ b/tests/run/context-functions.scala @@ -28,7 +28,7 @@ object m extends A: def g(x: Boolean): Ctx[Int] = if x then summon[String].length else 0 val a: Ctx[Int] = summon[String].length - var b: Ctx[Int] = _ + var b: Ctx[Int] = compiletime.uninitialized b = summon[String].length def h(x: Int): Ctx[Int] = x + g(true) + f + a + b diff --git a/tests/run/decorators/WordSplitter.scala b/tests/run/decorators/WordSplitter.scala index 4195fa73a220..a18c08a57c27 100644 --- a/tests/run/decorators/WordSplitter.scala +++ b/tests/run/decorators/WordSplitter.scala @@ -3,7 +3,7 @@ class WordSplitter(str: String, start: Int = 0, isSeparator: Char => Boolean = _ extends Iterator[String]: private var idx: Int = start private var lastIdx: Int = start - private var word: String = _ + private var word: String = compiletime.uninitialized private def skipSeparators() = while idx < str.length && isSeparator(str(idx)) do diff --git a/tests/run/lazy-impl.scala b/tests/run/lazy-impl.scala index a941dc89100a..43333056973c 100644 --- a/tests/run/lazy-impl.scala +++ b/tests/run/lazy-impl.scala @@ -97,7 +97,7 @@ class C { println(s"initialize $name"); "result" } - @volatile private[this] var _x: AnyRef = _ + @volatile private[this] var _x: AnyRef = compiletime.uninitialized // Expansion of: lazy val x: String = init("x") diff --git a/tests/run/lst/Lst.scala b/tests/run/lst/Lst.scala index 63a8236ef211..c986425d52d5 100644 --- a/tests/run/lst/Lst.scala +++ b/tests/run/lst/Lst.scala @@ -3,6 +3,7 @@ package lst import collection.mutable.{ListBuffer, StringBuilder} import collection.immutable.Map import reflect.ClassTag +import compiletime.uninitialized /** A lightweight class for lists, optimized for short and medium lengths. * A list is represented at runtime as @@ -563,8 +564,8 @@ object Lst { class Buffer[T] { private var len = 0 - private var elem: Any = _ - private var elems: Arr = _ + private var elem: Any = uninitialized + private var elems: Arr = uninitialized def size = len diff --git a/tests/run/returning.scala b/tests/run/returning.scala index 33cfebf62fad..5879b9e58e5d 100644 --- a/tests/run/returning.scala +++ b/tests/run/returning.scala @@ -3,7 +3,7 @@ package scala.util.control { object NonLocalReturns { class ReturnThrowable[T] extends ControlThrowable { - private var myResult: T = _ + private var myResult: T = compiletime.uninitialized def throwReturn(result: T): Nothing = { myResult = result throw this diff --git a/tests/run/transparentPrivates.scala b/tests/run/transparentPrivates.scala index ce438ae8d8a0..7373c446707f 100644 --- a/tests/run/transparentPrivates.scala +++ b/tests/run/transparentPrivates.scala @@ -1,10 +1,11 @@ +import compiletime.uninitialized object Test { class C[T](private val x: T) { private def foo[Z](z: Z): T = x - private var y: T = _ + private var y: T = uninitialized inline def get1 = x inline def get2[U](c: C[U]) = c.x diff --git a/tests/run/tuples.scala b/tests/run/tuples.scala index 4980f2fe6975..beeb98092ec9 100644 --- a/tests/run/tuples.scala +++ b/tests/run/tuples.scala @@ -1,7 +1,7 @@ import Function._ object Test extends App { - var xyz: (Int, String, Boolean) = _ + var xyz: (Int, String, Boolean) = compiletime.uninitialized xyz = (1, "abc", true) Console.println(xyz) xyz match { diff --git a/tests/untried/neg/nested-fn-print.scala b/tests/untried/neg/nested-fn-print.scala index c599a235aba6..e443e7227a3e 100644 --- a/tests/untried/neg/nested-fn-print.scala +++ b/tests/untried/neg/nested-fn-print.scala @@ -1,6 +1,7 @@ +import compiletime.uninitialized object Test { - var x1: Int => Float => Double = _ - var x2: (Int => Float) => Double = _ + var x1: Int => Float => Double = uninitialized + var x2: (Int => Float) => Double = uninitialized var x3: Int => Double def main(args: Array[String]): Unit = { diff --git a/tests/untried/neg/sabin2.scala b/tests/untried/neg/sabin2.scala index 24a4e511a6d0..2a5dbcc136dc 100644 --- a/tests/untried/neg/sabin2.scala +++ b/tests/untried/neg/sabin2.scala @@ -2,7 +2,7 @@ object Test extends App { abstract class Base { type T - var x: T = _ + var x: T = compiletime.uninitialized class Inner { def set(y: T) = x = y def get() = x diff --git a/tests/untried/neg/t5352.scala b/tests/untried/neg/t5352.scala index ed74a840f0c0..7bfa7752f870 100644 --- a/tests/untried/neg/t5352.scala +++ b/tests/untried/neg/t5352.scala @@ -7,7 +7,7 @@ object boop { type BarF = { def f(): Int } - var x: BarF = _ + var x: BarF = compiletime.uninitialized x = xs.head x.f diff --git a/tests/untried/neg/t6566a.scala b/tests/untried/neg/t6566a.scala index 74a0b38e5689..b972281982d8 100644 --- a/tests/untried/neg/t6566a.scala +++ b/tests/untried/neg/t6566a.scala @@ -3,7 +3,7 @@ object WhatsYourTypeIsMyType { class Foo { val tc = new TypeCheat[Foo] - var x: tc.MyType = _ + var x: tc.MyType = compiletime.uninitialized def setX() = x = new Foo } class Bar extends Foo { diff --git a/tests/untried/neg/t6566b.scala b/tests/untried/neg/t6566b.scala index 0d488dbe8a6c..640a375fc5f9 100644 --- a/tests/untried/neg/t6566b.scala +++ b/tests/untried/neg/t6566b.scala @@ -4,7 +4,7 @@ object WhatsYourTypeIsMyType { } class Foo extends WithMyType[Foo] { - var x: MyType = _ + var x: MyType = compiletime.uninitialized def setX() = x = new Foo } diff --git a/tests/untried/neg/t963b.scala b/tests/untried/neg/t963b.scala index f3927cb09fd6..7a1f1385ef2a 100644 --- a/tests/untried/neg/t963b.scala +++ b/tests/untried/neg/t963b.scala @@ -7,7 +7,7 @@ trait A { object B { def f(x : { val y : A }): Unit = { x.y.v = x.y.v } - var a : A = _ + var a : A = compiletime.uninitialized var b : Boolean = false def y : A = { if (b) {