Skip to content

Commit a8f3dc1

Browse files
authored
Merge pull request #49 from noti0na1/dotty-explicit-nulls-notNull
Add predicate to check out of order for mutable variables
2 parents 3bb1b82 + d26b424 commit a8f3dc1

File tree

215 files changed

+1883
-725
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

215 files changed

+1883
-725
lines changed

.github/ISSUE_TEMPLATE/bug.md

-2
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,3 @@ println("hello, world")
1515

1616

1717
## expectation
18-
19-

.github/ISSUE_TEMPLATE/crash.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name: "\U0001F4A5 Crash report"
33
about: Report a Dotty Compiler compiler crash
44
title: ''
5-
labels: itype:bug
5+
labels: itype:bug, itype:crash
66
assignees: ''
77

88
---

.github/ISSUE_TEMPLATE/feature.md

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22
name: "\U0001F389 Suggest a feature"
33
about: Please create a feature request here https://github.com/lampepfl/dotty-feature-requests
44
title: ''
5-
labels:
5+
labels: ''
66
assignees: ''
77

88
---
99

1010
Please create a feature request here: [lampepfl/dotty-feature-requests](https://github.com/lampepfl/dotty-feature-requests).
11-
12-
13-
+2-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
---
2-
name: "Syntax highlighting"
2+
name: Syntax highlighting
33
about: Please create a syntax highlighting issue here https://github.com/scala/vscode-scala-syntax/issues
44
title: ''
5-
labels:
5+
labels: ''
66
assignees: ''
77

88
---
99

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

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

+11-15
Original file line numberDiff line numberDiff line change
@@ -1224,23 +1224,20 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
12241224
}
12251225

12261226
/* Emit code to compare the two top-most stack values using the 'op' operator. */
1227-
private def genCJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label): Unit = {
1228-
if (targetIfNoJump == success) genCJUMP(failure, success, op.negate(), tk, targetIfNoJump)
1227+
private def genCJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label, negated: Boolean = false): Unit = {
1228+
if (targetIfNoJump == success) genCJUMP(failure, success, op.negate(), tk, targetIfNoJump, negated = !negated)
12291229
else {
12301230
if (tk.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT
12311231
bc.emitIF_ICMP(op, success)
12321232
} else if (tk.isRef) { // REFERENCE(_) | ARRAY(_)
12331233
bc.emitIF_ACMP(op, success)
12341234
} else {
12351235
import Primitives._
1236+
def useCmpG = if (negated) op == GT || op == GE else op == LT || op == LE
12361237
(tk: @unchecked) match {
12371238
case LONG => emit(asm.Opcodes.LCMP)
1238-
case FLOAT =>
1239-
if (op == LT || op == LE) emit(asm.Opcodes.FCMPL)
1240-
else emit(asm.Opcodes.FCMPG)
1241-
case DOUBLE =>
1242-
if (op == LT || op == LE) emit(asm.Opcodes.DCMPL)
1243-
else emit(asm.Opcodes.DCMPG)
1239+
case FLOAT => emit(if (useCmpG) asm.Opcodes.FCMPG else asm.Opcodes.FCMPL)
1240+
case DOUBLE => emit(if (useCmpG) asm.Opcodes.DCMPG else asm.Opcodes.DCMPL)
12441241
}
12451242
bc.emitIF(op, success)
12461243
}
@@ -1249,9 +1246,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
12491246
}
12501247

12511248
/* Emits code to compare (and consume) stack-top and zero using the 'op' operator */
1252-
private def genCZJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label): Unit = {
1249+
private def genCZJUMP(success: asm.Label, failure: asm.Label, op: TestOp, tk: BType, targetIfNoJump: asm.Label, negated: Boolean = false): Unit = {
12531250
import Primitives._
1254-
if (targetIfNoJump == success) genCZJUMP(failure, success, op.negate(), tk, targetIfNoJump)
1251+
if (targetIfNoJump == success) genCZJUMP(failure, success, op.negate(), tk, targetIfNoJump, negated = !negated)
12551252
else {
12561253
if (tk.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT
12571254
bc.emitIF(op, success)
@@ -1261,18 +1258,17 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
12611258
case NE => bc emitIFNONNULL success
12621259
}
12631260
} else {
1261+
def useCmpG = if (negated) op == GT || op == GE else op == LT || op == LE
12641262
(tk: @unchecked) match {
12651263
case LONG =>
12661264
emit(asm.Opcodes.LCONST_0)
12671265
emit(asm.Opcodes.LCMP)
12681266
case FLOAT =>
12691267
emit(asm.Opcodes.FCONST_0)
1270-
if (op == LT || op == LE) emit(asm.Opcodes.FCMPL)
1271-
else emit(asm.Opcodes.FCMPG)
1268+
emit(if (useCmpG) asm.Opcodes.FCMPG else asm.Opcodes.FCMPL)
12721269
case DOUBLE =>
12731270
emit(asm.Opcodes.DCONST_0)
1274-
if (op == LT || op == LE) emit(asm.Opcodes.DCMPL)
1275-
else emit(asm.Opcodes.DCMPG)
1271+
emit(if (useCmpG) asm.Opcodes.DCMPG else asm.Opcodes.DCMPL)
12761272
}
12771273
bc.emitIF(op, success)
12781274
}
@@ -1287,8 +1283,8 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
12871283
case ScalaPrimitivesOps.NE => Primitives.NE
12881284
case ScalaPrimitivesOps.LT => Primitives.LT
12891285
case ScalaPrimitivesOps.LE => Primitives.LE
1290-
case ScalaPrimitivesOps.GE => Primitives.GE
12911286
case ScalaPrimitivesOps.GT => Primitives.GT
1287+
case ScalaPrimitivesOps.GE => Primitives.GE
12921288
}
12931289

12941290
/*

compiler/src/dotty/tools/backend/jvm/BCodeSkelBuilder.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ trait BCodeSkelBuilder extends BCodeHelpers {
7676

7777
override def getCurrentCUnit(): CompilationUnit = { cunit }
7878

79-
/* ---------------- helper utils for generating classes and fiels ---------------- */
79+
/* ---------------- helper utils for generating classes and fields ---------------- */
8080

8181
def genPlainClass(cd: ClassDef) = cd match {
8282
case ClassDef(_, _, _, impl) =>

compiler/src/dotty/tools/backend/jvm/BCodeSyncAndTry.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ trait BCodeSyncAndTry extends BCodeBodyBuilder {
310310
* ------
311311
*/
312312

313-
// a note on terminology: this is not "postHandlers", despite appearences.
313+
// a note on terminology: this is not "postHandlers", despite appearances.
314314
// "postHandlers" as in the source-code view. And from that perspective, both (3.A) and (3.B) are invisible implementation artifacts.
315315
if (hasFinally) withFreshCleanupScope {
316316
nopIfNeeded(startTryBody)

compiler/src/dotty/tools/backend/jvm/BTypes.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ abstract class BTypes {
362362
*
363363
* - Initializer block (JLS 8.6 / 8.7): block of statements in a java class
364364
* - static initializer: executed before constructor body
365-
* - instance initializer: exectued when class is initialized (instance creation, static
365+
* - instance initializer: executed when class is initialized (instance creation, static
366366
* field access, ...)
367367
*
368368
* - A static nested class can be defined as

compiler/src/dotty/tools/dotc/CompilationUnit.scala

+7-2
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,14 @@ object CompilationUnit {
8383
unit1
8484
}
8585

86-
def apply(source: SourceFile)(implicit ctx: Context): CompilationUnit = {
86+
/** Create a compilation unit corresponding to `source`.
87+
* If `mustExist` is true, this will fail if `source` does not exist.
88+
*/
89+
def apply(source: SourceFile, mustExist: Boolean = true)(implicit ctx: Context): CompilationUnit = {
8790
val src =
88-
if (source.file.isDirectory) {
91+
if (!mustExist)
92+
source
93+
else if (source.file.isDirectory) {
8994
ctx.error(s"expected file, received directory '${source.file.path}'")
9095
NoSource
9196
}

compiler/src/dotty/tools/dotc/ast/Desugar.scala

+22-8
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,26 @@ object desugar {
804804
flatTree(cdef1 :: companions ::: implicitWrappers)
805805
}.reporting(i"desugared: $result", Printers.desugar)
806806

807+
/** Expand
808+
*
809+
* package object name { body }
810+
*
811+
* to:
812+
*
813+
* package name {
814+
* object `package` { body }
815+
* }
816+
*/
817+
def packageModuleDef(mdef: ModuleDef)(implicit ctx: Context): Tree =
818+
val impl = mdef.impl
819+
val mods = mdef.mods
820+
val moduleName = normalizeName(mdef, impl).asTermName
821+
if (mods.is(Package))
822+
PackageDef(Ident(moduleName),
823+
cpy.ModuleDef(mdef)(nme.PACKAGE, impl).withMods(mods &~ Package) :: Nil)
824+
else
825+
mdef
826+
807827
/** Expand
808828
*
809829
* object name extends parents { self => body }
@@ -854,7 +874,7 @@ object desugar {
854874
ctx.warning(em"${hl("final")} modifier is redundant for objects", flagSourcePos(Final))
855875

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

1232-
/** Does this package contains at least one top-level definition
1233-
* that will require a wrapping object ?
1234-
*/
1235-
def hasTopLevelDef(pdef: PackageDef)(given Context): Boolean =
1236-
pdef.stats.exists(isTopLevelDef)
1237-
12381252
/** Assuming `src` contains top-level definition, returns the name that should
12391253
* be using for the package object that will wrap them.
12401254
*/
@@ -1758,7 +1772,7 @@ object desugar {
17581772
case Block(Nil, expr) =>
17591773
collect(expr)
17601774
case Quote(expr) =>
1761-
new TreeTraverser {
1775+
new UntypedTreeTraverser {
17621776
def traverse(tree: untpd.Tree)(implicit ctx: Context): Unit = tree match {
17631777
case Splice(expr) => collect(expr)
17641778
case TypSplice(expr) =>

compiler/src/dotty/tools/dotc/ast/tpd.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
509509
Thicket(valdef, clsdef)
510510
}
511511

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

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

962-
/** If inititializer tree is `_', the default value of its type,
962+
/** If inititializer tree is `_`, the default value of its type,
963963
* otherwise the tree itself.
964964
*/
965965
def wildcardToDefault(implicit ctx: Context): Tree =

compiler/src/dotty/tools/dotc/config/ScalaSettings.scala

+1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ class ScalaSettings extends Settings.SettingGroup {
8181
val XshowPhases: Setting[Boolean] = BooleanSetting("-Xshow-phases", "Print all compiler phases")
8282
val XnoValueClasses: Setting[Boolean] = BooleanSetting("-Xno-value-classes", "Do not use value classes. Helps debugging.")
8383
val XreplLineWidth: Setting[Int] = IntSetting("-Xrepl-line-width", "Maximal number of columns per line for REPL output", 390)
84+
val XreplDisableDisplay: Setting[Boolean] = BooleanSetting("-Xrepl-disable-display", "Do not display definitions in REPL.")
8485
val XfatalWarnings: Setting[Boolean] = BooleanSetting("-Xfatal-warnings", "Fail the compilation if there are any warnings.")
8586
val XverifySignatures: Setting[Boolean] = BooleanSetting("-Xverify-signatures", "Verify generic signatures in generated bytecode.")
8687
val XignoreScala2Macros: Setting[Boolean] = BooleanSetting("-Xignore-scala2-macros", "Ignore errors when compiling code that calls Scala2 macros, these will fail at runtime.")

compiler/src/dotty/tools/dotc/core/Contexts.scala

+4-1
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,10 @@ object Contexts {
471471
else {
472472
val newCtx = fresh.setSource(source)
473473
if (newCtx.compilationUnit == null)
474-
newCtx.setCompilationUnit(CompilationUnit(source))
474+
// `source` might correspond to a file not necessarily
475+
// in the current project (e.g. when inlining library code),
476+
// so set `mustExist` to false.
477+
newCtx.setCompilationUnit(CompilationUnit(source, mustExist = false))
475478
sourceCtx = sourceCtx.updated(source, newCtx)
476479
newCtx
477480
}

compiler/src/dotty/tools/dotc/core/Definitions.scala

+15-9
Original file line numberDiff line numberDiff line change
@@ -459,12 +459,12 @@ class Definitions {
459459
@tu lazy val Boolean_|| : Symbol = BooleanClass.requiredMethod(nme.ZOR)
460460
@tu lazy val Boolean_== : Symbol =
461461
BooleanClass.info.member(nme.EQ).suchThat(_.info.firstParamTypes match {
462-
case List(pt) => (pt isRef BooleanClass)
462+
case List(pt) => pt.isRef(BooleanClass)
463463
case _ => false
464464
}).symbol
465465
@tu lazy val Boolean_!= : Symbol =
466466
BooleanClass.info.member(nme.NE).suchThat(_.info.firstParamTypes match {
467-
case List(pt) => (pt isRef BooleanClass)
467+
case List(pt) => pt.isRef(BooleanClass)
468468
case _ => false
469469
}).symbol
470470

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

@@ -539,15 +539,15 @@ class Definitions {
539539
@tu lazy val ClassCastExceptionClass: ClassSymbol = ctx.requiredClass("java.lang.ClassCastException")
540540
@tu lazy val ClassCastExceptionClass_stringConstructor: TermSymbol = ClassCastExceptionClass.info.member(nme.CONSTRUCTOR).suchThat(_.info.firstParamTypes match {
541541
case List(pt) =>
542-
val pt1 = if (ctx.explicitNulls) pt.stripNull else pt
543-
pt1 isRef StringClass
542+
val pt1 = if (ctx.explicitNulls) pt.stripNull() else pt
543+
pt1.isRef(StringClass)
544544
case _ => false
545545
}).symbol.asTerm
546546
@tu lazy val ArithmeticExceptionClass: ClassSymbol = ctx.requiredClass("java.lang.ArithmeticException")
547547
@tu lazy val ArithmeticExceptionClass_stringConstructor: TermSymbol = ArithmeticExceptionClass.info.member(nme.CONSTRUCTOR).suchThat(_.info.firstParamTypes match {
548548
case List(pt) =>
549-
val pt1 = if (ctx.explicitNulls) pt.stripNull else pt
550-
pt1 isRef StringClass
549+
val pt1 = if (ctx.explicitNulls) pt.stripNull() else pt
550+
pt1.isRef(StringClass)
551551
case _ => false
552552
}).symbol.asTerm
553553

@@ -822,16 +822,22 @@ class Definitions {
822822
// create Symbols for the ones that are present, so they can be checked during nullification.
823823
@tu lazy val NotNullAnnots: List[ClassSymbol] = ctx.getClassesIfDefined(
824824
"javax.annotation.Nonnull" ::
825-
"edu.umd.cs.findbugs.annotations.NonNull" ::
825+
"javax.validation.constraints.NotNull" ::
826826
"androidx.annotation.NonNull" ::
827827
"android.support.annotation.NonNull" ::
828828
"android.annotation.NonNull" ::
829829
"com.android.annotations.NonNull" ::
830830
"org.eclipse.jdt.annotation.NonNull" ::
831+
"edu.umd.cs.findbugs.annotations.NonNull" ::
831832
"org.checkerframework.checker.nullness.qual.NonNull" ::
832833
"org.checkerframework.checker.nullness.compatqual.NonNullDecl" ::
833834
"org.jetbrains.annotations.NotNull" ::
835+
"org.springframework.lang.NonNull" ::
836+
"org.springframework.lang.NonNullApi" ::
837+
"org.springframework.lang.NonNullFields" ::
834838
"lombok.NonNull" ::
839+
"reactor.util.annotation.NonNull" ::
840+
"reactor.util.annotation.NonNullApi" ::
835841
"io.reactivex.annotations.NonNull" :: Nil map PreNamedString)
836842

837843
// convenient one-parameter method types
@@ -886,7 +892,7 @@ class Definitions {
886892
if (ctx.erasedTypes) JavaArrayType(elem)
887893
else ArrayType.appliedTo(elem :: Nil)
888894
def unapply(tp: Type)(implicit ctx: Context): Option[Type] = tp.dealias match {
889-
case AppliedType(at, arg :: Nil) if at isRef ArrayType.symbol => Some(arg)
895+
case AppliedType(at, arg :: Nil) if at.isRef(ArrayType.symbol) => Some(arg)
890896
case _ => None
891897
}
892898
}

compiler/src/dotty/tools/dotc/core/Denotations.scala

+9-3
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ object Denotations {
116116
*/
117117
def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): PreDenotation
118118

119+
/** Map `f` over all single denotations and aggregate the results with `g`. */
120+
def aggregate[T](f: SingleDenotation => T, g: (T, T) => T): T
121+
119122
private var cachedPrefix: Type = _
120123
private var cachedAsSeenFrom: AsSeenFromResult = _
121124
private var validAsSeenFrom: Period = Nowhere
@@ -459,7 +462,7 @@ object Denotations {
459462
/** Sym preference provided types also override */
460463
def prefer(sym1: Symbol, sym2: Symbol, info1: Type, info2: Type) =
461464
preferSym(sym1, sym2) &&
462-
info1.overrides(info2, sym1.matchNullaryLoosely || sym2.matchNullaryLoosely)
465+
info1.overrides(info2, sym1.matchNullaryLoosely || sym2.matchNullaryLoosely, checkClassInfo = false)
463466

464467
def handleDoubleDef =
465468
if (preferSym(sym1, sym2)) denot1
@@ -600,13 +603,13 @@ object Denotations {
600603
case tp1: TypeBounds =>
601604
tp2 match {
602605
case tp2: TypeBounds => if (safeIntersection) tp1 safe_& tp2 else tp1 & tp2
603-
case tp2: ClassInfo if tp1 contains tp2 => tp2
606+
case tp2: ClassInfo => tp2
604607
case _ => mergeConflict(sym1, sym2, tp1, tp2)
605608
}
606609
case tp1: ClassInfo =>
607610
tp2 match {
608611
case tp2: ClassInfo if tp1.cls eq tp2.cls => tp1.derivedClassInfo(tp1.prefix & tp2.prefix)
609-
case tp2: TypeBounds if tp2 contains tp1 => tp1
612+
case tp2: TypeBounds => tp1
610613
case _ => mergeConflict(sym1, sym2, tp1, tp2)
611614
}
612615

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

11361140
type AsSeenFromResult = SingleDenotation
11371141
protected def computeAsSeenFrom(pre: Type)(implicit ctx: Context): SingleDenotation = {
@@ -1286,6 +1290,8 @@ object Denotations {
12861290
derivedUnion(denot1 filterDisjoint denot, denot2 filterDisjoint denot)
12871291
def filterWithFlags(required: FlagSet, excluded: FlagSet)(implicit ctx: Context): PreDenotation =
12881292
derivedUnion(denot1.filterWithFlags(required, excluded), denot2.filterWithFlags(required, excluded))
1293+
def aggregate[T](f: SingleDenotation => T, g: (T, T) => T): T =
1294+
g(denot1.aggregate(f, g), denot2.aggregate(f, g))
12891295
protected def derivedUnion(denot1: PreDenotation, denot2: PreDenotation) =
12901296
if ((denot1 eq this.denot1) && (denot2 eq this.denot2)) this
12911297
else denot1 union denot2

0 commit comments

Comments
 (0)