Skip to content

Commit

Permalink
Merge pull request #49 from noti0na1/dotty-explicit-nulls-notNull
Browse files Browse the repository at this point in the history
Add predicate to check out of order for mutable variables
  • Loading branch information
noti0na1 authored Dec 12, 2019
2 parents 3bb1b82 + d26b424 commit a8f3dc1
Show file tree
Hide file tree
Showing 215 changed files with 1,883 additions and 725 deletions.
2 changes: 0 additions & 2 deletions .github/ISSUE_TEMPLATE/bug.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,3 @@ println("hello, world")


## expectation


2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/crash.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name: "\U0001F4A5 Crash report"
about: Report a Dotty Compiler compiler crash
title: ''
labels: itype:bug
labels: itype:bug, itype:crash
assignees: ''

---
Expand Down
5 changes: 1 addition & 4 deletions .github/ISSUE_TEMPLATE/feature.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@
name: "\U0001F389 Suggest a feature"
about: Please create a feature request here https://github.com/lampepfl/dotty-feature-requests
title: ''
labels:
labels: ''
assignees: ''

---

Please create a feature request here: [lampepfl/dotty-feature-requests](https://github.com/lampepfl/dotty-feature-requests).



7 changes: 2 additions & 5 deletions .github/ISSUE_TEMPLATE/syntax-highlight.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
---
name: "Syntax highlighting"
name: Syntax highlighting
about: Please create a syntax highlighting issue here https://github.com/scala/vscode-scala-syntax/issues
title: ''
labels:
labels: ''
assignees: ''

---

Please create a syntax highlighting issue here: [scala/vscode-scala-syntax](https://github.com/scala/vscode-scala-syntax/issues).



26 changes: 11 additions & 15 deletions compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1224,23 +1224,20 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
}

/* Emit code to compare the two top-most stack values using the 'op' operator. */
private def genCJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label): Unit = {
if (targetIfNoJump == success) genCJUMP(failure, success, op.negate(), tk, targetIfNoJump)
private def genCJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label, negated: Boolean = false): Unit = {
if (targetIfNoJump == success) genCJUMP(failure, success, op.negate(), tk, targetIfNoJump, negated = !negated)
else {
if (tk.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT
bc.emitIF_ICMP(op, success)
} else if (tk.isRef) { // REFERENCE(_) | ARRAY(_)
bc.emitIF_ACMP(op, success)
} else {
import Primitives._
def useCmpG = if (negated) op == GT || op == GE else op == LT || op == LE
(tk: @unchecked) match {
case LONG => emit(asm.Opcodes.LCMP)
case FLOAT =>
if (op == LT || op == LE) emit(asm.Opcodes.FCMPL)
else emit(asm.Opcodes.FCMPG)
case DOUBLE =>
if (op == LT || op == LE) emit(asm.Opcodes.DCMPL)
else emit(asm.Opcodes.DCMPG)
case FLOAT => emit(if (useCmpG) asm.Opcodes.FCMPG else asm.Opcodes.FCMPL)
case DOUBLE => emit(if (useCmpG) asm.Opcodes.DCMPG else asm.Opcodes.DCMPL)
}
bc.emitIF(op, success)
}
Expand All @@ -1249,9 +1246,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
}

/* Emits code to compare (and consume) stack-top and zero using the 'op' operator */
private def genCZJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label): Unit = {
private def genCZJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label, negated: Boolean = false): Unit = {
import Primitives._
if (targetIfNoJump == success) genCZJUMP(failure, success, op.negate(), tk, targetIfNoJump)
if (targetIfNoJump == success) genCZJUMP(failure, success, op.negate(), tk, targetIfNoJump, negated = !negated)
else {
if (tk.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT
bc.emitIF(op, success)
Expand All @@ -1261,18 +1258,17 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
case NE => bc emitIFNONNULL success
}
} else {
def useCmpG = if (negated) op == GT || op == GE else op == LT || op == LE
(tk: @unchecked) match {
case LONG =>
emit(asm.Opcodes.LCONST_0)
emit(asm.Opcodes.LCMP)
case FLOAT =>
emit(asm.Opcodes.FCONST_0)
if (op == LT || op == LE) emit(asm.Opcodes.FCMPL)
else emit(asm.Opcodes.FCMPG)
emit(if (useCmpG) asm.Opcodes.FCMPG else asm.Opcodes.FCMPL)
case DOUBLE =>
emit(asm.Opcodes.DCONST_0)
if (op == LT || op == LE) emit(asm.Opcodes.DCMPL)
else emit(asm.Opcodes.DCMPG)
emit(if (useCmpG) asm.Opcodes.DCMPG else asm.Opcodes.DCMPL)
}
bc.emitIF(op, success)
}
Expand All @@ -1287,8 +1283,8 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
case ScalaPrimitivesOps.NE => Primitives.NE
case ScalaPrimitivesOps.LT => Primitives.LT
case ScalaPrimitivesOps.LE => Primitives.LE
case ScalaPrimitivesOps.GE => Primitives.GE
case ScalaPrimitivesOps.GT => Primitives.GT
case ScalaPrimitivesOps.GE => Primitives.GE
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {

override def getCurrentCUnit(): CompilationUnit = { cunit }

/* ---------------- helper utils for generating classes and fiels ---------------- */
/* ---------------- helper utils for generating classes and fields ---------------- */

def genPlainClass(cd: ClassDef) = cd match {
case ClassDef(_, _, _, impl) =>
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder {
* ------
*/

// a note on terminology: this is not "postHandlers", despite appearences.
// a note on terminology: this is not "postHandlers", despite appearances.
// "postHandlers" as in the source-code view. And from that perspective, both (3.A) and (3.B) are invisible implementation artifacts.
if (hasFinally) withFreshCleanupScope {
nopIfNeeded(startTryBody)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/backend/jvm/BTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ abstract class BTypes {
*
* - Initializer block (JLS 8.6 / 8.7): block of statements in a java class
* - static initializer: executed before constructor body
* - instance initializer: exectued when class is initialized (instance creation, static
* - instance initializer: executed when class is initialized (instance creation, static
* field access, ...)
*
* - A static nested class can be defined as
Expand Down
9 changes: 7 additions & 2 deletions compiler/src/dotty/tools/dotc/CompilationUnit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,14 @@ object CompilationUnit {
unit1
}

def apply(source: SourceFile)(implicit ctx: Context): CompilationUnit = {
/** Create a compilation unit corresponding to `source`.
* If `mustExist` is true, this will fail if `source` does not exist.
*/
def apply(source: SourceFile, mustExist: Boolean = true)(implicit ctx: Context): CompilationUnit = {
val src =
if (source.file.isDirectory) {
if (!mustExist)
source
else if (source.file.isDirectory) {
ctx.error(s"expected file, received directory '${source.file.path}'")
NoSource
}
Expand Down
30 changes: 22 additions & 8 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,26 @@ object desugar {
flatTree(cdef1 :: companions ::: implicitWrappers)
}.reporting(i"desugared: $result", Printers.desugar)

/** Expand
*
* package object name { body }
*
* to:
*
* package name {
* object `package` { body }
* }
*/
def packageModuleDef(mdef: ModuleDef)(implicit ctx: Context): Tree =
val impl = mdef.impl
val mods = mdef.mods
val moduleName = normalizeName(mdef, impl).asTermName
if (mods.is(Package))
PackageDef(Ident(moduleName),
cpy.ModuleDef(mdef)(nme.PACKAGE, impl).withMods(mods &~ Package) :: Nil)
else
mdef

/** Expand
*
* object name extends parents { self => body }
Expand Down Expand Up @@ -854,7 +874,7 @@ object desugar {
ctx.warning(em"${hl("final")} modifier is redundant for objects", flagSourcePos(Final))

if (mods.is(Package))
PackageDef(Ident(moduleName), cpy.ModuleDef(mdef)(nme.PACKAGE, impl).withMods(mods &~ Package) :: Nil)
packageModuleDef(mdef)
else if (isEnumCase) {
typeParamIsReferenced(enumClass.typeParams, Nil, Nil, impl.parents)
// used to check there are no illegal references to enum's type parameters in parents
Expand Down Expand Up @@ -1229,12 +1249,6 @@ object desugar {
case _ =>
false

/** Does this package contains at least one top-level definition
* that will require a wrapping object ?
*/
def hasTopLevelDef(pdef: PackageDef)(given Context): Boolean =
pdef.stats.exists(isTopLevelDef)

/** Assuming `src` contains top-level definition, returns the name that should
* be using for the package object that will wrap them.
*/
Expand Down Expand Up @@ -1758,7 +1772,7 @@ object desugar {
case Block(Nil, expr) =>
collect(expr)
case Quote(expr) =>
new TreeTraverser {
new UntypedTreeTraverser {
def traverse(tree: untpd.Tree)(implicit ctx: Context): Unit = tree match {
case Splice(expr) => collect(expr)
case TypSplice(expr) =>
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Thicket(valdef, clsdef)
}

/** A `_' with given type */
/** A `_` with given type */
def Underscore(tp: Type)(implicit ctx: Context): Ident = untpd.Ident(nme.WILDCARD).withType(tp)

def defaultValue(tpe: Type)(implicit ctx: Context): Tree = {
Expand Down Expand Up @@ -959,7 +959,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
receiver.select(defn.Object_ne).appliedTo(nullLiteral).withSpan(tree.span)
}

/** If inititializer tree is `_', the default value of its type,
/** If inititializer tree is `_`, the default value of its type,
* otherwise the tree itself.
*/
def wildcardToDefault(implicit ctx: Context): Tree =
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class ScalaSettings extends Settings.SettingGroup {
val XshowPhases: Setting[Boolean] = BooleanSetting("-Xshow-phases", "Print all compiler phases")
val XnoValueClasses: Setting[Boolean] = BooleanSetting("-Xno-value-classes", "Do not use value classes. Helps debugging.")
val XreplLineWidth: Setting[Int] = IntSetting("-Xrepl-line-width", "Maximal number of columns per line for REPL output", 390)
val XreplDisableDisplay: Setting[Boolean] = BooleanSetting("-Xrepl-disable-display", "Do not display definitions in REPL.")
val XfatalWarnings: Setting[Boolean] = BooleanSetting("-Xfatal-warnings", "Fail the compilation if there are any warnings.")
val XverifySignatures: Setting[Boolean] = BooleanSetting("-Xverify-signatures", "Verify generic signatures in generated bytecode.")
val XignoreScala2Macros: Setting[Boolean] = BooleanSetting("-Xignore-scala2-macros", "Ignore errors when compiling code that calls Scala2 macros, these will fail at runtime.")
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,10 @@ object Contexts {
else {
val newCtx = fresh.setSource(source)
if (newCtx.compilationUnit == null)
newCtx.setCompilationUnit(CompilationUnit(source))
// `source` might correspond to a file not necessarily
// in the current project (e.g. when inlining library code),
// so set `mustExist` to false.
newCtx.setCompilationUnit(CompilationUnit(source, mustExist = false))
sourceCtx = sourceCtx.updated(source, newCtx)
newCtx
}
Expand Down
24 changes: 15 additions & 9 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -459,12 +459,12 @@ class Definitions {
@tu lazy val Boolean_|| : Symbol = BooleanClass.requiredMethod(nme.ZOR)
@tu lazy val Boolean_== : Symbol =
BooleanClass.info.member(nme.EQ).suchThat(_.info.firstParamTypes match {
case List(pt) => (pt isRef BooleanClass)
case List(pt) => pt.isRef(BooleanClass)
case _ => false
}).symbol
@tu lazy val Boolean_!= : Symbol =
BooleanClass.info.member(nme.NE).suchThat(_.info.firstParamTypes match {
case List(pt) => (pt isRef BooleanClass)
case List(pt) => pt.isRef(BooleanClass)
case _ => false
}).symbol

Expand Down Expand Up @@ -527,7 +527,7 @@ class Definitions {
@tu lazy val StringModule: Symbol = StringClass.linkedClass
@tu lazy val String_+ : TermSymbol = enterMethod(StringClass, nme.raw.PLUS, methOfAny(StringType), Final)
@tu lazy val String_valueOf_Object: Symbol = StringModule.info.member(nme.valueOf).suchThat(_.info.firstParamTypes match {
case List(pt) => (pt isRef AnyClass) || (pt isRef ObjectClass)
case List(pt) => pt.isRef(AnyClass) || pt.isRef(ObjectClass)
case _ => false
}).symbol

Expand All @@ -539,15 +539,15 @@ class Definitions {
@tu lazy val ClassCastExceptionClass: ClassSymbol = ctx.requiredClass("java.lang.ClassCastException")
@tu lazy val ClassCastExceptionClass_stringConstructor: TermSymbol = ClassCastExceptionClass.info.member(nme.CONSTRUCTOR).suchThat(_.info.firstParamTypes match {
case List(pt) =>
val pt1 = if (ctx.explicitNulls) pt.stripNull else pt
pt1 isRef StringClass
val pt1 = if (ctx.explicitNulls) pt.stripNull() else pt
pt1.isRef(StringClass)
case _ => false
}).symbol.asTerm
@tu lazy val ArithmeticExceptionClass: ClassSymbol = ctx.requiredClass("java.lang.ArithmeticException")
@tu lazy val ArithmeticExceptionClass_stringConstructor: TermSymbol = ArithmeticExceptionClass.info.member(nme.CONSTRUCTOR).suchThat(_.info.firstParamTypes match {
case List(pt) =>
val pt1 = if (ctx.explicitNulls) pt.stripNull else pt
pt1 isRef StringClass
val pt1 = if (ctx.explicitNulls) pt.stripNull() else pt
pt1.isRef(StringClass)
case _ => false
}).symbol.asTerm

Expand Down Expand Up @@ -822,16 +822,22 @@ class Definitions {
// create Symbols for the ones that are present, so they can be checked during nullification.
@tu lazy val NotNullAnnots: List[ClassSymbol] = ctx.getClassesIfDefined(
"javax.annotation.Nonnull" ::
"edu.umd.cs.findbugs.annotations.NonNull" ::
"javax.validation.constraints.NotNull" ::
"androidx.annotation.NonNull" ::
"android.support.annotation.NonNull" ::
"android.annotation.NonNull" ::
"com.android.annotations.NonNull" ::
"org.eclipse.jdt.annotation.NonNull" ::
"edu.umd.cs.findbugs.annotations.NonNull" ::
"org.checkerframework.checker.nullness.qual.NonNull" ::
"org.checkerframework.checker.nullness.compatqual.NonNullDecl" ::
"org.jetbrains.annotations.NotNull" ::
"org.springframework.lang.NonNull" ::
"org.springframework.lang.NonNullApi" ::
"org.springframework.lang.NonNullFields" ::
"lombok.NonNull" ::
"reactor.util.annotation.NonNull" ::
"reactor.util.annotation.NonNullApi" ::
"io.reactivex.annotations.NonNull" :: Nil map PreNamedString)

// convenient one-parameter method types
Expand Down Expand Up @@ -886,7 +892,7 @@ class Definitions {
if (ctx.erasedTypes) JavaArrayType(elem)
else ArrayType.appliedTo(elem :: Nil)
def unapply(tp: Type)(implicit ctx: Context): Option[Type] = tp.dealias match {
case AppliedType(at, arg :: Nil) if at isRef ArrayType.symbol => Some(arg)
case AppliedType(at, arg :: Nil) if at.isRef(ArrayType.symbol) => Some(arg)
case _ => None
}
}
Expand Down
12 changes: 9 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Denotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ object Denotations {
*/
def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): PreDenotation

/** Map `f` over all single denotations and aggregate the results with `g`. */
def aggregate[T](f: SingleDenotation => T, g: (T, T) => T): T

private var cachedPrefix: Type = _
private var cachedAsSeenFrom: AsSeenFromResult = _
private var validAsSeenFrom: Period = Nowhere
Expand Down Expand Up @@ -459,7 +462,7 @@ object Denotations {
/** Sym preference provided types also override */
def prefer(sym1: Symbol, sym2: Symbol, info1: Type, info2: Type) =
preferSym(sym1, sym2) &&
info1.overrides(info2, sym1.matchNullaryLoosely || sym2.matchNullaryLoosely)
info1.overrides(info2, sym1.matchNullaryLoosely || sym2.matchNullaryLoosely, checkClassInfo = false)

def handleDoubleDef =
if (preferSym(sym1, sym2)) denot1
Expand Down Expand Up @@ -600,13 +603,13 @@ object Denotations {
case tp1: TypeBounds =>
tp2 match {
case tp2: TypeBounds => if (safeIntersection) tp1 safe_& tp2 else tp1 & tp2
case tp2: ClassInfo if tp1 contains tp2 => tp2
case tp2: ClassInfo => tp2
case _ => mergeConflict(sym1, sym2, tp1, tp2)
}
case tp1: ClassInfo =>
tp2 match {
case tp2: ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix & tp2.prefix)
case tp2: TypeBounds if tp2 contains tp1 => tp1
case tp2: TypeBounds => tp1
case _ => mergeConflict(sym1, sym2, tp1, tp2)
}

Expand Down Expand Up @@ -1132,6 +1135,7 @@ object Denotations {
if (denots.exists && denots.matches(this)) NoDenotation else this
def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): SingleDenotation =
if (required.isEmpty && excluded.isEmpty || compatibleWith(required, excluded)) this else NoDenotation
def aggregate[T](f: SingleDenotation => T, g: (T, T) => T): T = f(this)

type AsSeenFromResult = SingleDenotation
protected def computeAsSeenFrom(pre: Type)(implicit ctx: Context): SingleDenotation = {
Expand Down Expand Up @@ -1286,6 +1290,8 @@ object Denotations {
derivedUnion(denot1 filterDisjoint denot, denot2 filterDisjoint denot)
def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): PreDenotation =
derivedUnion(denot1.filterWithFlags(required, excluded), denot2.filterWithFlags(required, excluded))
def aggregate[T](f: SingleDenotation => T, g: (T, T) => T): T =
g(denot1.aggregate(f, g), denot2.aggregate(f, g))
protected def derivedUnion(denot1: PreDenotation, denot2: PreDenotation) =
if ((denot1 eq this.denot1) && (denot2 eq this.denot2)) this
else denot1 union denot2
Expand Down
Loading

0 comments on commit a8f3dc1

Please sign in to comment.