Skip to content

Make given clauses come last #6513

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
May 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class Compiler {
new ExpandSAMs, // Expand single abstract method closures to anonymous classes
new ProtectedAccessors, // Add accessors for protected members
new ExtensionMethods, // Expand methods of value classes with extension methods
new CacheAliasImplicits, // Cache RHS of parameterless alias implicits
new ShortcutImplicits, // Allow implicit functions without creating closures
new ByNameClosures, // Expand arguments to by-name parameters to closures
new HoistSuperArgs, // Hoist complex arguments of supercalls to enclosing scope
Expand Down
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,15 @@ object desugar {
case _ =>
constrVparamss
}
New(classTypeRef, vparamss.nestedMap(refOfDef))
val nu = (makeNew(classTypeRef) /: vparamss) { (nu, vparams) =>
val app = Apply(nu, vparams.map(refOfDef))
vparams match {
case vparam :: _ if vparam.mods.is(Given) => app.pushAttachment(ApplyGiven, ())
case _ =>
}
app
}
ensureApplied(nu)
}

val copiedAccessFlags = if (ctx.scala2Setting) EmptyFlags else AccessFlags
Expand Down
9 changes: 7 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/NavigateAST.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,21 @@ object NavigateAST {
*/
def pathTo(span: Span, from: Positioned, skipZeroExtent: Boolean = false)(implicit ctx: Context): List[Positioned] = {
def childPath(it: Iterator[Any], path: List[Positioned]): List[Positioned] = {
var bestFit: List[Positioned] = path
while (it.hasNext) {
val path1 = it.next() match {
case p: Positioned => singlePath(p, path)
case m: untpd.Modifiers => childPath(m.productIterator, path)
case xs: List[_] => childPath(xs.iterator, path)
case _ => path
}
if (path1 ne path) return path1
if ((path1 ne path) &&
((bestFit eq path) ||
bestFit.head.span != path1.head.span &&
bestFit.head.span.contains(path1.head.span)))
bestFit = path1
}
path
bestFit
}
def singlePath(p: Positioned, path: List[Positioned]): List[Positioned] =
if (p.span.exists && !(skipZeroExtent && p.span.isZeroExtent) && p.span.contains(span)) {
Expand Down
7 changes: 6 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/Positioned.scala
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Pro
}
}

/** A hook that can be overridden if overlap checking in `checkPos` should be
* disabled for this node.
*/
def disableOverlapChecks = false

/** Check that all positioned items in this tree satisfy the following conditions:
* - Parent spans contain child spans
* - If item is a non-empty tree, it has a position
Expand All @@ -169,7 +174,7 @@ abstract class Positioned(implicit @constructorOnly src: SourceFile) extends Pro
s"position error: position not set for $tree # ${tree.uniqueId}")
case _ =>
}
if (nonOverlapping) {
if (nonOverlapping && !disableOverlapChecks) {
this match {
case _: XMLBlock =>
// FIXME: Trees generated by the XML parser do not satisfy `checkPos`
Expand Down
8 changes: 8 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,10 @@ object Trees {
assert(tpt != genericEmptyTree)
def unforced: LazyTree = preRhs
protected def force(x: AnyRef): Unit = preRhs = x

override def disableOverlapChecks = rawMods.is(Flags.Implied)
// disable order checks for implicit aliases since their given clause follows
// their for clause, but the two appear swapped in the DefDef.
}

class BackquotedDefDef[-T >: Untyped] private[ast] (name: TermName, tparams: List[TypeDef[T]],
Expand Down Expand Up @@ -783,6 +787,10 @@ object Trees {

def parents: List[Tree[T]] = parentsOrDerived // overridden by DerivingTemplate
def derived: List[untpd.Tree] = Nil // overridden by DerivingTemplate

override def disableOverlapChecks = true
// disable overlaps checks since templates of instance definitions have their
// `given` clause come last, which means that the constructor span can contain the parent spans.
}


Expand Down
7 changes: 5 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def unitLiteral(implicit ctx: Context): Literal =
Literal(Constant(()))

def nullLiteral(implicit ctx: Context): Literal =
Literal(Constant(null))

def New(tpt: Tree)(implicit ctx: Context): New =
ta.assignType(untpd.New(tpt), tpt)

Expand Down Expand Up @@ -496,7 +499,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
else if (tpw isRef defn.DoubleClass) Literal(Constant(0d))
else if (tpw isRef defn.ByteClass) Literal(Constant(0.toByte))
else if (tpw isRef defn.ShortClass) Literal(Constant(0.toShort))
else Literal(Constant(null)).select(defn.Any_asInstanceOf).appliedToType(tpe)
else nullLiteral.select(defn.Any_asInstanceOf).appliedToType(tpe)
}

private class FindLocalDummyAccumulator(cls: ClassSymbol)(implicit ctx: Context) extends TreeAccumulator[Symbol] {
Expand Down Expand Up @@ -915,7 +918,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Typed(tree, TypeTree(defn.AnyRefType))
}
else tree.ensureConforms(defn.ObjectType)
receiver.select(defn.Object_ne).appliedTo(Literal(Constant(null)))
receiver.select(defn.Object_ne).appliedTo(nullLiteral)
}

/** If inititializer tree is `_', the default value of its type,
Expand Down
19 changes: 12 additions & 7 deletions compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
override def isType: Boolean = body.isType
}

/** A function type with `implicit`, `erased`, or `contextual` modifiers */
/** A function type with `implicit`, `erased`, or `given` modifiers */
class FunctionWithMods(args: List[Tree], body: Tree, val mods: Modifiers)(implicit @constructorOnly src: SourceFile)
extends Function(args, body)

Expand Down Expand Up @@ -343,7 +343,13 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
* navigation into these arguments from the IDE, and to do the right thing in
* PrepareInlineable.
*/
def New(tpt: Tree, argss: List[List[Tree]])(implicit ctx: Context): Tree = {
def New(tpt: Tree, argss: List[List[Tree]])(implicit ctx: Context): Tree =
ensureApplied((makeNew(tpt) /: argss)(Apply(_, _)))

/** A new expression with constrictor and possibly type arguments. See
* `New(tpt, argss)` for details.
*/
def makeNew(tpt: Tree)(implicit ctx: Context): Tree = {
val (tycon, targs) = tpt match {
case AppliedTypeTree(tycon, targs) =>
(tycon, targs)
Expand All @@ -354,9 +360,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case _ =>
(tpt, Nil)
}
var prefix: Tree = Select(New(tycon), nme.CONSTRUCTOR)
if (targs.nonEmpty) prefix = TypeApply(prefix, targs)
ensureApplied((prefix /: argss)(Apply(_, _)))
val nu: Tree = Select(New(tycon), nme.CONSTRUCTOR)
if (targs.nonEmpty) TypeApply(nu, targs) else nu
}

def Block(stat: Tree, expr: Tree)(implicit src: SourceFile): Block =
Expand Down Expand Up @@ -415,9 +420,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
vdef.withMods(mods | Param)
}

def makeSyntheticParameter(n: Int = 1, tpt: Tree = null, flags: FlagSet = EmptyFlags)(implicit ctx: Context): ValDef =
def makeSyntheticParameter(n: Int = 1, tpt: Tree = null, flags: FlagSet = SyntheticTermParam)(implicit ctx: Context): ValDef =
ValDef(nme.syntheticParamName(n), if (tpt == null) TypeTree() else tpt, EmptyTree)
.withFlags(flags | SyntheticTermParam)
.withFlags(flags)

def lambdaAbstract(tparams: List[TypeDef], tpt: Tree)(implicit ctx: Context): Tree =
if (tparams.isEmpty) tpt else LambdaTypeTree(tparams, tpt)
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ object Flags {
/** Symbol is an enum class or enum case (if used with case) */
final val Enum: FlagSet = commonFlag(40, "<enum>")

/** An export forwarder */
final val Exported: FlagSet = commonFlag(41, "exported")

/** Labeled with `erased` modifier (erased value) */
final val Erased: FlagSet = termFlag(42, "erased")

Expand Down Expand Up @@ -459,7 +462,7 @@ object Flags {

/** Flags representing source modifiers */
private val CommonSourceModifierFlags: FlagSet =
commonFlags(Private, Protected, Final, Case, Implicit, Implied, Override, JavaStatic)
commonFlags(Private, Protected, Final, Case, Implicit, Implied, Given, Override, JavaStatic)

final val TypeSourceModifierFlags: FlagSet =
CommonSourceModifierFlags.toTypeFlags | Abstract | Sealed | Opaque
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/NameKinds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ object NameKinds {
val InlineAccessorName: PrefixNameKind = new PrefixNameKind(INLINEACCESSOR, "inline$")

val AvoidClashName: SuffixNameKind = new SuffixNameKind(AVOIDCLASH, "$_avoid_name_clash_$")
val CacheName = new SuffixNameKind(CACHE, "$_cache")
val DirectMethodName: SuffixNameKind = new SuffixNameKind(DIRECT, "$direct") { override def definesNewName = true }
val FieldName: SuffixNameKind = new SuffixNameKind(FIELD, "$$local") {
override def mkString(underlying: TermName, info: ThisInfo) = underlying.toString
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/core/NameTags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ object NameTags extends TastyFormat.NameTags {
final val IMPLMETH = 32 // Used to define methods in implementation classes
// (can probably be removed).

final val CACHE = 33 // Used as a cache for the rhs of an alias implicit.

def nameTagToString(tag: Int): String = tag match {
case UTF8 => "UTF8"
case QUALIFIED => "QUALIFIED"
Expand Down
6 changes: 5 additions & 1 deletion compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ Standard-Section: "ASTs" TopLevelStat*
EXTENSION -- An extension method
GIVEN -- A new style implicit parameter, introduced with `given`
PARAMsetter -- The setter part `x_=` of a var parameter `x` which itself is pickled as a PARAM
EXPORTED -- An export forwarder
Annotation

Annotation = ANNOTATION Length tycon_Type fullAnnotation_Term -- An annotation, given (class) type of constructor, and full application tree
Expand Down Expand Up @@ -329,6 +330,7 @@ object TastyFormat {
final val GIVEN = 37
final val IMPLIED = 38
final val PARAMsetter = 39
final val EXPORTED = 40

// Cat. 2: tag Nat

Expand Down Expand Up @@ -457,7 +459,7 @@ object TastyFormat {

/** Useful for debugging */
def isLegalTag(tag: Int): Boolean =
firstSimpleTreeTag <= tag && tag <= PARAMsetter ||
firstSimpleTreeTag <= tag && tag <= EXPORTED ||
firstNatTreeTag <= tag && tag <= SYMBOLconst ||
firstASTTreeTag <= tag && tag <= SINGLETONtpt ||
firstNatASTTreeTag <= tag && tag <= NAMEDARG ||
Expand Down Expand Up @@ -500,6 +502,7 @@ object TastyFormat {
| EXTENSION
| GIVEN
| PARAMsetter
| EXPORTED
| ANNOTATION
| PRIVATEqualified
| PROTECTEDqualified => true
Expand Down Expand Up @@ -560,6 +563,7 @@ object TastyFormat {
case EXTENSION => "EXTENSION"
case GIVEN => "GIVEN"
case PARAMsetter => "PARAMsetter"
case EXPORTED => "EXPORTED"

case SHAREDterm => "SHAREDterm"
case SHAREDtype => "SHAREDtype"
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,7 @@ class TreePickler(pickler: TastyPickler) {
if (flags is Extension) writeByte(EXTENSION)
if (flags is Given) writeByte(GIVEN)
if (flags is ParamAccessor) writeByte(PARAMsetter)
if (flags is Exported) writeByte(EXPORTED)
assert(!(flags is Label))
} else {
if (flags is Sealed) writeByte(SEALED)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -632,8 +632,8 @@ class TreeUnpickler(reader: TastyReader,
case STABLE => addFlag(StableRealizable)
case EXTENSION => addFlag(Extension)
case GIVEN => addFlag(Given)
case PARAMsetter =>
addFlag(ParamAccessor)
case PARAMsetter => addFlag(ParamAccessor)
case EXPORTED => addFlag(Exported)
case PRIVATEqualified =>
readByte()
privateWithin = readWithin(ctx)
Expand Down
Loading