Skip to content

Commit

Permalink
Merge branch 'master' into 0.25.x
Browse files Browse the repository at this point in the history
  • Loading branch information
anatoliykmetyuk committed Jun 15, 2020
2 parents c89cf41 + cc4eeb5 commit ef3dacb
Show file tree
Hide file tree
Showing 75 changed files with 2,916 additions and 152 deletions.
13 changes: 1 addition & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
Dotty
=====
[![Build Status](http://dotty-ci.epfl.ch/api/badges/lampepfl/dotty/status.svg)](http://dotty-ci.epfl.ch/lampepfl/dotty)
[![Dotty CI](https://github.com/lampepfl/dotty/workflows/Dotty%20CI/badge.svg?branch=master)](https://github.com/lampepfl/dotty/actions?query=branch%3Amaster)
[![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)
[![Log Knowledge](https://img.shields.io/badge/log-knowledge-blueviolet.svg)](https://github.com/lampepfl/dotty-knowledge/issues/new/choose)


* [Homepage](http://dotty.epfl.ch)
* [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)
* [Documentation](https://dotty.epfl.ch/docs)

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

## Contribute Internals-related Knowledge
If you know anything useful at all about Dotty, feel free to log this knowledge:

- [📜Log the Knowledge](https://github.com/lampepfl/dotty-knowledge/issues/new/choose)
- [🎓More about Logging the Knowledge](https://github.com/lampepfl/dotty-knowledge/blob/master/README.md)

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.

License
=======
Dotty is licensed under the [Apache License Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
2 changes: 1 addition & 1 deletion community-build/community-projects/shapeless
Submodule shapeless updated 2 files
+1 −1 .travis.yml
+1 −1 build.sbt
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1531,9 +1531,9 @@ class JSCodeGen()(implicit ctx: Context) {
case jstpe.LongType =>
js.BinaryOp(js.BinaryOp.Long_-, js.LongLiteral(0), genArg)
case jstpe.FloatType =>
js.BinaryOp(js.BinaryOp.Float_-, js.FloatLiteral(0.0f), genArg)
js.BinaryOp(js.BinaryOp.Float_*, js.FloatLiteral(-1.0f), genArg)
case jstpe.DoubleType =>
js.BinaryOp(js.BinaryOp.Double_-, js.DoubleLiteral(0), genArg)
js.BinaryOp(js.BinaryOp.Double_*, js.DoubleLiteral(-1.0), genArg)
}

case NOT =>
Expand Down
14 changes: 14 additions & 0 deletions compiler/src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ import scala.util.control.NonFatal
/** A compiler run. Exports various methods to compile source files */
class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with ConstraintRunInfo {

/** Default timeout to stop looking for further implicit suggestions, in ms.
* This is usually for the first import suggestion; subsequent suggestions
* may get smaller timeouts. @see ImportSuggestions.reduceTimeBudget
*/
private var myImportSuggestionBudget: Int =
Int.MinValue // sentinel value; means whatever is set in command line option

def importSuggestionBudget =
if myImportSuggestionBudget == Int.MinValue then ictx.settings.XimportSuggestionTimeout.value
else myImportSuggestionBudget

def importSuggestionBudget_=(x: Int) =
myImportSuggestionBudget = x

/** If this variable is set to `true`, some core typer operations will
* return immediately. Currently these early abort operations are
* `Typer.typed` and `Implicits.typedImplicit`.
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,7 @@ object desugar {
case TypeDef(_, rhs) =>
def rhsOK(tree: Tree): Boolean = tree match {
case bounds: TypeBoundsTree => !bounds.alias.isEmpty
case _: Template => false
case _: Template | _: MatchTypeTree => false
case LambdaTypeTree(_, body) => rhsOK(body)
case _ => true
}
Expand Down
21 changes: 19 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
t
}

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

/** A key to be used in a context property that tracks the number of inlined trees */
private val InlinedTrees = Property.Key[Counter]()
final class Counter {
var count: Int = 0
}

/** Record an enclosing inlined call.
* EmptyTree calls (for parameters) cancel the next-enclosing call in the list instead of being added to it.
* We assume parameters are never nested inside parameters.
Expand All @@ -1230,14 +1236,25 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
else
call :: oldIC

ctx.fresh.setProperty(InlinedCalls, newIC)
val ctx1 = ctx.fresh.setProperty(InlinedCalls, newIC)
if oldIC.isEmpty then ctx1.setProperty(InlinedTrees, new Counter) else ctx1
}

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

/** Record inlined trees */
def addInlinedTrees(n: Int)(implicit ctx: Context): Unit =
ctx.property(InlinedTrees).foreach(_.count += n)

/** Check if the limit on the number of inlined trees has been reached */
def reachedInlinedTreesLimit(implicit ctx: Context): Boolean =
ctx.property(InlinedTrees) match
case Some(c) => c.count > ctx.settings.XmaxInlinedTrees.value
case None => false

/** The source file where the symbol of the `inline` method referred to by `call`
* is defined
*/
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class ScalaSettings extends Settings.SettingGroup {
val Xhelp: Setting[Boolean] = BooleanSetting("-X", "Print a synopsis of advanced options.")
val XnoForwarders: Setting[Boolean] = BooleanSetting("-Xno-forwarders", "Do not generate static forwarders in mirror classes.")
val XmaxInlines: Setting[Int] = IntSetting("-Xmax-inlines", "Maximal number of successive inlines.", 32)
val XmaxInlinedTrees: Setting[Int] = IntSetting("-Xmax-inlined-trees", "Maximal number of inlined trees.", 2_000_000)
val Xmigration: Setting[ScalaVersion] = VersionSetting("-Xmigration", "Warn about constructs whose behavior may have changed since version.")
val Xprint: Setting[List[String]] = PhasesSetting("-Xprint", "Print out program after")
val XprintTypes: Setting[Boolean] = BooleanSetting("-Xprint-types", "Print tree types (debugging option).")
Expand All @@ -87,6 +88,7 @@ class ScalaSettings extends Settings.SettingGroup {
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.")
val XimportSuggestionTimeout: Setting[Int] = IntSetting("-Ximport-suggestion-timeout", "Timeout (in ms) for searching for import suggestions when errors are reported.", 8000)

val XmixinForceForwarders = ChoiceSetting(
name = "-Xmixin-force-forwarders",
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/NameOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ object NameOps {
original.fieldName
}
else getterName.fieldName
else FieldName(name)
else FieldName(name.toSimpleName)

def stripScala2LocalSuffix: TermName =
if (name.isScala2LocalSuffix) name.asSimpleName.dropRight(1) else name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ class TreeUnpickler(reader: TastyReader,
else
ctx.newSymbol(ctx.owner, name, flags, completer, privateWithin, coord)
}
sym.annotations = annotFns.map(_(sym))
sym.annotations = annotFns.map(_(sym.owner))
if sym.isOpaqueAlias then sym.setFlag(Deferred)
val isScala2MacroDefinedInScala3 = flags.is(Macro, butNot = Inline) && flags.is(Erased)
ctx.owner match {
Expand Down
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2004,7 +2004,12 @@ object Parsers {
}

val finalizer =
if (in.token == FINALLY) { in.nextToken(); subExpr() }
if (in.token == FINALLY) {
in.nextToken();
val expr = subExpr()
if expr.span.exists then expr
else Literal(Constant(())) // finally without an expression
}
else {
if (handler.isEmpty) warning(
EmptyCatchAndFinallyBlock(body),
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/transform/Constructors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,9 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase =
// Drop accessors that are not retained from class scope
if (dropped.nonEmpty) {
val clsInfo = cls.classInfo
cls.copy(
info = clsInfo.derivedClassInfo(
decls = clsInfo.decls.filteredScope(!dropped.contains(_))))
val decls = clsInfo.decls.filteredScope(!dropped.contains(_))
val clsInfo2 = clsInfo.derivedClassInfo(decls = decls)
cls.copySymDenotation(info = clsInfo2).installAfter(thisPhase)
// TODO: this happens to work only because Constructors is the last phase in group
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/MixinOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont
val res = member.copy(
owner = cls,
name = member.name.stripScala2LocalSuffix,
flags = member.flags &~ Deferred | Synthetic | extraFlags,
flags = member.flags &~ Deferred &~ Module | Synthetic | extraFlags,
info = cls.thisType.memberInfo(member)).enteredAfter(thisPhase).asTerm
res.addAnnotations(member.annotations.filter(_.symbol != defn.TailrecAnnot))
res
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ class ReifyQuotes extends MacroTransform {

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

private def transformWithCapturer(tree: Tree)(capturer: mutable.Map[Symbol, Tree] => Tree => Tree)(implicit ctx: Context): Tree = {
Expand Down
19 changes: 10 additions & 9 deletions compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -427,18 +427,19 @@ class TreeChecker extends Phase with SymTransformer {
checkOwner(impl)
checkOwner(impl.constr)

def isNonMagicalMethod(x: Symbol) =
x.is(Method) &&
!x.isValueClassConvertMethod &&
!(x.is(Macro) && ctx.phase.refChecked) &&
!x.name.is(DocArtifactName)
def isNonMagicalMember(x: Symbol) =
!x.isValueClassConvertMethod &&
!x.name.is(DocArtifactName)

val symbolsNotDefined = cls.classInfo.decls.toList.toSet.filter(isNonMagicalMethod) -- impl.body.map(_.symbol) - constr.symbol
val decls = cls.classInfo.decls.toList.toSet.filter(isNonMagicalMember)
val defined = impl.body.map(_.symbol)

val symbolsNotDefined = decls -- defined - constr.symbol

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

super.typedClassDef(cdef, cls)
}
Expand Down
24 changes: 14 additions & 10 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ object Implicits {
if (wtp.derivesFrom(SingletonClass)) defn.AnyType else wtp
}

protected def isAccessible(ref: TermRef)(using Context): Boolean

/** Return those references in `refs` that are compatible with type `pt`. */
protected def filterMatching(pt: Type)(using Context): List[Candidate] = {
record("filterMatching")
Expand Down Expand Up @@ -198,7 +200,8 @@ object Implicits {
case _ => tp

var ckind =
if (!ref.symbol.isAccessibleFrom(ref.prefix)) Candidate.None
if !isAccessible(ref) then
Candidate.None
else pt match {
case pt: ViewProto =>
viewCandidateKind(ref.widen, pt.argType, pt.resType)
Expand Down Expand Up @@ -259,6 +262,9 @@ object Implicits {
filterMatching(tp)
}

override def isAccessible(ref: TermRef)(using Context): Boolean =
ref.symbol.exists && !ref.symbol.is(Private)

override def toString: String =
i"OfTypeImplicits($tp), companions = ${companionRefs.toList}%, %; refs = $refs%, %."
}
Expand Down Expand Up @@ -326,6 +332,9 @@ object Implicits {
}
}

override def isAccessible(ref: TermRef)(using Context): Boolean =
ref.symbol.isAccessibleFrom(ref.prefix)

override def toString: String = {
val own = i"(implicits: $refs%, %)"
if (isOuterMost) own else own + "\n " + outerImplicits
Expand Down Expand Up @@ -960,7 +969,6 @@ trait Implicits { self: Typer =>
implicits.println(i"committing ${result.tstate.constraint} yielding ${ctx.typerState.constraint} in ${ctx.typerState}")
result
case result: SearchFailure if result.isAmbiguous =>
//println(i"FAIL for $pt / $argument: $result0")
val deepPt = pt.deepenProto
if (deepPt ne pt) inferImplicit(deepPt, argument, span)
else if (migrateTo3 && !ctx.mode.is(Mode.OldOverloadingResolution))
Expand All @@ -975,10 +983,8 @@ trait Implicits { self: Typer =>
}
else result
case NoMatchingImplicitsFailure =>
//println(i"FAIL for $pt / $argument: $result0")
SearchFailure(new NoMatchingImplicits(pt, argument, ctx.typerState.constraint))
case _ =>
//println(i"FAIL for $pt / $argument: $result0")
result0
}
// If we are at the outermost implicit search then emit the implicit dictionary, if any.
Expand Down Expand Up @@ -1024,7 +1030,9 @@ trait Implicits { self: Typer =>
case _ =>
tryConversion
}
if (ctx.reporter.hasErrors) {
if ctx.reporter.hasErrors
|| !cand.ref.symbol.isAccessibleFrom(cand.ref.prefix)
then
ctx.reporter.removeBufferedMessages
adapted.tpe match {
case _: SearchFailureType => SearchFailure(adapted)
Expand All @@ -1036,13 +1044,11 @@ trait Implicits { self: Typer =>
else
SearchFailure(adapted.withType(new MismatchedImplicit(ref, pt, argument)))
}
}
else {
else
val returned =
if (cand.isExtension) Applications.ExtMethodApply(adapted)
else adapted
SearchSuccess(returned, ref, cand.level)(ctx.typerState, ctx.gadt)
}
}

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

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

//println(i"search implicits $pt / ${eligible.map(_.ref)}")

/** Try to type-check implicit reference, after checking that this is not
* a diverging search
*/
Expand Down
20 changes: 15 additions & 5 deletions compiler/src/dotty/tools/dotc/typer/ImportSuggestions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ trait ImportSuggestions:
/** Timeout to test a single implicit value as a suggestion, in ms */
private inline val testOneImplicitTimeOut = 500

/** Global timeout to stop looking for further implicit suggestions, in ms */
private inline val suggestImplicitTimeOut = 10000

/** A list of TermRefs referring to the roots where suggestions for
* imports of givens or extension methods that might fix a type error
* are searched.
Expand Down Expand Up @@ -145,7 +142,11 @@ trait ImportSuggestions:
*/
private def importSuggestions(pt: Type)(using Context): (List[TermRef], List[TermRef]) =
val timer = new Timer()
val deadLine = System.currentTimeMillis() + suggestImplicitTimeOut
val allotted = ctx.run.importSuggestionBudget
if allotted <= 1 then return (Nil, Nil)
implicits.println(i"looking for import suggestions, timeout = ${allotted}ms")
val start = System.currentTimeMillis()
val deadLine = start + allotted

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

/** Reduce next timeout for import suggestions by the amount of time it took
* for current search, but but never less than to half of the previous budget.
*/
private def reduceTimeBudget(used: Int)(using Context) =
ctx.run.importSuggestionBudget =
(ctx.run.importSuggestionBudget - used) max (ctx.run.importSuggestionBudget / 2)

/** The `ref` parts of this list of pairs, discarding subsequent elements that
* have the same String part. Elements are sorted by their String parts.
*/
Expand Down
Loading

0 comments on commit ef3dacb

Please sign in to comment.