Skip to content

Commit 053d509

Browse files
Merge branch 'master' into ws-optimize-string-interpolation
2 parents 2da90a0 + 08f4679 commit 053d509

File tree

242 files changed

+3711
-855
lines changed

Some content is hidden

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

242 files changed

+3711
-855
lines changed

AUTHORS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,7 @@ The majority of the dotty codebase is new code, with the exception of the compon
7171
> the [compiler bridge in sbt 0.13](https://github.com/sbt/sbt/tree/0.13/compile/interface/src/main/scala/xsbt),
7272
> but has been heavily adapted and refactored.
7373
> Original authors were Mark Harrah, Grzegorz Kossakowski, Martin Duhemm, Adriaan Moors and others.
74+
75+
`dotty.tools.dotc.plugins`
76+
77+
> Adapted from [scala/scala](https://github.com/scala/scala) with some modifications. They were originally authored by Lex Spoon, Som Snytt, Adriaan Moors, Paul Phillips and others.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
972972
case tp =>
973973
ctx.warning(
974974
s"an unexpected type representation reached the compiler backend while compiling $currentUnit: $tp. " +
975-
"If possible, please file a bug on issues.scala-lang.org.")
975+
"If possible, please file a bug on https://github.com/lampepfl/dotty/issues")
976976

977977
tp match {
978978
case tp: ThisType if tp.cls == ArrayClass => ObjectReference.asInstanceOf[ct.bTypes.ClassBType] // was introduced in 9b17332f11 to fix SI-999, but this code is not reached in its test, or any other test

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

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
159159
*/
160160
class Worker1(needsOutFolder: Boolean) {
161161

162-
val caseInsensitively = scala.collection.mutable.Map.empty[String, Symbol]
162+
val caseInsensitively = scala.collection.mutable.HashMap.empty[String, Symbol]
163163

164164
def run(): Unit = {
165165
while (true) {
@@ -190,18 +190,27 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter
190190
val claszSymbol = cd.symbol
191191

192192
// GenASM checks this before classfiles are emitted, https://github.com/scala/scala/commit/e4d1d930693ac75d8eb64c2c3c69f2fc22bec739
193-
val lowercaseJavaClassName = claszSymbol.name.toString.toLowerCase
194-
caseInsensitively.get(lowercaseJavaClassName) match {
195-
case None =>
196-
caseInsensitively.put(lowercaseJavaClassName, claszSymbol)
197-
case Some(dupClassSym) =>
198-
// Order is not deterministic so we enforce lexicographic order between the duplicates for error-reporting
199-
if (claszSymbol.name.toString < dupClassSym.name.toString)
200-
ctx.warning(s"Class ${claszSymbol.name} differs only in case from ${dupClassSym.name}. " +
201-
"Such classes will overwrite one another on case-insensitive filesystems.", claszSymbol.pos)
202-
else
203-
ctx.warning(s"Class ${dupClassSym.name} differs only in case from ${claszSymbol.name}. " +
204-
"Such classes will overwrite one another on case-insensitive filesystems.", dupClassSym.pos)
193+
def checkName(claszSymbol: Symbol): Unit = {
194+
val lowercaseJavaClassName = claszSymbol.effectiveName.toString.toLowerCase
195+
caseInsensitively.get(lowercaseJavaClassName) match {
196+
case None =>
197+
caseInsensitively.put(lowercaseJavaClassName, claszSymbol)
198+
case Some(dupClassSym) =>
199+
if (claszSymbol.effectiveName.toString != dupClassSym.effectiveName.toString) {
200+
// Order is not deterministic so we enforce lexicographic order between the duplicates for error-reporting
201+
val (cl1, cl2) =
202+
if (claszSymbol.effectiveName.toString < dupClassSym.effectiveName.toString) (claszSymbol, dupClassSym)
203+
else (dupClassSym, claszSymbol)
204+
ctx.warning(s"Class ${cl1.effectiveName} differs only in case from ${cl2.effectiveName}. " +
205+
"Such classes will overwrite one another on case-insensitive filesystems.", cl1.pos)
206+
}
207+
}
208+
}
209+
checkName(claszSymbol)
210+
if (int.symHelper(claszSymbol).isModuleClass) {
211+
val companionModule = claszSymbol.companionModule
212+
if (int.symHelper(companionModule.owner).isPackageClass)
213+
checkName(companionModule)
205214
}
206215

207216
// -------------- mirror class, if needed --------------

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class Compiler {
6666
new NormalizeFlags, // Rewrite some definition flags
6767
new ExtensionMethods, // Expand methods of value classes with extension methods
6868
new ExpandSAMs, // Expand single abstract method closures to anonymous classes
69+
new ShortcutImplicits, // Allow implicit functions without creating closures
6970
new TailRec, // Rewrite tail recursion to loops
7071
new ByNameClosures, // Expand arguments to by-name parameters to closures
7172
new LiftTry, // Put try expressions that might execute on non-empty stacks into their own methods
@@ -76,11 +77,11 @@ class Compiler {
7677
new PatternMatcher, // Compile pattern matches
7778
new ExplicitOuter, // Add accessors to outer classes from nested ones.
7879
new ExplicitSelf, // Make references to non-trivial self types explicit as casts
79-
new ShortcutImplicits, // Allow implicit functions without creating closures
8080
new StringInterpolatorOpt, // Optimizes raw and s string interpolators by rewriting them to string concatentations
8181
new CrossCastAnd, // Normalize selections involving intersection types.
8282
new Splitter) :: // Expand selections involving union types into conditionals
8383
List(new ErasedDecls, // Removes all erased defs and vals decls (except for parameters)
84+
new IsInstanceOfChecker, // check runtime realisability for `isInstanceOf`
8485
new VCInlineMethods, // Inlines calls to value class methods
8586
new SeqLiterals, // Express vararg arguments as arrays
8687
new InterceptedMethods, // Special handling of `==`, `|=`, `getClass` methods

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
157157
if (ctx.settings.YtestPickler.value) List("pickler")
158158
else ctx.settings.YstopAfter.value
159159

160-
val phases = ctx.squashPhases(ctx.phasePlan,
160+
val pluginPlan = ctx.addPluginPhases(ctx.phasePlan)
161+
val phases = ctx.squashPhases(pluginPlan,
161162
ctx.settings.Yskip.value, ctx.settings.YstopBefore.value, stopAfter, ctx.settings.Ycheck.value)
162163
ctx.usePhases(phases)
163164

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ object desugar {
5050
*/
5151
class DerivedFromParamTree(suffix: String) extends DerivedTypeTree {
5252

53-
/** Make sure that for all enclosing module classes their companion lasses
53+
/** Make sure that for all enclosing module classes their companion classes
5454
* are completed. Reason: We need the constructor of such companion classes to
5555
* be completed so that OriginalSymbol attachments are pushed to DerivedTypeTrees
5656
* in apply/unapply methods.
@@ -429,7 +429,6 @@ object desugar {
429429
}
430430
val hasRepeatedParam = constrVparamss.exists(_.exists {
431431
case ValDef(_, tpt, _) => isRepeated(tpt)
432-
case _ => false
433432
})
434433
if (mods.is(Abstract) || hasRepeatedParam) Nil // cannot have default arguments for repeated parameters, hence copy method is not issued
435434
else {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ object Trees {
771771
def flatten[T >: Untyped](trees: List[Tree[T]]): List[Tree[T]] = {
772772
var buf: ListBuffer[Tree[T]] = null
773773
var xs = trees
774-
while (xs.nonEmpty) {
774+
while (!xs.isEmpty) {
775775
xs.head match {
776776
case Thicket(elems) =>
777777
if (buf == null) {
@@ -805,7 +805,7 @@ object Trees {
805805
def unforced: AnyRef
806806
protected def force(x: AnyRef): Unit
807807
def forceIfLazy(implicit ctx: Context): T = unforced match {
808-
case lzy: Lazy[T] =>
808+
case lzy: Lazy[T @unchecked] =>
809809
val x = lzy.complete
810810
force(x)
811811
x

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
6060
class NonEmptyFunction(args: List[Tree], body: Tree, val mods: Modifiers) extends Function(args, body)
6161

6262
/** A function created from a wildcard expression
63-
* @param placeHolderParams a list of definitions of synthetic parameters
63+
* @param placeholderParams a list of definitions of synthetic parameters.
6464
* @param body the function body where wildcards are replaced by
6565
* references to synthetic parameters.
6666
*/

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,15 @@ object CompilerCommand extends DotClass {
114114

115115
def shouldStopWithInfo = {
116116
import settings._
117-
Set(help, Xhelp, Yhelp) exists (_.value)
117+
Set(help, Xhelp, Yhelp, showPlugins) exists (_.value)
118118
}
119119

120120
def infoMessage: String = {
121121
import settings._
122122
if (help.value) usageMessage
123123
else if (Xhelp.value) xusageMessage
124124
else if (Yhelp.value) yusageMessage
125+
else if (showPlugins.value) ctx.pluginDescriptions
125126
else ""
126127
}
127128

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ object Printers {
2828
val overload: Printer = noPrinter
2929
val patmatch: Printer = noPrinter
3030
val pickling: Printer = noPrinter
31+
val plugins: Printer = noPrinter
3132
val simplify: Printer = noPrinter
3233
val subtyping: Printer = noPrinter
3334
val transforms: Printer = noPrinter

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ trait PropertiesTrait {
5656
def scalaPropOrElse(name: String, alt: String): String = scalaProps.getProperty(name, alt)
5757
def scalaPropOrEmpty(name: String): String = scalaPropOrElse(name, "")
5858
def scalaPropOrNone(name: String): Option[String] = Option(scalaProps.getProperty(name))
59-
59+
6060
/** Either the development or release version if known, otherwise
6161
* the empty string.
6262
*/
@@ -73,7 +73,15 @@ trait PropertiesTrait {
7373
} else ""
7474
}
7575
}
76-
76+
77+
/** Whether the current version of compiler is experimental
78+
*
79+
* 1. Snapshot and nightly releases are experimental.
80+
* 2. Features supported by experimental versions of the compiler:
81+
* - research plugins
82+
*/
83+
val experimental = versionString.contains("SNAPSHOT") || versionString.contains("NIGHTLY")
84+
7785
val copyrightString = scalaPropOrElse("copyright.string", "(c) 2002-2017 LAMP/EPFL")
7886

7987
/** This is the encoding to use reading in source files, overridden with -encoding

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ class ScalaSettings extends Settings.SettingGroup {
5050
val printTasty = BooleanSetting("-print-tasty", "Prints the raw tasty when decompiling.")
5151
val printLines = BooleanSetting("-print-lines", "Show source code line numbers.")
5252

53+
/** Plugin-related setting */
54+
val plugin = MultiStringSetting ("-Xplugin", "paths", "Load a plugin from each classpath.")
55+
val disable = MultiStringSetting ("-Xplugin-disable", "plugin", "Disable plugins by name.")
56+
val require = MultiStringSetting ("-Xplugin-require", "plugin", "Abort if a named plugin is not loaded.")
57+
val showPlugins = BooleanSetting ("-Xplugin-list", "Print a synopsis of loaded plugins.")
58+
val pluginsDir = StringSetting ("-Xpluginsdir", "path", "Path to search for plugin archives.", Defaults.scalaPluginPath)
59+
val pluginOptions = MultiStringSetting ("-P", "plugin:opt", "Pass an option to a plugin, e.g. -P:<plugin>:<opt>")
60+
5361
/** -X "Advanced" settings
5462
*/
5563
val Xhelp = BooleanSetting("-X", "Print a synopsis of advanced options.")

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

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ object CheckRealizable {
3030
class NotFinal(sym: Symbol)(implicit ctx: Context)
3131
extends Realizability(i" refers to nonfinal $sym")
3232

33-
class HasProblemBounds(typ: SingleDenotation)(implicit ctx: Context)
34-
extends Realizability(i" has a member $typ with possibly conflicting bounds ${typ.info.bounds.lo} <: ... <: ${typ.info.bounds.hi}")
33+
class HasProblemBounds(name: Name, info: Type)(implicit ctx: Context)
34+
extends Realizability(i" has a member $name with possibly conflicting bounds ${info.bounds.lo} <: ... <: ${info.bounds.hi}")
3535

3636
class HasProblemBaseArg(typ: Type, argBounds: TypeBounds)(implicit ctx: Context)
3737
extends Realizability(i" has a base type $typ with possibly conflicting parameter bounds ${argBounds.lo} <: ... <: ${argBounds.hi}")
@@ -96,6 +96,14 @@ class CheckRealizable(implicit ctx: Context) {
9696
else boundsRealizability(tp).andAlso(memberRealizability(tp))
9797
}
9898

99+
private def refinedNames(tp: Type): Set[Name] = tp.dealias match {
100+
case tp: RefinedType => refinedNames(tp.parent) + tp.refinedName
101+
case tp: AndType => refinedNames(tp.tp1) ++ refinedNames(tp.tp2)
102+
case tp: OrType => refinedNames(tp.tp1) ++ refinedNames(tp.tp2)
103+
case tp: TypeProxy => refinedNames(tp.underlying)
104+
case _ => Set.empty
105+
}
106+
99107
/** `Realizable` if `tp` has good bounds, a `HasProblem...` instance
100108
* pointing to a bad bounds member otherwise. "Has good bounds" means:
101109
*
@@ -107,12 +115,22 @@ class CheckRealizable(implicit ctx: Context) {
107115
* also lead to base types with bad bounds).
108116
*/
109117
private def boundsRealizability(tp: Type) = {
110-
val mbrProblems =
118+
119+
val memberProblems =
111120
for {
112121
mbr <- tp.nonClassTypeMembers
113122
if !(mbr.info.loBound <:< mbr.info.hiBound)
114123
}
115-
yield new HasProblemBounds(mbr)
124+
yield new HasProblemBounds(mbr.name, mbr.info)
125+
126+
val refinementProblems =
127+
for {
128+
name <- refinedNames(tp)
129+
if (name.isTypeName)
130+
mbr <- tp.member(name).alternatives
131+
if !(mbr.info.loBound <:< mbr.info.hiBound)
132+
}
133+
yield new HasProblemBounds(name, mbr.info)
116134

117135
def baseTypeProblems(base: Type) = base match {
118136
case AndType(base1, base2) =>
@@ -126,12 +144,13 @@ class CheckRealizable(implicit ctx: Context) {
126144
val baseProblems =
127145
tp.baseClasses.map(_.baseTypeOf(tp)).flatMap(baseTypeProblems)
128146

129-
(((Realizable: Realizability)
130-
/: mbrProblems)(_ andAlso _)
147+
((((Realizable: Realizability)
148+
/: memberProblems)(_ andAlso _)
149+
/: refinementProblems)(_ andAlso _)
131150
/: baseProblems)(_ andAlso _)
132151
}
133152

134-
/** `Realizable` if all of `tp`'s non-struct fields have realizable types,
153+
/** `Realizable` if all of `tp`'s non-strict fields have realizable types,
135154
* a `HasProblemField` instance pointing to a bad field otherwise.
136155
*/
137156
private def memberRealizability(tp: Type) = {

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import dotty.tools.dotc.profile.Profiler
3535
import util.Property.Key
3636
import util.Store
3737
import xsbti.AnalysisCallback
38+
import plugins._
3839

3940
object Contexts {
4041

@@ -76,6 +77,7 @@ object Contexts {
7677
with SymDenotations
7778
with Reporting
7879
with NamerContextOps
80+
with Plugins
7981
with Cloneable { thiscontext =>
8082
implicit def ctx: Context = this
8183

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,12 +1020,6 @@ object Denotations {
10201020
interval
10211021
}
10221022

1023-
/** For ClassDenotations only:
1024-
* If caches influenced by parent classes are still valid, the denotation
1025-
* itself, otherwise a freshly initialized copy.
1026-
*/
1027-
def syncWithParents(implicit ctx: Context): SingleDenotation = this
1028-
10291023
/** Show declaration string; useful for showing declarations
10301024
* as seen from subclasses.
10311025
*/

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ trait Hashable {
6464
var h = seed
6565
var xs = tps
6666
var len = arity
67-
while (xs.nonEmpty) {
67+
while (!xs.isEmpty) {
6868
val elemHash = typeHash(bs, xs.head)
6969
if (elemHash == NotCached) return NotCached
7070
h = hashing.mix(h, elemHash)

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

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ object Phases {
8282
final def squashPhases(phasess: List[List[Phase]],
8383
phasesToSkip: List[String], stopBeforePhases: List[String], stopAfterPhases: List[String], YCheckAfter: List[String]): List[Phase] = {
8484
val squashedPhases = ListBuffer[Phase]()
85-
var prevPhases: Set[Class[_ <: Phase]] = Set.empty
85+
var prevPhases: Set[String] = Set.empty
8686
val YCheckAll = YCheckAfter.contains("all")
8787

8888
var stop = false
@@ -99,7 +99,6 @@ object Phases {
9999
val filteredPhaseBlock = filteredPhases(i)
100100
val phaseToAdd =
101101
if (filteredPhaseBlock.length > 1) {
102-
val phasesInBlock: Set[String] = filteredPhaseBlock.map(_.phaseName).toSet
103102
for (phase <- filteredPhaseBlock) {
104103
phase match {
105104
case p: MiniPhase =>
@@ -112,11 +111,11 @@ object Phases {
112111
}
113112
}
114113
val superPhase = new MegaPhase(filteredPhaseBlock.asInstanceOf[List[MiniPhase]].toArray)
115-
prevPhases ++= filteredPhaseBlock.map(_.getClazz)
114+
prevPhases ++= filteredPhaseBlock.map(_.phaseName)
116115
superPhase
117116
} else { // block of a single phase, no squashing
118117
val phase = filteredPhaseBlock.head
119-
prevPhases += phase.getClazz
118+
prevPhases += phase.phaseName
120119
phase
121120
}
122121
squashedPhases += phaseToAdd
@@ -147,7 +146,7 @@ object Phases {
147146

148147
phases = (NoPhase :: flatPhases.toList ::: new TerminalPhase :: Nil).toArray
149148
setSpecificPhases()
150-
var phasesAfter:Set[Class[_ <: Phase]] = Set.empty
149+
var phasesAfter: Set[String] = Set.empty
151150
nextDenotTransformerId = new Array[Int](phases.length)
152151
denotTransformers = new Array[DenotTransformer](phases.length)
153152

@@ -161,7 +160,7 @@ object Phases {
161160
val unmetPrecedeRequirements = p.runsAfter -- phasesAfter
162161
assert(unmetPrecedeRequirements.isEmpty,
163162
s"phase ${p} has unmet requirement: ${unmetPrecedeRequirements.mkString(", ")} should precede this phase")
164-
phasesAfter += p.getClazz
163+
phasesAfter += p.phaseName
165164

166165
}
167166
var i = 0
@@ -281,7 +280,7 @@ object Phases {
281280
def allowsImplicitSearch: Boolean = false
282281

283282
/** List of names of phases that should precede this phase */
284-
def runsAfter: Set[Class[_ <: Phase]] = Set.empty
283+
def runsAfter: Set[String] = Set.empty
285284

286285
/** @pre `isRunnable` returns true */
287286
def run(implicit ctx: Context): Unit
@@ -383,22 +382,10 @@ object Phases {
383382
override def toString = phaseName
384383
}
385384

386-
trait NeedsCompanions {
387-
def isCompanionNeeded(cls: ClassSymbol)(implicit ctx: Context): Boolean
388-
}
389-
390385
/** Replace all instances of `oldPhaseClass` in `current` phases
391386
* by the result of `newPhases` applied to the old phase.
392387
*/
393388
def replace(oldPhaseClass: Class[_ <: Phase], newPhases: Phase => List[Phase], current: List[List[Phase]]): List[List[Phase]] =
394389
current.map(_.flatMap(phase =>
395390
if (oldPhaseClass.isInstance(phase)) newPhases(phase) else phase :: Nil))
396-
397-
/** Dotty deviation: getClass yields Class[_], instead of [Class <: <type of receiver>].
398-
* We can get back the old behavior using this decorator. We should also use the same
399-
* trick for standard getClass.
400-
*/
401-
private implicit class getClassDeco[T](val x: T) extends AnyVal {
402-
def getClazz: Class[_ <: T] = x.getClass.asInstanceOf[Class[_ <: T]]
403-
}
404391
}

0 commit comments

Comments
 (0)