Skip to content

Commit ef3dacb

Browse files
Merge branch 'master' into 0.25.x
2 parents c89cf41 + cc4eeb5 commit ef3dacb

File tree

75 files changed

+2916
-152
lines changed

Some content is hidden

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

75 files changed

+2916
-152
lines changed

README.md

+1-12
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
Dotty
22
=====
3-
[![Build Status](http://dotty-ci.epfl.ch/api/badges/lampepfl/dotty/status.svg)](http://dotty-ci.epfl.ch/lampepfl/dotty)
43
[![Dotty CI](https://github.com/lampepfl/dotty/workflows/Dotty%20CI/badge.svg?branch=master)](https://github.com/lampepfl/dotty/actions?query=branch%3Amaster)
54
[![Join the chat at https://gitter.im/lampepfl/dotty](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/lampepfl/dotty?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6-
[![Log Knowledge](https://img.shields.io/badge/log-knowledge-blueviolet.svg)](https://github.com/lampepfl/dotty-knowledge/issues/new/choose)
7-
85

96
* [Homepage](http://dotty.epfl.ch)
10-
* [Documentation](https://dotty.epfl.ch/docs) [![Deadlink Status](https://travis-ci.org/nicolasstucki/dotty-website-linkcheck.svg?branch=master)](https://travis-ci.org/nicolasstucki/dotty-website-linkcheck)
7+
* [Documentation](https://dotty.epfl.ch/docs)
118

129
Try it out
1310
==========
@@ -24,14 +21,6 @@ How to Contribute
2421
* [Getting Started as Contributor](https://dotty.epfl.ch/docs/contributing/getting-started.html)
2522
* [Issues](https://github.com/lampepfl/dotty/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)
2623

27-
## Contribute Internals-related Knowledge
28-
If you know anything useful at all about Dotty, feel free to log this knowledge:
29-
30-
- [📜Log the Knowledge](https://github.com/lampepfl/dotty-knowledge/issues/new/choose)
31-
- [🎓More about Logging the Knowledge](https://github.com/lampepfl/dotty-knowledge/blob/master/README.md)
32-
33-
In short, no need to make it pretty, particularly human-readable or give it a particular structure. Just dump the knowledge you have, and we'll take it from there.
34-
3524
License
3625
=======
3726
Dotty is licensed under the [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -1531,9 +1531,9 @@ class JSCodeGen()(implicit ctx: Context) {
15311531
case jstpe.LongType =>
15321532
js.BinaryOp(js.BinaryOp.Long_-, js.LongLiteral(0), genArg)
15331533
case jstpe.FloatType =>
1534-
js.BinaryOp(js.BinaryOp.Float_-, js.FloatLiteral(0.0f), genArg)
1534+
js.BinaryOp(js.BinaryOp.Float_*, js.FloatLiteral(-1.0f), genArg)
15351535
case jstpe.DoubleType =>
1536-
js.BinaryOp(js.BinaryOp.Double_-, js.DoubleLiteral(0), genArg)
1536+
js.BinaryOp(js.BinaryOp.Double_*, js.DoubleLiteral(-1.0), genArg)
15371537
}
15381538

15391539
case NOT =>

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

+14
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,20 @@ import scala.util.control.NonFatal
3131
/** A compiler run. Exports various methods to compile source files */
3232
class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with ConstraintRunInfo {
3333

34+
/** Default timeout to stop looking for further implicit suggestions, in ms.
35+
* This is usually for the first import suggestion; subsequent suggestions
36+
* may get smaller timeouts. @see ImportSuggestions.reduceTimeBudget
37+
*/
38+
private var myImportSuggestionBudget: Int =
39+
Int.MinValue // sentinel value; means whatever is set in command line option
40+
41+
def importSuggestionBudget =
42+
if myImportSuggestionBudget == Int.MinValue then ictx.settings.XimportSuggestionTimeout.value
43+
else myImportSuggestionBudget
44+
45+
def importSuggestionBudget_=(x: Int) =
46+
myImportSuggestionBudget = x
47+
3448
/** If this variable is set to `true`, some core typer operations will
3549
* return immediately. Currently these early abort operations are
3650
* `Typer.typed` and `Implicits.typedImplicit`.

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,7 @@ object desugar {
11281128
case TypeDef(_, rhs) =>
11291129
def rhsOK(tree: Tree): Boolean = tree match {
11301130
case bounds: TypeBoundsTree => !bounds.alias.isEmpty
1131-
case _: Template => false
1131+
case _: Template | _: MatchTypeTree => false
11321132
case LambdaTypeTree(_, body) => rhsOK(body)
11331133
case _ => true
11341134
}

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

+19-2
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
421421
t
422422
}
423423

424-
def singleton(tp: Type)(implicit ctx: Context): Tree = tp match {
424+
def singleton(tp: Type)(implicit ctx: Context): Tree = tp.dealias match {
425425
case tp: TermRef => ref(tp)
426426
case tp: ThisType => This(tp.cls)
427427
case tp: SkolemType => singleton(tp.narrow)
@@ -1214,6 +1214,12 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
12141214
/** A key to be used in a context property that tracks enclosing inlined calls */
12151215
private val InlinedCalls = Property.Key[List[Tree]]()
12161216

1217+
/** A key to be used in a context property that tracks the number of inlined trees */
1218+
private val InlinedTrees = Property.Key[Counter]()
1219+
final class Counter {
1220+
var count: Int = 0
1221+
}
1222+
12171223
/** Record an enclosing inlined call.
12181224
* EmptyTree calls (for parameters) cancel the next-enclosing call in the list instead of being added to it.
12191225
* We assume parameters are never nested inside parameters.
@@ -1230,14 +1236,25 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
12301236
else
12311237
call :: oldIC
12321238

1233-
ctx.fresh.setProperty(InlinedCalls, newIC)
1239+
val ctx1 = ctx.fresh.setProperty(InlinedCalls, newIC)
1240+
if oldIC.isEmpty then ctx1.setProperty(InlinedTrees, new Counter) else ctx1
12341241
}
12351242

12361243
/** All enclosing calls that are currently inlined, from innermost to outermost.
12371244
*/
12381245
def enclosingInlineds(implicit ctx: Context): List[Tree] =
12391246
ctx.property(InlinedCalls).getOrElse(Nil)
12401247

1248+
/** Record inlined trees */
1249+
def addInlinedTrees(n: Int)(implicit ctx: Context): Unit =
1250+
ctx.property(InlinedTrees).foreach(_.count += n)
1251+
1252+
/** Check if the limit on the number of inlined trees has been reached */
1253+
def reachedInlinedTreesLimit(implicit ctx: Context): Boolean =
1254+
ctx.property(InlinedTrees) match
1255+
case Some(c) => c.count > ctx.settings.XmaxInlinedTrees.value
1256+
case None => false
1257+
12411258
/** The source file where the symbol of the `inline` method referred to by `call`
12421259
* is defined
12431260
*/

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

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class ScalaSettings extends Settings.SettingGroup {
7272
val Xhelp: Setting[Boolean] = BooleanSetting("-X", "Print a synopsis of advanced options.")
7373
val XnoForwarders: Setting[Boolean] = BooleanSetting("-Xno-forwarders", "Do not generate static forwarders in mirror classes.")
7474
val XmaxInlines: Setting[Int] = IntSetting("-Xmax-inlines", "Maximal number of successive inlines.", 32)
75+
val XmaxInlinedTrees: Setting[Int] = IntSetting("-Xmax-inlined-trees", "Maximal number of inlined trees.", 2_000_000)
7576
val Xmigration: Setting[ScalaVersion] = VersionSetting("-Xmigration", "Warn about constructs whose behavior may have changed since version.")
7677
val Xprint: Setting[List[String]] = PhasesSetting("-Xprint", "Print out program after")
7778
val XprintTypes: Setting[Boolean] = BooleanSetting("-Xprint-types", "Print tree types (debugging option).")
@@ -87,6 +88,7 @@ class ScalaSettings extends Settings.SettingGroup {
8788
val XfatalWarnings: Setting[Boolean] = BooleanSetting("-Xfatal-warnings", "Fail the compilation if there are any warnings.")
8889
val XverifySignatures: Setting[Boolean] = BooleanSetting("-Xverify-signatures", "Verify generic signatures in generated bytecode.")
8990
val XignoreScala2Macros: Setting[Boolean] = BooleanSetting("-Xignore-scala2-macros", "Ignore errors when compiling code that calls Scala2 macros, these will fail at runtime.")
91+
val XimportSuggestionTimeout: Setting[Int] = IntSetting("-Ximport-suggestion-timeout", "Timeout (in ms) for searching for import suggestions when errors are reported.", 8000)
9092

9193
val XmixinForceForwarders = ChoiceSetting(
9294
name = "-Xmixin-force-forwarders",

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ object NameOps {
270270
original.fieldName
271271
}
272272
else getterName.fieldName
273-
else FieldName(name)
273+
else FieldName(name.toSimpleName)
274274

275275
def stripScala2LocalSuffix: TermName =
276276
if (name.isScala2LocalSuffix) name.asSimpleName.dropRight(1) else name

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ class TreeUnpickler(reader: TastyReader,
578578
else
579579
ctx.newSymbol(ctx.owner, name, flags, completer, privateWithin, coord)
580580
}
581-
sym.annotations = annotFns.map(_(sym))
581+
sym.annotations = annotFns.map(_(sym.owner))
582582
if sym.isOpaqueAlias then sym.setFlag(Deferred)
583583
val isScala2MacroDefinedInScala3 = flags.is(Macro, butNot = Inline) && flags.is(Erased)
584584
ctx.owner match {

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

+6-1
Original file line numberDiff line numberDiff line change
@@ -2004,7 +2004,12 @@ object Parsers {
20042004
}
20052005

20062006
val finalizer =
2007-
if (in.token == FINALLY) { in.nextToken(); subExpr() }
2007+
if (in.token == FINALLY) {
2008+
in.nextToken();
2009+
val expr = subExpr()
2010+
if expr.span.exists then expr
2011+
else Literal(Constant(())) // finally without an expression
2012+
}
20082013
else {
20092014
if (handler.isEmpty) warning(
20102015
EmptyCatchAndFinallyBlock(body),

compiler/src/dotty/tools/dotc/transform/Constructors.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,9 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase =
251251
// Drop accessors that are not retained from class scope
252252
if (dropped.nonEmpty) {
253253
val clsInfo = cls.classInfo
254-
cls.copy(
255-
info = clsInfo.derivedClassInfo(
256-
decls = clsInfo.decls.filteredScope(!dropped.contains(_))))
254+
val decls = clsInfo.decls.filteredScope(!dropped.contains(_))
255+
val clsInfo2 = clsInfo.derivedClassInfo(decls = decls)
256+
cls.copySymDenotation(info = clsInfo2).installAfter(thisPhase)
257257
// TODO: this happens to work only because Constructors is the last phase in group
258258
}
259259

compiler/src/dotty/tools/dotc/transform/MixinOps.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont
2222
val res = member.copy(
2323
owner = cls,
2424
name = member.name.stripScala2LocalSuffix,
25-
flags = member.flags &~ Deferred | Synthetic | extraFlags,
25+
flags = member.flags &~ Deferred &~ Module | Synthetic | extraFlags,
2626
info = cls.thisType.memberInfo(member)).enteredAfter(thisPhase).asTerm
2727
res.addAnnotations(member.annotations.filter(_.symbol != defn.TailrecAnnot))
2828
res

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ class ReifyQuotes extends MacroTransform {
270270

271271
val tpe = MethodType(defn.SeqType.appliedTo(defn.AnyType) :: Nil, tree.tpe.widen)
272272
val meth = ctx.newSymbol(lambdaOwner, UniqueName.fresh(nme.ANON_FUN), Synthetic | Method, tpe)
273-
Closure(meth, tss => body(tss.head.head)(ctx.withOwner(meth)).changeOwner(ctx.owner, meth)).withSpan(tree.span)
273+
Closure(meth, tss => body(tss.head.head)(ctx.withOwner(meth)).changeNonLocalOwners(meth)).withSpan(tree.span)
274274
}
275275

276276
private def transformWithCapturer(tree: Tree)(capturer: mutable.Map[Symbol, Tree] => Tree => Tree)(implicit ctx: Context): Tree = {

compiler/src/dotty/tools/dotc/transform/TreeChecker.scala

+10-9
Original file line numberDiff line numberDiff line change
@@ -427,18 +427,19 @@ class TreeChecker extends Phase with SymTransformer {
427427
checkOwner(impl)
428428
checkOwner(impl.constr)
429429

430-
def isNonMagicalMethod(x: Symbol) =
431-
x.is(Method) &&
432-
!x.isValueClassConvertMethod &&
433-
!(x.is(Macro) && ctx.phase.refChecked) &&
434-
!x.name.is(DocArtifactName)
430+
def isNonMagicalMember(x: Symbol) =
431+
!x.isValueClassConvertMethod &&
432+
!x.name.is(DocArtifactName)
435433

436-
val symbolsNotDefined = cls.classInfo.decls.toList.toSet.filter(isNonMagicalMethod) -- impl.body.map(_.symbol) - constr.symbol
434+
val decls = cls.classInfo.decls.toList.toSet.filter(isNonMagicalMember)
435+
val defined = impl.body.map(_.symbol)
436+
437+
val symbolsNotDefined = decls -- defined - constr.symbol
437438

438439
assert(symbolsNotDefined.isEmpty,
439-
i" $cls tree does not define methods: ${symbolsNotDefined.toList}%, %\n" +
440-
i"expected: ${cls.classInfo.decls.toList.toSet.filter(isNonMagicalMethod)}%, %\n" +
441-
i"defined: ${impl.body.map(_.symbol)}%, %")
440+
i" $cls tree does not define members: ${symbolsNotDefined.toList}%, %\n" +
441+
i"expected: ${decls.toList}%, %\n" +
442+
i"defined: ${defined}%, %")
442443

443444
super.typedClassDef(cdef, cls)
444445
}

compiler/src/dotty/tools/dotc/typer/Implicits.scala

+14-10
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ object Implicits {
100100
if (wtp.derivesFrom(SingletonClass)) defn.AnyType else wtp
101101
}
102102

103+
protected def isAccessible(ref: TermRef)(using Context): Boolean
104+
103105
/** Return those references in `refs` that are compatible with type `pt`. */
104106
protected def filterMatching(pt: Type)(using Context): List[Candidate] = {
105107
record("filterMatching")
@@ -198,7 +200,8 @@ object Implicits {
198200
case _ => tp
199201

200202
var ckind =
201-
if (!ref.symbol.isAccessibleFrom(ref.prefix)) Candidate.None
203+
if !isAccessible(ref) then
204+
Candidate.None
202205
else pt match {
203206
case pt: ViewProto =>
204207
viewCandidateKind(ref.widen, pt.argType, pt.resType)
@@ -259,6 +262,9 @@ object Implicits {
259262
filterMatching(tp)
260263
}
261264

265+
override def isAccessible(ref: TermRef)(using Context): Boolean =
266+
ref.symbol.exists && !ref.symbol.is(Private)
267+
262268
override def toString: String =
263269
i"OfTypeImplicits($tp), companions = ${companionRefs.toList}%, %; refs = $refs%, %."
264270
}
@@ -326,6 +332,9 @@ object Implicits {
326332
}
327333
}
328334

335+
override def isAccessible(ref: TermRef)(using Context): Boolean =
336+
ref.symbol.isAccessibleFrom(ref.prefix)
337+
329338
override def toString: String = {
330339
val own = i"(implicits: $refs%, %)"
331340
if (isOuterMost) own else own + "\n " + outerImplicits
@@ -960,7 +969,6 @@ trait Implicits { self: Typer =>
960969
implicits.println(i"committing ${result.tstate.constraint} yielding ${ctx.typerState.constraint} in ${ctx.typerState}")
961970
result
962971
case result: SearchFailure if result.isAmbiguous =>
963-
//println(i"FAIL for $pt / $argument: $result0")
964972
val deepPt = pt.deepenProto
965973
if (deepPt ne pt) inferImplicit(deepPt, argument, span)
966974
else if (migrateTo3 && !ctx.mode.is(Mode.OldOverloadingResolution))
@@ -975,10 +983,8 @@ trait Implicits { self: Typer =>
975983
}
976984
else result
977985
case NoMatchingImplicitsFailure =>
978-
//println(i"FAIL for $pt / $argument: $result0")
979986
SearchFailure(new NoMatchingImplicits(pt, argument, ctx.typerState.constraint))
980987
case _ =>
981-
//println(i"FAIL for $pt / $argument: $result0")
982988
result0
983989
}
984990
// If we are at the outermost implicit search then emit the implicit dictionary, if any.
@@ -1024,7 +1030,9 @@ trait Implicits { self: Typer =>
10241030
case _ =>
10251031
tryConversion
10261032
}
1027-
if (ctx.reporter.hasErrors) {
1033+
if ctx.reporter.hasErrors
1034+
|| !cand.ref.symbol.isAccessibleFrom(cand.ref.prefix)
1035+
then
10281036
ctx.reporter.removeBufferedMessages
10291037
adapted.tpe match {
10301038
case _: SearchFailureType => SearchFailure(adapted)
@@ -1036,13 +1044,11 @@ trait Implicits { self: Typer =>
10361044
else
10371045
SearchFailure(adapted.withType(new MismatchedImplicit(ref, pt, argument)))
10381046
}
1039-
}
1040-
else {
1047+
else
10411048
val returned =
10421049
if (cand.isExtension) Applications.ExtMethodApply(adapted)
10431050
else adapted
10441051
SearchSuccess(returned, ref, cand.level)(ctx.typerState, ctx.gadt)
1045-
}
10461052
}
10471053

10481054
/** An implicit search; parameters as in `inferImplicit` */
@@ -1067,8 +1073,6 @@ trait Implicits { self: Typer =>
10671073

10681074
val isNot: Boolean = wildProto.classSymbol == defn.NotClass
10691075

1070-
//println(i"search implicits $pt / ${eligible.map(_.ref)}")
1071-
10721076
/** Try to type-check implicit reference, after checking that this is not
10731077
* a diverging search
10741078
*/

compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala

+15-5
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@ trait ImportSuggestions:
2727
/** Timeout to test a single implicit value as a suggestion, in ms */
2828
private inline val testOneImplicitTimeOut = 500
2929

30-
/** Global timeout to stop looking for further implicit suggestions, in ms */
31-
private inline val suggestImplicitTimeOut = 10000
32-
3330
/** A list of TermRefs referring to the roots where suggestions for
3431
* imports of givens or extension methods that might fix a type error
3532
* are searched.
@@ -145,7 +142,11 @@ trait ImportSuggestions:
145142
*/
146143
private def importSuggestions(pt: Type)(using Context): (List[TermRef], List[TermRef]) =
147144
val timer = new Timer()
148-
val deadLine = System.currentTimeMillis() + suggestImplicitTimeOut
145+
val allotted = ctx.run.importSuggestionBudget
146+
if allotted <= 1 then return (Nil, Nil)
147+
implicits.println(i"looking for import suggestions, timeout = ${allotted}ms")
148+
val start = System.currentTimeMillis()
149+
val deadLine = start + allotted
149150

150151
// Candidates that are already available without explicit import because they
151152
// are already provided by the context (imported or inherited) or because they
@@ -249,9 +250,18 @@ trait ImportSuggestions:
249250
println("caught exception when searching for suggestions")
250251
ex.printStackTrace()
251252
(Nil, Nil)
252-
finally timer.cancel()
253+
finally
254+
timer.cancel()
255+
reduceTimeBudget(((System.currentTimeMillis() - start) min Int.MaxValue).toInt)
253256
end importSuggestions
254257

258+
/** Reduce next timeout for import suggestions by the amount of time it took
259+
* for current search, but but never less than to half of the previous budget.
260+
*/
261+
private def reduceTimeBudget(used: Int)(using Context) =
262+
ctx.run.importSuggestionBudget =
263+
(ctx.run.importSuggestionBudget - used) max (ctx.run.importSuggestionBudget / 2)
264+
255265
/** The `ref` parts of this list of pairs, discarding subsequent elements that
256266
* have the same String part. Elements are sorted by their String parts.
257267
*/

0 commit comments

Comments
 (0)