Skip to content

Commit

Permalink
Merge branch 'master' into ct_ops_expansion
Browse files Browse the repository at this point in the history
  • Loading branch information
OlivierBlanvillain authored Nov 17, 2021
2 parents 762d90e + e94032c commit 75a3df2
Show file tree
Hide file tree
Showing 173 changed files with 2,529 additions and 671 deletions.
6 changes: 6 additions & 0 deletions .github/ISSUE_TEMPLATE/bug.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ If you're not sure what version you're using, run `print scalaVersion` from sbt

## Minimized code

<!--
This code should be self contained, compilable (with possible failures) and as small as possible.
Ideally, we should be able to just copy this code in a file and run `scalac` (and maybe `scala`) to reproduce the issue.
-->

```Scala
println("hello, world")
```
Expand Down
6 changes: 6 additions & 0 deletions .github/ISSUE_TEMPLATE/crash.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ If you're not sure what version you're using, run `print scalaVersion` from sbt

## Minimized code

<!--
This code should be self contained, compilable (with possible failures) and as small as possible.
Ideally, we should be able to just copy this code in a file and run `scalac` (and maybe `scala`) to reproduce the issue.
-->

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

---

Please create a syntax highlighting issue here: [scala/vscode-scala-syntax](https://github.com/scala/vscode-scala-syntax/issues).
Please create a syntax highlighting issue here
* VS Code / GitHub: https://github.com/scala/vscode-scala-syntax/issues
* IntelliJ: https://youtrack.jetbrains.com/issues/SCL?q=tag:%20%7BScala%203%7D%20tag:%20%7BSyntax%20Highlighting%7D
* highlight.js: https://github.com/highlightjs/highlight.js/issues
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,6 @@
[submodule "community-build/community-projects/scala-java8-compat"]
path = community-build/community-projects/scala-java8-compat
url = https://github.com/dotty-staging/scala-java8-compat.git
[submodule "community-build/community-projects/specs2"]
path = community-build/community-projects/specs2
url = https://github.com/dotty-staging/specs2.git
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Dotty
[![Dotty CI](https://github.com/lampepfl/dotty/workflows/Dotty/badge.svg?branch=master)](https://github.com/lampepfl/dotty/actions?query=branch%3Amaster)
[![Join the chat at https://gitter.im/scala/scala](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/scala/scala?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

* [Homepage](http://dotty.epfl.ch)
* [Homepage](https://dotty.epfl.ch)
* [Documentation](https://dotty.epfl.ch/docs)

Try it out
Expand Down
1 change: 1 addition & 0 deletions community-build/community-projects/specs2
Submodule specs2 added at 0652da
8 changes: 8 additions & 0 deletions community-build/src/scala/dotty/communitybuild/projects.scala
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,13 @@ object projects:
dependencies = List(scalaJava8Compat, scalatest)
)

lazy val specs2 = SbtCommunityProject(
project = "specs2",
sbtTestCommand = "core/testOnly -- exclude ci",
sbtPublishCommand = "core/publishLocal",
dependencies = List()
)

end projects

def allProjects = List(
Expand Down Expand Up @@ -809,6 +816,7 @@ def allProjects = List(
projects.fs2,
projects.libretto,
projects.jacksonModuleScala,
projects.specs2,
)

lazy val projectMap = allProjects.groupBy(_.project)
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class CommunityBuildTestC:
@Test def sconfig = projects.sconfig.run()
@Test def shapeless = projects.shapeless.run()
@Test def sourcecode = projects.sourcecode.run()
@Test def specs2 = projects.specs2.run()
@Test def stdLib213 = projects.stdLib213.run()
@Test def ujson = projects.ujson.run()
@Test def upickle = projects.upickle.run()
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4706,7 +4706,7 @@ object JSCodeGen {
if (!overloads.isOverloaded)
overloads.symbol
else
overloads.suchThat(_.is(HasDefaultParams)).symbol
overloads.suchThat(_.is(HasDefaultParams, butNot = Bridge)).symbol
}
}

Expand Down
23 changes: 0 additions & 23 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1410,29 +1410,6 @@ object desugar {
FunctionWithMods(params, body, Modifiers(mods))
}

/** Add annotation to tree:
* tree @fullName
*
* The annotation is usually represented as a TypeTree referring to the class
* with the given name `fullName`. However, if the annotation matches a file name
* that is still to be entered, the annotation is represented as a cascade of `Selects`
* following `fullName`. This is necessary so that we avoid reading an annotation from
* the classpath that is also compiled from source.
*/
def makeAnnotated(fullName: String, tree: Tree)(using Context): Annotated = {
val parts = fullName.split('.')
val ttree = typerPhase match {
case phase: TyperPhase if phase.stillToBeEntered(parts.last) =>
val prefix =
parts.init.foldLeft(Ident(nme.ROOTPKG): Tree)((qual, name) =>
Select(qual, name.toTermName))
Select(prefix, parts.last.toTypeName)
case _ =>
TypeTree(requiredClass(fullName).typeRef)
}
Annotated(tree, New(ttree, Nil))
}

private def derivedValDef(original: Tree, named: NameTree, tpt: Tree, rhs: Tree, mods: Modifiers)(using Context) = {
val vdef = ValDef(named.name.asTermName, tpt, rhs)
.withMods(mods)
Expand Down
11 changes: 3 additions & 8 deletions compiler/src/dotty/tools/dotc/ast/DesugarEnums.scala
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,12 @@ object DesugarEnums {
* }
*/
private def enumValueCreator(using Context) = {
val fieldMethods = if isJavaEnum then Nil else ordinalMeth(Ident(nme.ordinalDollar_)) :: Nil
val creator = New(Template(
constr = emptyConstructor,
parents = enumClassRef :: scalaRuntimeDot(tpnme.EnumValue) :: Nil,
derived = Nil,
self = EmptyValDef,
body = fieldMethods
body = Nil
).withAttachment(ExtendsSingletonMirror, ()))
DefDef(nme.DOLLAR_NEW,
List(List(param(nme.ordinalDollar_, defn.IntType), param(nme.nameDollar, defn.StringType))),
Expand Down Expand Up @@ -270,8 +269,6 @@ object DesugarEnums {
def param(name: TermName, typ: Type)(using Context): ValDef = param(name, TypeTree(typ))
def param(name: TermName, tpt: Tree)(using Context): ValDef = ValDef(name, tpt, EmptyTree).withFlags(Param)

private def isJavaEnum(using Context): Boolean = enumClass.derivesFrom(defn.JavaEnumClass)

def ordinalMeth(body: Tree)(using Context): DefDef =
DefDef(nme.ordinal, Nil, TypeTree(defn.IntType), body).withAddedFlags(Synthetic)

Expand All @@ -290,10 +287,8 @@ object DesugarEnums {
expandSimpleEnumCase(name, mods, definesLookups, span)
else {
val (tag, scaffolding) = nextOrdinal(name, CaseKind.Object, definesLookups)
val impl1 = cpy.Template(impl)(
parents = impl.parents :+ scalaRuntimeDot(tpnme.EnumValue),
body = if isJavaEnum then Nil else ordinalMethLit(tag) :: Nil
).withAttachment(ExtendsSingletonMirror, ())
val impl1 = cpy.Template(impl)(parents = impl.parents :+ scalaRuntimeDot(tpnme.EnumValue), body = Nil)
.withAttachment(ExtendsSingletonMirror, ())
val vdef = ValDef(name, TypeTree(), New(impl1)).withMods(mods.withAddedFlags(EnumValue, span))
flatTree(vdef :: scaffolding).withSpan(span)
}
Expand Down
23 changes: 22 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/NavigateAST.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import core.Contexts._
import core.Decorators._
import util.Spans._
import Trees.{MemberDef, DefTree, WithLazyField}
import dotty.tools.dotc.core.Annotations.ConcreteAnnotation
import dotty.tools.dotc.core.Types.AnnotatedType
import dotty.tools.dotc.core.Types.ImportType
import dotty.tools.dotc.core.Types.Type

/** Utility functions to go from typed to untyped ASTs */
// TODO: Handle trees with mixed source files
Expand Down Expand Up @@ -86,6 +90,18 @@ object NavigateAST {
}
bestFit
}
/*
* Annotations trees are located in the Type
*/
def unpackAnnotations(t: Type, path: List[Positioned]): List[Positioned] =
t match {
case ann: AnnotatedType =>
unpackAnnotations(ann.parent, childPath(ann.annot.tree.productIterator, path))
case imp: ImportType =>
childPath(imp.expr.productIterator, path)
case other =>
path
}
def singlePath(p: Positioned, path: List[Positioned]): List[Positioned] =
if (p.span.exists && !(skipZeroExtent && p.span.isZeroExtent) && p.span.contains(span)) {
// FIXME: We shouldn't be manually forcing trees here, we should replace
Expand All @@ -98,7 +114,12 @@ object NavigateAST {
}
childPath(p.productIterator, p :: path)
}
else path
else {
p match {
case t: untpd.TypeTree => unpackAnnotations(t.typeOpt, path)
case _ => path
}
}
singlePath(from, Nil)
}
}
11 changes: 2 additions & 9 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,7 @@ import Decorators._

object Trees {

// Note: it would be more logical to make Untyped = Nothing.
// However, this interacts in a bad way with Scala's current type inference.
// In fact, we cannot write something like Select(pre, name), where pre is
// of type Tree[Nothing]; type inference will treat the Nothing as an uninstantiated
// value and will not infer Nothing as the type parameter for Select.
// We should come back to this issue once type inference is changed.
type Untyped = Null
type Untyped = Nothing

/** The total number of created tree nodes, maintained if Stats.enabled */
@sharable var ntrees: Int = 0
Expand All @@ -44,8 +38,7 @@ object Trees {
*
* - You can never observe a `tpe` which is `null` (throws an exception)
* - So when creating a typed tree with `withType` we can re-use
* the existing tree transparently, assigning its `tpe` field,
* provided it was `null` before.
* the existing tree transparently, assigning its `tpe` field.
* - It is impossible to embed untyped trees in typed ones.
* - Typed trees can be embedded in untyped ones provided they are rooted
* in a TypedSplice node.
Expand Down
19 changes: 17 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Closure(Nil, call, targetTpt))
}

/** A closure whole anonymous function has the given method type */
/** A closure whose anonymous function has the given method type */
def Lambda(tpe: MethodType, rhsFn: List[Tree] => Tree)(using Context): Block = {
val meth = newSymbol(ctx.owner, nme.ANON_FUN, Synthetic | Method, tpe)
val meth = newAnonFun(ctx.owner, tpe)
Closure(meth, tss => rhsFn(tss.head).changeOwner(ctx.owner, meth))
}

Expand Down Expand Up @@ -1104,6 +1104,21 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
if (sym.exists) sym.defTree = tree
tree
}

def etaExpandCFT(using Context): Tree =
def expand(target: Tree, tp: Type)(using Context): Tree = tp match
case defn.ContextFunctionType(argTypes, resType, isErased) =>
val anonFun = newAnonFun(
ctx.owner,
MethodType.companion(isContextual = true, isErased = isErased)(argTypes, resType),
coord = ctx.owner.coord)
def lambdaBody(refss: List[List[Tree]]) =
expand(target.select(nme.apply).appliedToArgss(refss), resType)(
using ctx.withOwner(anonFun))
Closure(anonFun, lambdaBody)
case _ =>
target
expand(tree, tree.tpe.widen)
}

inline val MapRecursionLimit = 10
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ object ScalaSettings:
val jdkVersion = JDK9Reflectors.runtimeVersionMajor(JDK9Reflectors.runtimeVersion()).intValue()
val maxVersion = Math.min(jdkVersion, maxTargetVersion)
(minTargetVersion to maxVersion).toList.map(_.toString)
else List()
else List(minTargetVersion).map(_.toString)

def defaultClasspath: String = sys.env.getOrElse("CLASSPATH", ".")

Expand Down Expand Up @@ -218,6 +218,7 @@ private sealed trait XSettings:
val Xtarget: Setting[String] = ChoiceSetting("-Xtarget", "target", "Emit bytecode for the specified version of the Java platform. This might produce bytecode that will break at runtime. When on JDK 9+, consider -release as a safer alternative.", ScalaSettings.supportedTargetVersions, "", aliases = List("--Xtarget"))
val XcheckMacros: Setting[Boolean] = BooleanSetting("-Xcheck-macros", "Check some invariants of macro generated code while expanding macros", aliases = List("--Xcheck-macros"))
val XmainClass: Setting[String] = StringSetting("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d <jar>)", "")
val XimplicitSearchLimit: Setting[Int] = IntSetting("-Ximplicit-search-limit", "Maximal number of expressions to be generated in an implicit search", 50000)

val XmixinForceForwarders = ChoiceSetting(
name = "-Xmixin-force-forwarders",
Expand Down
38 changes: 21 additions & 17 deletions compiler/src/dotty/tools/dotc/config/Settings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,33 @@ object Settings:
changed = true
ArgsSummary(updateIn(sstate, value1), args, errors, dangers)
end update

def fail(msg: String, args: List[String]) =
ArgsSummary(sstate, args, errors :+ msg, warnings)

def missingArg =
fail(s"missing argument for option $name", args)

def setString(argValue: String, args: List[String]) =
choices match
case Some(xs) if !xs.contains(argValue) =>
fail(s"$argValue is not a valid choice for $name", args)
case _ =>
update(argValue, args)

def setInt(argValue: String, args: List[String]) =
try
val x = argValue.toInt
choices match
case Some(r: Range) if x < r.head || r.last < x =>
fail(s"$argValue is out of legal range ${r.head}..${r.last} for $name", args)
case Some(xs) if !xs.contains(x) =>
fail(s"$argValue is not a valid choice for $name", args)
case _ =>
update(x, args)
catch case _: NumberFormatException =>
fail(s"$argValue is not an integer argument for $name", args)

def doSet(argRest: String) = ((implicitly[ClassTag[T]], args): @unchecked) match {
case (BooleanTag, _) =>
update(true, args)
Expand Down Expand Up @@ -136,23 +153,10 @@ object Settings:
val output = if (isJar) JarArchive.create(path) else new PlainDirectory(path)
update(output, args)
}
case (IntTag, _) =>
val arg2 :: args2 = if (argRest == "") args else argRest :: args
try {
val x = arg2.toInt
choices match {
case Some(r: Range) if x < r.head || r.last < x =>
fail(s"$arg2 is out of legal range ${r.head}..${r.last} for $name", args2)
case Some(xs) if !xs.contains(x) =>
fail(s"$arg2 is not a valid choice for $name", args)
case _ =>
update(x, args2)
}
}
catch {
case _: NumberFormatException =>
fail(s"$arg2 is not an integer argument for $name", args2)
}
case (IntTag, args) if argRest.nonEmpty =>
setInt(argRest, args)
case (IntTag, arg2 :: args2) =>
setInt(arg2, args2)
case (VersionTag, _) =>
ScalaVersion.parse(argRest) match {
case Success(v) => update(v, args)
Expand Down
27 changes: 5 additions & 22 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@ class Definitions {
@tu lazy val NoneModule: Symbol = requiredModule("scala.None")

@tu lazy val EnumClass: ClassSymbol = requiredClass("scala.reflect.Enum")
@tu lazy val Enum_ordinal: Symbol = EnumClass.requiredMethod(nme.ordinal)

@tu lazy val EnumValueSerializationProxyClass: ClassSymbol = requiredClass("scala.runtime.EnumValueSerializationProxy")
@tu lazy val EnumValueSerializationProxyConstructor: TermSymbol =
Expand Down Expand Up @@ -1380,23 +1381,6 @@ class Definitions {
def isBoxedUnitClass(cls: Symbol): Boolean =
cls.isClass && (cls.owner eq ScalaRuntimePackageClass) && cls.name == tpnme.BoxedUnit

/** Returns the erased class of the function class `cls`
* - FunctionN for N > 22 becomes FunctionXXL
* - FunctionN for 22 > N >= 0 remains as FunctionN
* - ContextFunctionN for N > 22 becomes FunctionXXL
* - ContextFunctionN for N <= 22 becomes FunctionN
* - ErasedFunctionN becomes Function0
* - ImplicitErasedFunctionN becomes Function0
* - anything else becomes a NoSymbol
*/
def erasedFunctionClass(cls: Symbol): Symbol = {
val arity = scalaClassName(cls).functionArity
if (cls.name.isErasedFunction) FunctionClass(0)
else if (arity > 22) FunctionXXLClass
else if (arity >= 0) FunctionClass(arity)
else NoSymbol
}

/** Returns the erased type of the function class `cls`
* - FunctionN for N > 22 becomes FunctionXXL
* - FunctionN for 22 > N >= 0 remains as FunctionN
Expand All @@ -1406,13 +1390,12 @@ class Definitions {
* - ImplicitErasedFunctionN becomes Function0
* - anything else becomes a NoType
*/
def erasedFunctionType(cls: Symbol): Type = {
def functionTypeErasure(cls: Symbol): Type =
val arity = scalaClassName(cls).functionArity
if (cls.name.isErasedFunction) FunctionType(0)
else if (arity > 22) FunctionXXLClass.typeRef
else if (arity >= 0) FunctionType(arity)
if cls.name.isErasedFunction then FunctionType(0)
else if arity > 22 then FunctionXXLClass.typeRef
else if arity >= 0 then FunctionType(arity)
else NoType
}

val predefClassNames: Set[Name] =
Set("Predef$", "DeprecatedPredef", "LowPriorityImplicits").map(_.toTypeName.unmangleClassName)
Expand Down
Loading

0 comments on commit 75a3df2

Please sign in to comment.