summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-04-30 22:56:06 +0000
committerMartin Odersky <odersky@gmail.com>2007-04-30 22:56:06 +0000
commit03f09f244ec0ce9fc3891a8eaab0a4024fae7d87 (patch)
treeaa20e0555b2e1dd9260cf1c13cd5eaa9ed96ff4d /src/compiler
parent750e57765b10d0f072eff68274047daa1c2040ae (diff)
downloadscala-03f09f244ec0ce9fc3891a8eaab0a4024fae7d87.tar.gz
scala-03f09f244ec0ce9fc3891a8eaab0a4024fae7d87.tar.bz2
scala-03f09f244ec0ce9fc3891a8eaab0a4024fae7d87.zip
added support for notnull, first steps
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala193
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala9
7 files changed, 132 insertions, 83 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index ff3b2a21d6..2baea3f4e2 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -156,6 +156,11 @@ abstract class TreeGen {
def mkAsInstanceOf(value: Tree, tpe: Type): Tree =
mkAsInstanceOf(value, tpe, global.phase.erasedTypes)
+ def mkCheckInit(tree: Tree): Tree =
+ if (tree.hasSymbol && tree.symbol.tpe <:< NotNullClass.tpe && !tree.symbol.tpe.isNotNull)
+ mkRuntimeCall(nme.checkInitialized, List(tree))
+ else tree
+
/** Builds a list with given head and tail. */
def mkNewCons(head: Tree, tail: Tree): Tree =
New(Apply(mkAttributedRef(definitions.ConsClass), List(head, tail)))
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 1c898082bc..67404caf12 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -106,6 +106,7 @@ trait Definitions {
def SeqFactory = getMember(ScalaRunTimeModule, nme.Seq);
def checkDefinedMethod = getMember(ScalaRunTimeModule, "checkDefined")
def isArrayMethod = getMember(ScalaRunTimeModule, "isArray")
+ var NotNullClass: Symbol = _
var BoxesUtilityModule: Symbol = _
var ComparatorModule: Symbol = _
def Comparator_equals = getMember(ComparatorModule, nme.equals_)
@@ -873,6 +874,7 @@ trait Definitions {
getClass(if (forMSIL) "System.IndexOutOfRangeException"
else "java.lang.IndexOutOfBoundsException")
ScalaRunTimeModule = getModule("scala.runtime.ScalaRunTime")
+ NotNullClass = getClass("scala.NotNull")
BoxesUtilityModule = getModule("scala.runtime.BoxesUtility")
ComparatorModule = getModule("scala.runtime.Comparator")
RepeatedParamClass = newCovariantPolyClass(
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 5afe99bed0..fd1893054c 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -247,7 +247,7 @@ trait StdNames {
val booleanValue = newTermName("booleanValue")
val box = newTermName("box")
val boxArray = newTermName("boxArray")
- val checkCastability = newTermName("checkCastability")
+ val checkInitialized = newTermName("checkInitialized")
val classOf = newTermName("classOf")
val coerce = newTermName("coerce")
val defaultValue = newTermName("defaultValue")
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 5e62b50f23..a1015eed4a 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -63,6 +63,55 @@ trait Types {
*/
var intersectionWitness = new HashMap[List[Type], Type]
+ /** A proxy for a type (identified by field `tp') that forwards all operations to it
+ * Every operation that is overridden for some kind of types should be forwarded.
+ */
+ trait TypeProxy extends Type {
+ val tp: Type
+
+ private def maybeRewrap(newtp: Type) = if (newtp eq tp) this else newtp
+
+ // the following are all operations in class Type that are overridden in some subclass
+ // Important to keep this up-to-date when new operations are added!
+ override def isTrivial = tp.isTrivial
+ override def symbol = tp.symbol
+ override def singleDeref = maybeRewrap(tp.singleDeref)
+ override def widen = maybeRewrap(tp.widen)
+ override def deconst = maybeRewrap(tp.deconst)
+ override def typeOfThis = tp.typeOfThis
+ override def narrow = tp.narrow
+ override def bounds = tp.bounds
+ override def parents = tp.parents
+ override def prefix = tp.prefix
+ override def typeArgs = tp.typeArgs
+ override def resultType = maybeRewrap(tp.resultType)
+ override def finalResultType = maybeRewrap(tp.finalResultType)
+ override def paramSectionCount = tp.paramSectionCount
+ override def paramTypes = tp.paramTypes
+ override def typeParams = tp.typeParams
+ override def notNull = maybeRewrap(tp.notNull)
+ override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) =
+ tp.instantiateTypeParams(formals, actuals)
+ override def isHigherKinded: boolean = tp.isHigherKinded
+ override def normalize = maybeRewrap(tp.normalize)
+ override def isError = tp.isError
+ override def isErroneous = tp.isErroneous
+ override def isStable: boolean = tp.isStable
+ override def isNotNull = tp.isNotNull
+ override def decls = tp.decls
+ override def baseType(clazz: Symbol) = tp.baseType(clazz)
+ override def closure = tp.closure
+ override def closureDepth = tp.closureDepth
+ override def baseClasses = tp.baseClasses
+ override def cloneInfo(owner: Symbol) = maybeRewrap(tp.cloneInfo(owner))
+ override def prefixString = tp.prefixString
+ override def isComplete = tp.isComplete
+ override def complete(sym: Symbol) = tp.complete(sym)
+ override def load(sym: Symbol): unit = tp.load(sym)
+ override def withAttributes(attribs: List[AnnotationInfo[Any]]) = tp.withAttributes(attribs)
+ override def withoutAttributes = tp.withoutAttributes
+ }
+
/** The base class for all types */
abstract class Type {
@@ -85,9 +134,13 @@ trait Types {
* identity for all other types */
def widen: Type = this
+ /** Map a constant type or not-null-type to its underlying base type,
+ * identity for all other types */
+ def deconst: Type = this
+
/** The type of <code>this</code> of a class type or reference type
*/
- def typeOfThis = symbol.typeOfThis
+ def typeOfThis: Type = symbol.typeOfThis
/** Map to a this type which is a subtype of this type.
*/
@@ -95,10 +148,6 @@ trait Types {
if (phase.erasedTypes) this
else refinedType(List(this), commonOwner(this), EmptyScope).narrow
- /** Map a constant type to its underlying base type,
- * identity for all other types */
- def deconst: Type = this
-
/** For a TypeBounds type, itself;
* for a reference denoting an abstract type, its bounds,
* for all other types, a TypeBounds type all of whose bounds are this type.
@@ -137,6 +186,10 @@ trait Types {
* the empty list for all other types */
def typeParams: List[Symbol] = List()
+ /** Mixin a NotNull trait unless type already has one */
+ def notNull: Type =
+ if (isNotNull) this else NotNullType(this)
+
/** Replace formal type parameter symbols with actual type arguments.
*
* Amounts to substitution except for higher-kinded types. (See overridden method in TypeRef) -- @M (contact adriaan.moors at cs.kuleuven.be)
@@ -162,12 +215,12 @@ trait Types {
/** Does this type denote a stable reference (i.e. singleton type)? */
def isStable: boolean = false
+ /** Is this type guaranteed not to have `null' as a value? */
+ def isNotNull: boolean = false
+
/** Does this type denote a reference type which can be null? */
// def isNullable: boolean = false
- /** Is this type guaranteed to be non-null? */
- // def isNonNull: boolean = false
-
/** For a classtype or refined type, its defined or declared members;
* inherited by subtypes and typerefs.
* The empty scope for all other types */
@@ -549,7 +602,14 @@ trait Types {
override def closure: Array[Type] = supertype.closure
override def closureDepth: int = supertype.closureDepth
override def baseClasses: List[Symbol] = supertype.baseClasses
- // override def isNonNull = supertype.isNonNull
+ override def isNotNull = supertype.isNotNull
+ }
+
+ case class NotNullType(tp: Type) extends SubType with TypeProxy {
+ override def supertype = tp
+ override def isNotNull: boolean = true
+ override def deconst: Type = tp
+ override def toString(): String = supertype.toString() + " with NotNull"
}
/** A base class for types that represent a single value
@@ -618,7 +678,7 @@ trait Types {
case class ThisType(sym: Symbol) extends SingletonType {
//assert(sym.isClass && !sym.isModuleClass || sym.isRoot, sym)
override def isTrivial: boolean = sym.isPackageClass
- // override def isNonNull = true
+ override def isNotNull = true
override def symbol = sym
override def singleDeref: Type = sym.typeOfThis
override def prefixString =
@@ -641,7 +701,7 @@ trait Types {
case class SingleType(pre: Type, sym: Symbol) extends SingletonType {
override val isTrivial: boolean = pre.isTrivial
// override def isNullable = supertype.isNullable
- // override def isNonNull = supertype.isNonNull
+ override def isNotNull = supertype.isNotNull
private var singleDerefCache: Type = _
private var singleDerefPeriod = NoPeriod
override def singleDeref: Type = {
@@ -677,7 +737,7 @@ trait Types {
case class SuperType(thistpe: Type, supertp: Type) extends SingletonType {
override val isTrivial: boolean = thistpe.isTrivial && supertp.isTrivial
- // override def isNonNull = true;
+ override def isNotNull = true;
override def symbol = thistpe.symbol
override def singleDeref = supertp
override def prefix: Type = supertp.prefix
@@ -860,7 +920,7 @@ trait Types {
symbol.thisType
}
- // override def isNonNull: boolean = parents forall (.isNonNull);
+ override def isNotNull: boolean = parents exists (.isNotNull)
// override def isNullable: boolean =
// parents forall (p => p.isNullable && !p.symbol.isAbstractType);
@@ -1025,8 +1085,11 @@ trait Types {
case class ConstantType(value: Constant) extends SingletonType {
assert(value.tpe.symbol != UnitClass)
override def isTrivial: boolean = true
+ override def isNotNull = value.value != null
override def symbol: Symbol = value.tpe.symbol
- override def singleDeref: Type = value.tpe //M@ probably ok since constants don't take type params?
+ override def singleDeref: Type =
+ if (value.value.isInstanceOf[String]) value.tpe
+ else value.tpe
override def deconst: Type = value.tpe
override def toString(): String =
value.tpe.toString() + "(" + value.escapedStringValue + ")"
@@ -1320,7 +1383,7 @@ A type's symbol should never be inspected directly.
* to the core compiler, but can be observed by type-system plugins. The
* core compiler does take care to propagate attributes and to save them
* in the symbol tables of object files. */
- case class AnnotatedType(attributes: List[AnnotationInfo[Any]], tp: Type) extends Type {
+ case class AnnotatedType(attributes: List[AnnotationInfo[Any]], tp: Type) extends TypeProxy {
override def toString(): String = {
val attString =
if (attributes.isEmpty)
@@ -1339,20 +1402,7 @@ A type's symbol should never be inspected directly.
/** Remove any attributes from this type */
override def withoutAttributes = tp.withoutAttributes
- override def isTrivial: boolean = tp.isTrivial
-
- /** Return the argument, unless it is eq to tp, in which case return the
- * receiver. This method is used for methods like singleDeref and widen,
- * so that the attributes are remembered more frequently. */
- private def maybeRewrap(newtp: Type) =
- if (newtp eq tp) this else newtp
-
- // ---------------- methods forwarded to tp ------------------ \\
-
- override def symbol: Symbol = tp.symbol
- override def singleDeref: Type = maybeRewrap(tp.singleDeref)
- override def widen: Type = maybeRewrap(tp.widen)
- override def deconst: Type = maybeRewrap(tp.deconst)
+ /** Martin to Lex: I don't understand what the following 2 method do? */
override def bounds: TypeBounds = {
val oftp = tp.bounds
oftp match {
@@ -1360,17 +1410,6 @@ A type's symbol should never be inspected directly.
case _ => oftp
}
}
- override def parents: List[Type] = tp.parents
- override def prefix: Type = tp.prefix
- override def typeArgs: List[Type] = tp.typeArgs
- override def resultType: Type = maybeRewrap(tp.resultType)
- override def finalResultType: Type = maybeRewrap(tp.finalResultType)
- override def paramSectionCount: int = tp.paramSectionCount
- override def paramTypes: List[Type] = tp.paramTypes
- override def typeParams: List[Symbol] = tp.typeParams
- override def isStable: boolean = tp.isStable
- override def nonPrivateDecl(name: Name): Symbol = tp.nonPrivateDecl(name)
- override def baseType(clazz: Symbol): Type = tp.baseType(clazz)
override def closure: Array[Type] = {
val oftp = tp.closure
if ((oftp.length == 1 &&) (oftp(0) eq this))
@@ -1378,14 +1417,6 @@ A type's symbol should never be inspected directly.
else
oftp
}
- override def closureDepth: int = tp.closureDepth
- override def baseClasses: List[Symbol] = tp.baseClasses
- override def cloneInfo(owner: Symbol) = maybeRewrap(cloneInfo(owner))
- override def isComplete: boolean = tp.isComplete
- override def complete(sym: Symbol) = tp.complete(sym)
- override def load(sym: Symbol): unit = tp.load(sym)
- override def findMember(name: Name, excludedFlags: int, requiredFlags: long, stableOnly: boolean): Symbol =
- tp.findMember(name, excludedFlags, requiredFlags, stableOnly)
}
/** A class representing an as-yet unevaluated type.
@@ -1750,12 +1781,14 @@ A type's symbol should never be inspected directly.
case TypeVar(_, constr) =>
if (constr.inst != NoType) this(constr.inst)
else tp
+ case NotNullType(tp) =>
+ val tp1 = this(tp)
+ if (tp1 eq tp) tp
+ else NotNullType(tp1)
case AnnotatedType(attribs, atp) =>
val atp1 = this(atp)
- if (atp1 eq atp)
- tp
- else
- AnnotatedType(attribs, atp1)
+ if (atp1 eq atp) tp
+ else AnnotatedType(attribs, atp1)
case _ =>
tp
// throw new Error("mapOver inapplicable for " + tp);
@@ -2105,6 +2138,7 @@ A type's symbol should never be inspected directly.
case MethodType(_, _) => mapOver(tp)
case TypeVar(_, _) => mapOver(tp)
case AnnotatedType(_,_) => mapOver(tp)
+ case NotNullType(_) => mapOver(tp)
case _ => tp
}
}
@@ -2290,7 +2324,10 @@ A type's symbol should never be inspected directly.
} finally {
pendingSubTypes -= p
}
- } else isSubType0(tp1, tp2)
+ } else {
+ isSubType0(tp1, tp2)
+ }
+
} finally {
stc = stc - 1
}
@@ -2322,7 +2359,9 @@ A type's symbol should never be inspected directly.
case (SingleType(_, _), SingleType(_, _)) => tp1 =:= tp2
case (ConstantType(_), ConstantType(_)) => tp1 =:= tp2
- case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) if !(tp1.isHigherKinded || tp2.isHigherKinded) => //Console.println("isSubType " + tp1 + " " + tp2);//DEBUG
+ case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2))
+ if !(tp1.isHigherKinded || tp2.isHigherKinded) =>
+ //Console.println("isSubType " + tp1 + " " + tp2);//DEBUG
if (inIDE) { trackTypeIDE(sym1); trackTypeIDE(sym2); }
def isSubArgs(tps1: List[Type], tps2: List[Type],
@@ -2342,15 +2381,14 @@ A type's symbol should never be inspected directly.
||
sym2.isAbstractType && !(tp2 =:= tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo)
||
-// sym2 == NonNullClass && tp1.isNonNull
-// ||
- sym2.isClass &&
- ({ val base = tp1 baseType sym2; !(base eq tp1) && (base <:< tp2) })
+ sym2.isClass &&
+ ({ val base = tp1 baseType sym2; !(base eq tp1) && (base <:< tp2) })
||
- sym1 == AllClass
+ sym1 == AllClass
||
// Console.println("last chance " + sym1 + " " + sym2 + " " + sym2.isClass + " " (sym2 isSubClass ObjectClass))
- sym1 == AllRefClass && sym2.isClass && sym2 != AllClass && (sym2 isSubClass ObjectClass))
+ sym1 == AllRefClass &&
+ sym2.isClass && (sym2 isNonBottomSubClass ObjectClass) && (!(tp2.normalize.symbol isNonBottomSubClass NotNullClass)))
case (MethodType(pts1, res1), MethodType(pts2, res2)) =>
(pts1.length == pts2.length &&
matchingParams(pts1, pts2, tp2.isInstanceOf[JavaMethodType]) &&
@@ -2377,16 +2415,21 @@ A type's symbol should never be inspected directly.
atp1 <:< tp2
case (_, AnnotatedType(_,atp2)) =>
tp1 <:< atp2
+ case (NotNullType(ntp1), _) =>
+ ntp1 <:< tp2
+ case (_, NotNullType(ntp2)) =>
+ tp1.isNotNull && tp1 <:< ntp2
case (_, _) if (tp1.isHigherKinded || tp2.isHigherKinded) =>
- (tp1.symbol == AllClass
+ (tp1.symbol == AllClass
||
- tp2.symbol == AnyClass // @M Any and Nothing are super-type resp. subtype of every well-kinded type
+ tp2.symbol == AnyClass // @M Any and Nothing are super-type resp. subtype of every well-kinded type
|| // @M! normalize reduces higher-kinded case to PolyType's
- (tp1.isHigherKinded && tp2.isHigherKinded) && isSubType0(tp1.normalize, tp2.normalize))
+ (tp1.isHigherKinded && tp2.isHigherKinded) && isSubType0(tp1.normalize, tp2.normalize))
case (_, TypeRef(pre2, sym2, args2))
- if sym2.isAbstractType && !(tp2 =:= tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo) && {
- if (!inIDE) true else trackTypeIDE(sym2)
- } => true
+ if (sym2.isAbstractType && !(tp2 =:= tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo) &&
+ (if (!inIDE) true else trackTypeIDE(sym2)) ||
+ sym2 == NotNullClass && tp1.isNotNull) =>
+ true
case (_, RefinedType(parents2, ref2)) =>
(parents2 forall tp1.<:<) && (ref2.toList forall tp1.specializes) &&
(!parents2.exists(.symbol.isAbstractType) || tp1.symbol != AllRefClass)
@@ -2399,24 +2442,20 @@ A type's symbol should never be inspected directly.
once patern matching bug is fixed */
case (ThisType(_), _) => tp1.singleDeref <:< tp2
case (SingleType(_, _), _) => tp1.singleDeref <:< tp2
- case (ConstantType(_), _) => tp1.singleDeref <:< tp2
+ case (ConstantType(_), _) =>
+ tp1.singleDeref <:< tp2
case (TypeRef(pre1, sym1, args1), _) =>
if (inIDE) trackTypeIDE(sym1)
(sym1 == AllClass && tp2 <:< AnyClass.tpe
||
sym1 == AllRefClass && tp2.isInstanceOf[SingletonType] && (tp1 <:< tp2.widen))
-/* ||
- sym1 == AllRefClass && tp2.symbol != AllClass &&
- tp2 <:< AnyRefClass.tpe))
- if (X) tp2.isNullable
- else tp2.symbol != AllClass && tp2 <:< AnyRefClass.tpe))*/
case _ =>
false
}
} || {
- val tp1n= tp1.normalize
- val tp2n= tp2.normalize
+ val tp1n = tp1.normalize
+ val tp2n = tp2.normalize
((tp1n ne tp1) || (tp2n ne tp2)) && isSubType0(tp1n, tp2n)
}
@@ -2626,7 +2665,7 @@ A type's symbol should never be inspected directly.
/** The least upper bound wrt &lt;:&lt; of a list of types */
def lub(ts: List[Type], depth: int): Type = {
- def lub0(ts0: List[Type]): Type = elimSub(ts0 map (.deconst)) match {
+ def lub0(ts0: List[Type]): Type = elimSub(ts0 map (_.deconst)) match {
case List() => AllClass.tpe
case List(t) => t
case ts @ PolyType(tparams, _) :: _ =>
@@ -2702,7 +2741,7 @@ A type's symbol should never be inspected directly.
// indent = indent.substring(0, indent.length() - 2)
// log(indent + "lub of " + ts + " is " + res)//debug
// }
- res
+ if (ts forall (_.isNotNull)) res.notNull else res
}
def glb(ts: List[Type]): Type = glb(ts, maxClosureDepth(ts) + LubGlbMargin)
@@ -2791,7 +2830,7 @@ A type's symbol should never be inspected directly.
indent = indent.substring(0, indent.length() - 2)
log(indent + "glb of " + ts + " is " + res)//debug
}
- res
+ if (ts exists (_.isNotNull)) res.notNull else res
}
/** The most deeply nested owner that contains all the symbols
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index b8abc66fa9..d9bd6cc225 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -502,7 +502,7 @@ abstract class Mixin extends InfoTransform {
case _ => Select(This(clazz), sym.accessed)
}
if (sym.isSetter) Assign(accessedRef, Ident(vparams.head))
- else accessedRef
+ else gen.mkCheckInit(accessedRef)
})
} else if (sym.isModule && !(sym hasFlag LIFTED | BRIDGE)) {
// add modules
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index a2760218e9..7b0eb3bc2c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -471,7 +471,7 @@ trait Namers requires Analyzer {
val tparamSyms = typer.reenterTypeParams(tparams)
var vparamSymss = enterValueParams(meth, vparamss)
- if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) tpt.tpe = context.enclClass.owner.tpe
+ if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) tpt.tpe = context.enclClass.owner.tpe.notNull
if (onlyPresentation)
methodArgumentNames(meth) = vparamss.map(.map(.symbol));
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index f9f3fd2b67..6ef190be69 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -987,7 +987,9 @@ trait Typers requires Analyzer {
getter.attributes = value.initialize.attributes
val result = DefDef(getter, vparamss =>
if (mods hasFlag DEFERRED) EmptyTree
- else typed(atPos(vdef.pos)(Select(This(value.owner), value)), EXPRmode, value.tpe))
+ else typed(
+ atPos(vdef.pos) { gen.mkCheckInit(Select(This(value.owner), value)) },
+ EXPRmode, value.tpe))
result.tpt.asInstanceOf[TypeTree] setOriginal tpt /* setPos tpt.pos */
checkNoEscaping.privates(getter, result.tpt)
copy.DefDef(result, result.mods withAnnotations mods.annotations, result.name,
@@ -1777,8 +1779,9 @@ trait Typers requires Analyzer {
val elemtpt1 = typedType(elemtpt)
val elems1 = List.mapConserve(elems)(elem => typed(elem, mode, elemtpt1.tpe))
copy.ArrayValue(tree, elemtpt1, elems1)
- .setType(if (isFullyDefined(pt) && !phase.erasedTypes) pt
- else appliedType(ArrayClass.typeConstructor, List(elemtpt1.tpe)))
+ .setType(
+ (if (isFullyDefined(pt) && !phase.erasedTypes) pt
+ else appliedType(ArrayClass.typeConstructor, List(elemtpt1.tpe))).notNull)
}
def typedAssign(lhs: Tree, rhs: Tree): Tree = {