aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/dotty')
-rw-r--r--compiler/src/dotty/tools/backend/jvm/LabelDefs.scala45
-rw-r--r--compiler/src/dotty/tools/dotc/Run.scala3
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Desugar.scala26
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Positioned.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/ast/TreeInfo.scala22
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Trees.scala188
-rw-r--r--compiler/src/dotty/tools/dotc/ast/tpd.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/ast/untpd.scala22
-rw-r--r--compiler/src/dotty/tools/dotc/config/ScalaSettings.scala18
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala18
-rw-r--r--compiler/src/dotty/tools/dotc/core/Phases.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/core/StdNames.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala11
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/parsing/Parsers.scala26
-rw-r--r--compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/printing/package.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/transform/Erasure.scala4
-rw-r--r--compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala27
-rw-r--r--compiler/src/dotty/tools/dotc/transform/Mixin.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/PostTyper.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Checking.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Dynamic.scala66
-rw-r--r--compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Implicits.scala6
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Inliner.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Namer.scala23
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala89
-rw-r--r--compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala12
34 files changed, 417 insertions, 250 deletions
diff --git a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala
index 371396e36..654507991 100644
--- a/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala
+++ b/compiler/src/dotty/tools/backend/jvm/LabelDefs.scala
@@ -37,44 +37,47 @@ import StdNames.nme
/**
* Verifies that each Label DefDef has only a single address to jump back and
- * reorders them such that they are not nested and this address is a fall-through address for JVM
- *
- * ei such code
- *
+ * reorders them such that they are not nested and this address is a
+ * fall-through address for the JVM.
*
+ * ```scala
* <label> def foo(i: Int) = {
* <label> def bar = 0
* <label> def dough(i: Int) = if (i == 0) bar else foo(i-1)
* dough(i)
- * }
+ * }
*
* foo(100)
+ * ```
*
- * will get rewritten to
+ * will get rewritten to:
*
- * \
+ * ```scala
* <label> def foo(i: Int) = dough(i)
* <label> def dough(i: Int) = if (i == 0) bar else foo(i-1)
* <label> def bar = 2
* foo(100)
+ * ```
*
- * Proposed way to generate this pattern in backend is:
+ * Proposed way to generate this pattern in backend is:
*
- * foo(100)
- * <jump foo>
- * <label> def foo(i: Int) = dough(i)
- * // <jump a> // unreachable
- * <label> def dough(i: Int) = if (i == 0) bar else foo(i-1)
- * // <jump a> // unreachable
- * <label> def bar = 2
- * // <jump a> // unreachable
- * <asm point a>
+ * ```scala
+ * foo(100)
+ * <jump foo>
+ * <label> def foo(i: Int) = dough(i)
+ * // <jump a> // unreachable
+ * <label> def dough(i: Int) = if (i == 0) bar else foo(i-1)
+ * // <jump a> // unreachable
+ * <label> def bar = 2
+ * // <jump a> // unreachable
+ * <asm point a>
+ * ```
*
- * Unreachable jumps will be eliminated by local dead code analysis.
- * After JVM is smart enough to remove next-line jumps
+ * Unreachable jumps will be eliminated by local dead code analysis.
+ * After JVM is smart enough to remove next-line jumps
*
- * Note that Label DefDefs can be only nested in Block, otherwise no one would be able to call them
- * Other DefDefs are eliminated
+ * Note that Label DefDefs can be only nested in Block, otherwise no one would
+ * be able to call them Other DefDefs are eliminated
*/
class LabelDefs extends MiniPhaseTransform {
def phaseName: String = "labelDef"
diff --git a/compiler/src/dotty/tools/dotc/Run.scala b/compiler/src/dotty/tools/dotc/Run.scala
index 0f652ff0b..38bf80bad 100644
--- a/compiler/src/dotty/tools/dotc/Run.scala
+++ b/compiler/src/dotty/tools/dotc/Run.scala
@@ -15,6 +15,7 @@ import reporting.Reporter
import transform.TreeChecker
import rewrite.Rewrites
import java.io.{BufferedWriter, OutputStreamWriter}
+import printing.XprintMode
import scala.annotation.tailrec
import scala.reflect.io.VirtualFile
@@ -95,7 +96,7 @@ class Run(comp: Compiler)(implicit ctx: Context) {
val unit = ctx.compilationUnit
val prevPhase = ctx.phase.prev // can be a mini-phase
val squashedPhase = ctx.squashed(prevPhase)
- val treeString = unit.tpdTree.show
+ val treeString = unit.tpdTree.show(ctx.withProperty(XprintMode, Some(())))
ctx.echo(s"result of $unit after $squashedPhase:")
diff --git a/compiler/src/dotty/tools/dotc/ast/Desugar.scala b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
index 2e471e046..eda4a12dc 100644
--- a/compiler/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Desugar.scala
@@ -353,7 +353,7 @@ object desugar {
for (i <- 0 until arity if nme.selectorName(i) `ne` caseParams(i).name)
yield syntheticProperty(nme.selectorName(i), Select(This(EmptyTypeIdent), caseParams(i).name))
def isRepeated(tree: Tree): Boolean = tree match {
- case PostfixOp(_, nme.raw.STAR) => true
+ case PostfixOp(_, Ident(nme.raw.STAR)) => true
case ByNameTypeTree(tree1) => isRepeated(tree1)
case _ => false
}
@@ -739,23 +739,25 @@ object desugar {
/** Translate infix operation expression left op right
*/
- def makeBinop(left: Tree, op: Name, right: Tree): Tree = {
+ def makeBinop(left: Tree, op: Ident, right: Tree): Tree = {
def assignToNamedArg(arg: Tree) = arg match {
case Assign(Ident(name), rhs) => cpy.NamedArg(arg)(name, rhs)
case _ => arg
}
- if (isLeftAssoc(op)) {
+ if (isLeftAssoc(op.name)) {
val args: List[Tree] = right match {
case Parens(arg) => assignToNamedArg(arg) :: Nil
case Tuple(args) => args mapConserve assignToNamedArg
case _ => right :: Nil
}
- Apply(Select(left, op), args)
+ val selectPos = Position(left.pos.start, op.pos.end, op.pos.start)
+ Apply(Select(left, op.name).withPos(selectPos), args)
} else {
val x = ctx.freshName().toTermName
+ val selectPos = Position(op.pos.start, right.pos.end, op.pos.start)
new InfixOpBlock(
ValDef(x, TypeTree(), left).withMods(synthetic),
- Apply(Select(right, op), Ident(x)))
+ Apply(Select(right, op.name).withPos(selectPos), Ident(x).withPos(left.pos)))
}
}
@@ -956,25 +958,25 @@ object desugar {
Apply(Select(Apply(Ident(nme.StringContext), strs), id), elems)
case InfixOp(l, op, r) =>
if (ctx.mode is Mode.Type)
- if (op == tpnme.raw.AMP) AndTypeTree(l, r) // l & r
- else if (op == tpnme.raw.BAR) OrTypeTree(l, r) // l | r
- else AppliedTypeTree(Ident(op), l :: r :: Nil) // op[l, r]
+ if (!op.isBackquoted && op.name == tpnme.raw.AMP) AndTypeTree(l, r) // l & r
+ else if (!op.isBackquoted && op.name == tpnme.raw.BAR) OrTypeTree(l, r) // l | r
+ else AppliedTypeTree(op, l :: r :: Nil) // op[l, r]
else if (ctx.mode is Mode.Pattern)
- Apply(Ident(op), l :: r :: Nil) // op(l, r)
+ Apply(op, l :: r :: Nil) // op(l, r)
else // l.op(r), or val x = r; l.op(x), plus handle named args specially
makeBinop(l, op, r)
case PostfixOp(t, op) =>
- if ((ctx.mode is Mode.Type) && op == nme.raw.STAR) {
+ if ((ctx.mode is Mode.Type) && !op.isBackquoted && op.name == nme.raw.STAR) {
val seqType = if (ctx.compilationUnit.isJava) defn.ArrayType else defn.SeqType
Annotated(
AppliedTypeTree(ref(seqType), t),
New(ref(defn.RepeatedAnnotType), Nil :: Nil))
} else {
assert(ctx.mode.isExpr || ctx.reporter.hasErrors, ctx.mode)
- Select(t, op)
+ Select(t, op.name)
}
case PrefixOp(op, t) =>
- Select(t, nme.UNARY_PREFIX ++ op)
+ Select(t, nme.UNARY_PREFIX ++ op.name)
case Parens(t) =>
t
case Tuple(ts) =>
diff --git a/compiler/src/dotty/tools/dotc/ast/Positioned.scala b/compiler/src/dotty/tools/dotc/ast/Positioned.scala
index bb6817603..51949c6fe 100644
--- a/compiler/src/dotty/tools/dotc/ast/Positioned.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Positioned.scala
@@ -123,6 +123,8 @@ abstract class Positioned extends DotClass with Product {
private def unionPos(pos: Position, xs: List[_]): Position = xs match {
case (p: Positioned) :: xs1 => unionPos(pos union p.pos, xs1)
+ case (xs0: List[_]) :: xs1 => unionPos(unionPos(pos, xs0), xs1)
+ case _ :: xs1 => unionPos(pos, xs1)
case _ => pos
}
diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
index da83d0644..bcda4b92f 100644
--- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -629,6 +629,28 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
case nil =>
Nil
}
+
+ /** Is this a selection of a member of a structural type that is not a member
+ * of an underlying class or trait?
+ */
+ def isStructuralTermSelect(tree: Tree)(implicit ctx: Context) = tree match {
+ case tree: Select =>
+ def hasRefinement(qualtpe: Type): Boolean = qualtpe.dealias match {
+ case RefinedType(parent, rname, rinfo) =>
+ rname == tree.name || hasRefinement(parent)
+ case tp: TypeProxy =>
+ hasRefinement(tp.underlying)
+ case tp: OrType =>
+ hasRefinement(tp.tp1) || hasRefinement(tp.tp2)
+ case tp: AndType =>
+ hasRefinement(tp.tp1) && hasRefinement(tp.tp2)
+ case _ =>
+ false
+ }
+ !tree.symbol.exists && tree.isTerm && hasRefinement(tree.qualifier.tpe)
+ case _ =>
+ false
+ }
}
object TreeInfo {
diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala
index 798f0f567..bf11a442e 100644
--- a/compiler/src/dotty/tools/dotc/ast/Trees.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala
@@ -3,7 +3,7 @@ package dotc
package ast
import core._
-import Types._, Names._, Flags._, util.Positions._, Contexts._, Constants._
+import Types._, Names._, NameOps._, Flags._, util.Positions._, Contexts._, Constants._
import SymDenotations._, Symbols._, Denotations._, StdNames._, Comments._
import annotation.tailrec
import language.higherKinds
@@ -316,7 +316,7 @@ object Trees {
def namePos =
if (pos.exists)
if (rawMods.is(Synthetic)) Position(pos.point, pos.point)
- else Position(pos.point, pos.point + name.length, pos.point)
+ else Position(pos.point, pos.point + name.stripModuleClassSuffix.length, pos.point)
else pos
}
@@ -334,10 +334,15 @@ object Trees {
extends RefTree[T] {
type ThisTree[-T >: Untyped] = Ident[T]
def qualifier: Tree[T] = genericEmptyTree
+
+ /** Is this a `BackquotedIdent` ? */
+ def isBackquoted: Boolean = false
}
class BackquotedIdent[-T >: Untyped] private[ast] (name: Name)
extends Ident[T](name) {
+ override def isBackquoted: Boolean = true
+
override def toString = s"BackquotedIdent($name)"
}
@@ -1069,95 +1074,100 @@ object Trees {
Template(tree: Tree)(constr, parents, self, body)
}
+ /** Hook to indicate that a transform of some subtree should be skipped */
+ protected def skipTransform(tree: Tree)(implicit ctx: Context): Boolean = false
+
abstract class TreeMap(val cpy: TreeCopier = inst.cpy) {
- def transform(tree: Tree)(implicit ctx: Context): Tree = tree match {
- case Ident(name) =>
- tree
- case Select(qualifier, name) =>
- cpy.Select(tree)(transform(qualifier), name)
- case This(qual) =>
- tree
- case Super(qual, mix) =>
- cpy.Super(tree)(transform(qual), mix)
- case Apply(fun, args) =>
- cpy.Apply(tree)(transform(fun), transform(args))
- case TypeApply(fun, args) =>
- cpy.TypeApply(tree)(transform(fun), transform(args))
- case Literal(const) =>
- tree
- case New(tpt) =>
- cpy.New(tree)(transform(tpt))
- case Typed(expr, tpt) =>
- cpy.Typed(tree)(transform(expr), transform(tpt))
- case NamedArg(name, arg) =>
- cpy.NamedArg(tree)(name, transform(arg))
- case Assign(lhs, rhs) =>
- cpy.Assign(tree)(transform(lhs), transform(rhs))
- case Block(stats, expr) =>
- cpy.Block(tree)(transformStats(stats), transform(expr))
- case If(cond, thenp, elsep) =>
- cpy.If(tree)(transform(cond), transform(thenp), transform(elsep))
- case Closure(env, meth, tpt) =>
- cpy.Closure(tree)(transform(env), transform(meth), transform(tpt))
- case Match(selector, cases) =>
- cpy.Match(tree)(transform(selector), transformSub(cases))
- case CaseDef(pat, guard, body) =>
- cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
- case Return(expr, from) =>
- cpy.Return(tree)(transform(expr), transformSub(from))
- case Try(block, cases, finalizer) =>
- cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
- case SeqLiteral(elems, elemtpt) =>
- cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
- case Inlined(call, bindings, expansion) =>
- cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion))
- case TypeTree() =>
- tree
- case SingletonTypeTree(ref) =>
- cpy.SingletonTypeTree(tree)(transform(ref))
- case AndTypeTree(left, right) =>
- cpy.AndTypeTree(tree)(transform(left), transform(right))
- case OrTypeTree(left, right) =>
- cpy.OrTypeTree(tree)(transform(left), transform(right))
- case RefinedTypeTree(tpt, refinements) =>
- cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
- case AppliedTypeTree(tpt, args) =>
- cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
- case PolyTypeTree(tparams, body) =>
- cpy.PolyTypeTree(tree)(transformSub(tparams), transform(body))
- case ByNameTypeTree(result) =>
- cpy.ByNameTypeTree(tree)(transform(result))
- case TypeBoundsTree(lo, hi) =>
- cpy.TypeBoundsTree(tree)(transform(lo), transform(hi))
- case Bind(name, body) =>
- cpy.Bind(tree)(name, transform(body))
- case Alternative(trees) =>
- cpy.Alternative(tree)(transform(trees))
- case UnApply(fun, implicits, patterns) =>
- cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns))
- case EmptyValDef =>
- tree
- case tree @ ValDef(name, tpt, _) =>
- val tpt1 = transform(tpt)
- val rhs1 = transform(tree.rhs)
- cpy.ValDef(tree)(name, tpt1, rhs1)
- case tree @ DefDef(name, tparams, vparamss, tpt, _) =>
- cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs))
- case tree @ TypeDef(name, rhs) =>
- cpy.TypeDef(tree)(name, transform(rhs))
- case tree @ Template(constr, parents, self, _) =>
- cpy.Template(tree)(transformSub(constr), transform(parents), transformSub(self), transformStats(tree.body))
- case Import(expr, selectors) =>
- cpy.Import(tree)(transform(expr), selectors)
- case PackageDef(pid, stats) =>
- cpy.PackageDef(tree)(transformSub(pid), transformStats(stats))
- case Annotated(arg, annot) =>
- cpy.Annotated(tree)(transform(arg), transform(annot))
- case Thicket(trees) =>
- val trees1 = transform(trees)
- if (trees1 eq trees) tree else Thicket(trees1)
- }
+ def transform(tree: Tree)(implicit ctx: Context): Tree =
+ if (skipTransform(tree)) tree
+ else tree match {
+ case Ident(name) =>
+ tree
+ case Select(qualifier, name) =>
+ cpy.Select(tree)(transform(qualifier), name)
+ case This(qual) =>
+ tree
+ case Super(qual, mix) =>
+ cpy.Super(tree)(transform(qual), mix)
+ case Apply(fun, args) =>
+ cpy.Apply(tree)(transform(fun), transform(args))
+ case TypeApply(fun, args) =>
+ cpy.TypeApply(tree)(transform(fun), transform(args))
+ case Literal(const) =>
+ tree
+ case New(tpt) =>
+ cpy.New(tree)(transform(tpt))
+ case Typed(expr, tpt) =>
+ cpy.Typed(tree)(transform(expr), transform(tpt))
+ case NamedArg(name, arg) =>
+ cpy.NamedArg(tree)(name, transform(arg))
+ case Assign(lhs, rhs) =>
+ cpy.Assign(tree)(transform(lhs), transform(rhs))
+ case Block(stats, expr) =>
+ cpy.Block(tree)(transformStats(stats), transform(expr))
+ case If(cond, thenp, elsep) =>
+ cpy.If(tree)(transform(cond), transform(thenp), transform(elsep))
+ case Closure(env, meth, tpt) =>
+ cpy.Closure(tree)(transform(env), transform(meth), transform(tpt))
+ case Match(selector, cases) =>
+ cpy.Match(tree)(transform(selector), transformSub(cases))
+ case CaseDef(pat, guard, body) =>
+ cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
+ case Return(expr, from) =>
+ cpy.Return(tree)(transform(expr), transformSub(from))
+ case Try(block, cases, finalizer) =>
+ cpy.Try(tree)(transform(block), transformSub(cases), transform(finalizer))
+ case SeqLiteral(elems, elemtpt) =>
+ cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
+ case Inlined(call, bindings, expansion) =>
+ cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion))
+ case TypeTree() =>
+ tree
+ case SingletonTypeTree(ref) =>
+ cpy.SingletonTypeTree(tree)(transform(ref))
+ case AndTypeTree(left, right) =>
+ cpy.AndTypeTree(tree)(transform(left), transform(right))
+ case OrTypeTree(left, right) =>
+ cpy.OrTypeTree(tree)(transform(left), transform(right))
+ case RefinedTypeTree(tpt, refinements) =>
+ cpy.RefinedTypeTree(tree)(transform(tpt), transformSub(refinements))
+ case AppliedTypeTree(tpt, args) =>
+ cpy.AppliedTypeTree(tree)(transform(tpt), transform(args))
+ case PolyTypeTree(tparams, body) =>
+ cpy.PolyTypeTree(tree)(transformSub(tparams), transform(body))
+ case ByNameTypeTree(result) =>
+ cpy.ByNameTypeTree(tree)(transform(result))
+ case TypeBoundsTree(lo, hi) =>
+ cpy.TypeBoundsTree(tree)(transform(lo), transform(hi))
+ case Bind(name, body) =>
+ cpy.Bind(tree)(name, transform(body))
+ case Alternative(trees) =>
+ cpy.Alternative(tree)(transform(trees))
+ case UnApply(fun, implicits, patterns) =>
+ cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns))
+ case EmptyValDef =>
+ tree
+ case tree @ ValDef(name, tpt, _) =>
+ val tpt1 = transform(tpt)
+ val rhs1 = transform(tree.rhs)
+ cpy.ValDef(tree)(name, tpt1, rhs1)
+ case tree @ DefDef(name, tparams, vparamss, tpt, _) =>
+ cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs))
+ case tree @ TypeDef(name, rhs) =>
+ cpy.TypeDef(tree)(name, transform(rhs))
+ case tree @ Template(constr, parents, self, _) =>
+ cpy.Template(tree)(transformSub(constr), transform(parents), transformSub(self), transformStats(tree.body))
+ case Import(expr, selectors) =>
+ cpy.Import(tree)(transform(expr), selectors)
+ case PackageDef(pid, stats) =>
+ cpy.PackageDef(tree)(transformSub(pid), transformStats(stats))
+ case Annotated(arg, annot) =>
+ cpy.Annotated(tree)(transform(arg), transform(annot))
+ case Thicket(trees) =>
+ val trees1 = transform(trees)
+ if (trees1 eq trees) tree else Thicket(trees1)
+ }
def transformStats(trees: List[Tree])(implicit ctx: Context): List[Tree] =
transform(trees)
diff --git a/compiler/src/dotty/tools/dotc/ast/tpd.scala b/compiler/src/dotty/tools/dotc/ast/tpd.scala
index 433808e8e..565ec5ce2 100644
--- a/compiler/src/dotty/tools/dotc/ast/tpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/tpd.scala
@@ -573,6 +573,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
Try(tree: Tree)(expr, cases, finalizer)
}
+ override def skipTransform(tree: Tree)(implicit ctx: Context) = tree.tpe.isError
+
implicit class TreeOps[ThisTree <: tpd.Tree](val tree: ThisTree) extends AnyVal {
def isValue(implicit ctx: Context): Boolean =
diff --git a/compiler/src/dotty/tools/dotc/ast/untpd.scala b/compiler/src/dotty/tools/dotc/ast/untpd.scala
index f3ffce8f8..99bc3240f 100644
--- a/compiler/src/dotty/tools/dotc/ast/untpd.scala
+++ b/compiler/src/dotty/tools/dotc/ast/untpd.scala
@@ -15,9 +15,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
// ----- Tree cases that exist in untyped form only ------------------
trait OpTree extends Tree {
- def op: Name
- override def isTerm = op.isTermName
- override def isType = op.isTypeName
+ def op: Ident
+ override def isTerm = op.name.isTermName
+ override def isType = op.name.isTypeName
}
/** A typed subtree of an untyped tree needs to be wrapped in a TypedSlice
@@ -66,9 +66,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
*/
class WildcardFunction(placeholderParams: List[ValDef], body: Tree) extends Function(placeholderParams, body)
- case class InfixOp(left: Tree, op: Name, right: Tree) extends OpTree
- case class PostfixOp(od: Tree, op: Name) extends OpTree
- case class PrefixOp(op: Name, od: Tree) extends OpTree
+ case class InfixOp(left: Tree, op: Ident, right: Tree) extends OpTree
+ case class PostfixOp(od: Tree, op: Ident) extends OpTree
+ case class PrefixOp(op: Ident, od: Tree) extends OpTree
case class Parens(t: Tree) extends ProxyTree {
def forwardTo = t
}
@@ -357,7 +357,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
* parameter, the reference will be a repeated argument.
*/
def refOfDef(tree: MemberDef)(implicit ctx: Context) = tree match {
- case ValDef(_, PostfixOp(_, nme.raw.STAR), _) => repeated(Ident(tree.name))
+ case ValDef(_, PostfixOp(_, Ident(nme.raw.STAR)), _) => repeated(Ident(tree.name))
case _ => Ident(tree.name)
}
@@ -409,15 +409,15 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case tree: Function if (args eq tree.args) && (body eq tree.body) => tree
case _ => untpd.Function(args, body).withPos(tree.pos)
}
- def InfixOp(tree: Tree)(left: Tree, op: Name, right: Tree) = tree match {
+ def InfixOp(tree: Tree)(left: Tree, op: Ident, right: Tree) = tree match {
case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree
case _ => untpd.InfixOp(left, op, right).withPos(tree.pos)
}
- def PostfixOp(tree: Tree)(od: Tree, op: Name) = tree match {
+ def PostfixOp(tree: Tree)(od: Tree, op: Ident) = tree match {
case tree: PostfixOp if (od eq tree.od) && (op eq tree.op) => tree
case _ => untpd.PostfixOp(od, op).withPos(tree.pos)
}
- def PrefixOp(tree: Tree)(op: Name, od: Tree) = tree match {
+ def PrefixOp(tree: Tree)(op: Ident, od: Tree) = tree match {
case tree: PrefixOp if (op eq tree.op) && (od eq tree.od) => tree
case _ => untpd.PrefixOp(op, od).withPos(tree.pos)
}
@@ -476,7 +476,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case SymbolLit(str) =>
cpy.SymbolLit(tree)(str)
case InterpolatedString(id, segments) =>
- cpy.InterpolatedString(tree)(id, transform(segments))
+ cpy.InterpolatedString(tree)(id, segments.map(transform(_)))
case Function(args, body) =>
cpy.Function(tree)(transform(args), transform(body))
case InfixOp(left, op, right) =>
diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
index 21a6c1165..e4c90789c 100644
--- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
+++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
@@ -101,6 +101,7 @@ class ScalaSettings extends Settings.SettingGroup {
val XoldPatmat = BooleanSetting("-Xoldpatmat", "Use the pre-2.10 pattern matcher. Otherwise, the 'virtualizing' pattern matcher is used in 2.10.")
val XnoPatmatAnalysis = BooleanSetting("-Xno-patmat-analysis", "Don't perform exhaustivity/unreachability analysis. Also, ignore @switch annotation.")
val XfullLubs = BooleanSetting("-Xfull-lubs", "Retains pre 2.10 behavior of less aggressive truncation of least upper bounds.")
+ val wikiSyntax = BooleanSetting("-Xwiki-syntax", "Retains the Scala2 behavior of using Wiki Syntax in Scaladoc")
/** -Y "Private" settings
*/
@@ -212,11 +213,18 @@ class ScalaSettings extends Settings.SettingGroup {
"A directory containing static resources needed for the API documentation"
)
- val DocTitle = StringSetting (
- "-Ydoc-title",
- "title",
- "The overall name of the Scaladoc site",
- ""
+ val siteRoot = StringSetting(
+ "-siteroot",
+ "site root",
+ "A directory containing static files from which to generate documentation",
+ sys.props("user.dir")
+ )
+
+ val projectName = StringSetting (
+ "-project",
+ "project title",
+ "The name of the project",
+ sys.props("user.dir").split(sys.props("file.separator")).last
)
val DocVersion = StringSetting (
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index 0aeb28d36..7fe6505ff 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -26,6 +26,9 @@ object Definitions {
* else without affecting the set of programs that can be compiled.
*/
val MaxImplementedFunctionArity = 22
+
+ /** The maximal arity of a function that can be accessed as member of a structural type */
+ val MaxStructuralMethodArity = 7
}
/** A class defining symbols and types of standard definitions
@@ -130,7 +133,7 @@ class Definitions {
ClassInfo(ScalaPackageClass.thisType, cls, ObjectType :: parentTraits, decls)
}
}
- newClassSymbol(ScalaPackageClass, name, Trait, completer)
+ newClassSymbol(ScalaPackageClass, name, Trait | NoInits, completer)
}
private def newMethod(cls: ClassSymbol, name: TermName, info: Type, flags: FlagSet = EmptyFlags): TermSymbol =
@@ -515,6 +518,7 @@ class Definitions {
lazy val LanguageModuleRef = ctx.requiredModule("scala.language")
def LanguageModuleClass(implicit ctx: Context) = LanguageModuleRef.symbol.moduleClass.asClass
lazy val NonLocalReturnControlType: TypeRef = ctx.requiredClassRef("scala.runtime.NonLocalReturnControl")
+ lazy val SelectableType: TypeRef = ctx.requiredClassRef("scala.Selectable")
lazy val ClassTagType = ctx.requiredClassRef("scala.reflect.ClassTag")
def ClassTagClass(implicit ctx: Context) = ClassTagType.symbol.asClass
@@ -766,6 +770,18 @@ class Definitions {
lazy val PhantomClasses = Set[Symbol](AnyClass, AnyValClass, NullClass, NothingClass)
+ /** Classes that are known not to have an initializer irrespective of
+ * whether NoInits is set. Note: FunctionXXLClass is in this set
+ * because if it is compiled by Scala2, it does not get a NoInit flag.
+ * But since it is introduced only at erasure, there's no chance
+ * for augmentScala2Traits to do anything on a class that inherits it. So
+ * it also misses an implementation class, which means that the usual scheme
+ * of calling a superclass init in the implementation class of a Scala2
+ * trait gets screwed up. Therefore, it is mandatory that FunctionXXL
+ * is treated as a NoInit trait.
+ */
+ lazy val NoInitClasses = PhantomClasses + FunctionXXLClass
+
def isPolymorphicAfterErasure(sym: Symbol) =
(sym eq Any_isInstanceOf) || (sym eq Any_asInstanceOf)
diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala
index 6a53e1b30..44608296a 100644
--- a/compiler/src/dotty/tools/dotc/core/Phases.scala
+++ b/compiler/src/dotty/tools/dotc/core/Phases.scala
@@ -40,9 +40,6 @@ trait Phases {
def atPhaseNotLaterThan[T](limit: Phase)(op: Context => T): T =
if (!limit.exists || phase <= limit) op(this) else atPhase(limit)(op)
- def atPhaseNotLaterThanTyper[T](op: Context => T): T =
- atPhaseNotLaterThan(base.typerPhase)(op)
-
def isAfterTyper: Boolean = base.isAfterTyper(phase)
}
@@ -266,6 +263,13 @@ object Phases {
trait Phase extends DotClass {
+ /** A name given to the `Phase` that can be used to debug the compiler. For
+ * instance, it is possible to print trees after a given phase using:
+ *
+ * ```bash
+ * $ ./bin/dotc -Xprint:<phaseNameHere> sourceFile.scala
+ * ```
+ */
def phaseName: String
/** List of names of phases that should precede this phase */
diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala
index 716959648..4a9c50dad 100644
--- a/compiler/src/dotty/tools/dotc/core/StdNames.scala
+++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala
@@ -481,6 +481,7 @@ object StdNames {
val sameElements: N = "sameElements"
val scala_ : N = "scala"
val selectDynamic: N = "selectDynamic"
+ val selectDynamicMethod: N = "selectDynamicMethod"
val selectOverloadedMethod: N = "selectOverloadedMethod"
val selectTerm: N = "selectTerm"
val selectType: N = "selectType"
diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala
index 636204f64..ae9122853 100644
--- a/compiler/src/dotty/tools/dotc/core/Types.scala
+++ b/compiler/src/dotty/tools/dotc/core/Types.scala
@@ -41,9 +41,11 @@ object Types {
implicit def eqType: Eq[Type, Type] = Eq
- /** The class of types.
+ /** Main class representing types.
+ *
* The principal subclasses and sub-objects are as follows:
*
+ * ```none
* Type -+- ProxyType --+- NamedType ----+--- TypeRef
* | | \
* | +- SingletonType-+-+- TermRef
@@ -74,6 +76,7 @@ object Types {
* +- NoPrefix
* +- ErrorType
* +- WildcardType
+ * ```
*
* Note: please keep in sync with copy in `docs/docs/internals/type-system.md`.
*/
diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index 97a82e80d..5b751ef3c 100644
--- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -818,7 +818,7 @@ class ClassfileParser(
case Some(entry) =>
val outerName = entry.outerName.stripModuleClassSuffix
val owner = classSymbol(outerName)
- val result = ctx.atPhaseNotLaterThanTyper { implicit ctx =>
+ val result = ctx.atPhaseNotLaterThan(ctx.typerPhase) { implicit ctx =>
getMember(owner, innerName.toTypeName)
}
assert(result ne NoSymbol,
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
index 0dc8d8fea..fb37c9e7d 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyPrinter.scala
@@ -31,8 +31,10 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
def nameRefToString(ref: NameRef): String = nameToString(tastyName(ref))
def printNames() =
- for ((name, idx) <- tastyName.contents.zipWithIndex)
- println(f"$idx%4d: " + nameToString(name))
+ for ((name, idx) <- tastyName.contents.zipWithIndex) {
+ val index = "%4d: ".format(idx)
+ println(index + nameToString(name))
+ }
def printContents(): Unit = {
println("Names:")
@@ -47,7 +49,10 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) {
def unpickle(reader: TastyReader, tastyName: TastyName.Table): Unit = {
import reader._
var indent = 0
- def newLine() = print(f"\n ${index(currentAddr) - index(startAddr)}%5d:" + " " * indent)
+ def newLine() = {
+ val length = "%5d:".format(index(currentAddr) - index(startAddr))
+ print(s"\n $length" + " " * indent)
+ }
def printNat() = print(" " + readNat())
def printName() = {
val idx = readNat()
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index 51f08a295..ffd594454 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -733,11 +733,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
// no longer necessary.
goto(end)
setPos(start, tree)
-
- // This is also done in PostTyper but needs to be redone here
- if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass) {
- sym.info = Checking.checkNoPrivateLeaks(sym, tree.pos)
- }
+ sym.info = ta.avoidPrivateLeaks(sym, tree.pos)
tree
}
diff --git a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
index 92ab10db9..d35594823 100644
--- a/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala
@@ -448,7 +448,7 @@ object JavaParsers {
if (in.token == DOTDOTDOT) {
in.nextToken()
t = atPos(t.pos.start) {
- PostfixOp(t, nme.raw.STAR)
+ PostfixOp(t, Ident(nme.raw.STAR))
}
}
atPos(start, in.offset) {
diff --git a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
index a733eb65d..3162f61b4 100644
--- a/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/compiler/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -30,7 +30,7 @@ object Parsers {
import reporting.diagnostic.Message
import reporting.diagnostic.messages._
- case class OpInfo(operand: Tree, operator: Name, offset: Offset)
+ case class OpInfo(operand: Tree, operator: Ident, offset: Offset)
class ParensCounters {
private var parCounts = new Array[Int](lastParen - firstParen)
@@ -414,18 +414,17 @@ object Parsers {
"left- and right-associative operators with same precedence may not be mixed", offset)
def reduceStack(base: List[OpInfo], top: Tree, prec: Int, leftAssoc: Boolean): Tree = {
- if (opStack != base && precedence(opStack.head.operator) == prec)
- checkAssoc(opStack.head.offset, opStack.head.operator, leftAssoc)
+ if (opStack != base && precedence(opStack.head.operator.name) == prec)
+ checkAssoc(opStack.head.offset, opStack.head.operator.name, leftAssoc)
def recur(top: Tree): Tree = {
if (opStack == base) top
else {
val opInfo = opStack.head
- val opPrec = precedence(opInfo.operator)
+ val opPrec = precedence(opInfo.operator.name)
if (prec < opPrec || leftAssoc && prec == opPrec) {
opStack = opStack.tail
recur {
- val opPos = Position(opInfo.offset, opInfo.offset + opInfo.operator.length, opInfo.offset)
- atPos(opPos union opInfo.operand.pos union top.pos) {
+ atPos(opInfo.operator.pos union opInfo.operand.pos union top.pos) {
InfixOp(opInfo.operand, opInfo.operator, top)
}
}
@@ -449,10 +448,9 @@ object Parsers {
val base = opStack
var top = first
while (isIdent && in.name != notAnOperator) {
- val op = if (isType) in.name.toTypeName else in.name
- top = reduceStack(base, top, precedence(op), isLeftAssoc(op))
+ val op = if (isType) typeIdent() else termIdent()
+ top = reduceStack(base, top, precedence(op.name), isLeftAssoc(op.name))
opStack = OpInfo(top, op, in.offset) :: opStack
- ident()
newLineOptWhenFollowing(canStartOperand)
if (maybePostfix && !canStartOperand(in.token)) {
val topInfo = opStack.head
@@ -870,7 +868,7 @@ object Parsers {
val t = toplevelTyp()
if (isIdent(nme.raw.STAR)) {
in.nextToken()
- atPos(startOffset(t)) { PostfixOp(t, nme.raw.STAR) }
+ atPos(startOffset(t)) { PostfixOp(t, Ident(nme.raw.STAR)) }
} else t
}
@@ -1189,11 +1187,11 @@ object Parsers {
val prefixExpr = () =>
if (isIdent && nme.raw.isUnary(in.name)) {
val start = in.offset
- val name = ident()
- if (name == nme.raw.MINUS && isNumericLit)
+ val op = termIdent()
+ if (op.name == nme.raw.MINUS && isNumericLit)
simpleExprRest(literal(start), canApply = true)
else
- atPos(start) { PrefixOp(name, simpleExpr()) }
+ atPos(start) { PrefixOp(op, simpleExpr()) }
}
else simpleExpr()
@@ -1260,7 +1258,7 @@ object Parsers {
val app = atPos(startOffset(t), in.offset) { Apply(t, argumentExprs()) }
simpleExprRest(app, canApply = true)
case USCORE =>
- atPos(startOffset(t), in.skipToken()) { PostfixOp(t, nme.WILDCARD) }
+ atPos(startOffset(t), in.skipToken()) { PostfixOp(t, Ident(nme.WILDCARD)) }
case _ =>
t
}
diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 3085ad8fd..5b75df6b2 100644
--- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -61,7 +61,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
override def nameString(name: Name): String = name.decode.toString
override protected def simpleNameString(sym: Symbol): String = {
- val name = sym.originalName
+ val name = if (ctx.property(XprintMode).isEmpty) sym.originalName else sym.name
nameString(if (sym is ExpandedTypeParam) name.asTypeName.unexpandedName else name)
}
@@ -516,7 +516,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
argsText ~ " => " ~ toText(body)
}
case InfixOp(l, op, r) =>
- val opPrec = parsing.precedence(op)
+ val opPrec = parsing.precedence(op.name)
changePrec(opPrec) { toText(l) ~ " " ~ toText(op) ~ " " ~ toText(r) }
case PostfixOp(l, op) =>
changePrec(InfixPrec) { toText(l) ~ " " ~ toText(op) }
diff --git a/compiler/src/dotty/tools/dotc/printing/package.scala b/compiler/src/dotty/tools/dotc/printing/package.scala
index 814eb2ad0..e2c0dda1b 100644
--- a/compiler/src/dotty/tools/dotc/printing/package.scala
+++ b/compiler/src/dotty/tools/dotc/printing/package.scala
@@ -2,6 +2,7 @@ package dotty.tools.dotc
import core.StdNames.nme
import parsing.{precedence, minPrec, maxPrec, minInfixPrec}
+import util.Property.Key
package object printing {
@@ -14,4 +15,9 @@ package object printing {
val GlobalPrec = parsing.minPrec
val TopLevelPrec = parsing.minPrec - 1
+ /** A property to indicate whether the compiler is currently doing -Xprint
+ *
+ * -Xprint will print `sym.name` instead of `sym.originalName`
+ */
+ val XprintMode = new Key[Unit]
}
diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
index 71ecb5c65..00abddd91 100644
--- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
@@ -542,7 +542,9 @@ object Erasure extends TypeTestsCasts{
* to deal with boxing and unboxing of value classes ourselves.
*/
override def typedClosure(tree: untpd.Closure, pt: Type)(implicit ctx: Context) = {
- val implClosure @ Closure(_, meth, _) = super.typedClosure(tree, pt)
+ val xxl = defn.isUnimplementedFunctionClass(tree.typeOpt.typeSymbol)
+ var implClosure @ Closure(_, meth, _) = super.typedClosure(tree, pt)
+ if (xxl) implClosure = cpy.Closure(implClosure)(tpt = TypeTree(defn.FunctionXXLType))
implClosure.tpe match {
case SAMType(sam) =>
val implType = meth.tpe.widen
diff --git a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala
index 8bc4a2aa9..ebd2ae436 100644
--- a/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala
+++ b/compiler/src/dotty/tools/dotc/transform/IsInstanceOfEvaluator.scala
@@ -7,36 +7,37 @@ import core._
import Contexts.Context, Types._, Constants._, Decorators._, Symbols._
import TypeUtils._, TypeErasure._, Flags._
-
/** Implements partial evaluation of `sc.isInstanceOf[Sel]` according to:
*
- * +-------------+----------------------------+----------------------------+------------------+
* | Sel\sc | trait | class | final class |
- * +-------------+----------------------------+----------------------------+------------------+
+ * | ----------: | :------------------------: | :------------------------: | :--------------: |
* | trait | ? | ? | statically known |
* | class | ? | false if classes unrelated | statically known |
* | final class | false if classes unrelated | false if classes unrelated | statically known |
- * +-------------+----------------------------+----------------------------+------------------+
*
* This is a generalized solution to raising an error on unreachable match
* cases and warnings on other statically known results of `isInstanceOf`.
*
* Steps taken:
*
- * 1. evalTypeApply will establish the matrix and choose the appropriate
- * handling for the case:
- * 2. a) Sel/sc is a value class or scrutinee is `Any`
- * b) handleStaticallyKnown
- * c) falseIfUnrelated with `scrutinee <:< selector`
- * d) handleFalseUnrelated
- * e) leave as is (aka `happens`)
- * 3. Rewrite according to step taken in `2`
+ * 1. `evalTypeApply` will establish the matrix and choose the appropriate
+ * handling for the case:
+ * - Sel/sc is a value class or scrutinee is `Any`
+ * - `handleStaticallyKnown`
+ * - `falseIfUnrelated` with `scrutinee <:< selector`
+ * - `handleFalseUnrelated`
+ * - leave as is (`happens`)
+ * 2. Rewrite according to steps taken in 1
*/
class IsInstanceOfEvaluator extends MiniPhaseTransform { thisTransformer =>
import dotty.tools.dotc.ast.tpd._
- def phaseName = "isInstanceOfEvaluator"
+ val phaseName = "isInstanceOfEvaluator"
+
+ /** Transforms a [TypeApply](dotty.tools.dotc.ast.Trees.TypeApply) in order to
+ * evaluate an `isInstanceOf` check according to the rules defined above.
+ */
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = {
val defn = ctx.definitions
diff --git a/compiler/src/dotty/tools/dotc/transform/Mixin.scala b/compiler/src/dotty/tools/dotc/transform/Mixin.scala
index 27cfc835a..fd4370d3e 100644
--- a/compiler/src/dotty/tools/dotc/transform/Mixin.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Mixin.scala
@@ -175,7 +175,7 @@ class Mixin extends MiniPhaseTransform with SymTransformer { thisTransform =>
case Some(call) =>
if (defn.PhantomClasses.contains(baseCls)) Nil else call :: Nil
case None =>
- if (baseCls.is(NoInitsTrait) || defn.PhantomClasses.contains(baseCls)) Nil
+ if (baseCls.is(NoInitsTrait) || defn.NoInitClasses.contains(baseCls)) Nil
else {
//println(i"synth super call ${baseCls.primaryConstructor}: ${baseCls.primaryConstructor.info}")
transformFollowingDeep(superRef(baseCls.primaryConstructor).appliedToNone) :: Nil
diff --git a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
index 181dfccd9..7c49e68dd 100644
--- a/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
+++ b/compiler/src/dotty/tools/dotc/transform/PatternMatcher.scala
@@ -1077,8 +1077,6 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {
trait MatchTranslator extends TreeMakers with ScalacPatternExpanders {
- def isBackquoted(x: Ident) = x.isInstanceOf[BackquotedIdent]
-
def isVarPattern(pat: Tree): Boolean = pat match {
case x: BackquotedIdent => false
case x: Ident => x.name.isVariableName
diff --git a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
index e7c0df1b9..8dff58dea 100644
--- a/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -107,12 +107,6 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
private def transformMemberDef(tree: MemberDef)(implicit ctx: Context): Unit = {
val sym = tree.symbol
sym.transformAnnotations(transformAnnot)
- // Has to be redone in TreeUnpickler
- if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass) {
- val info1 = Checking.checkNoPrivateLeaks(sym, tree.pos)
- if (info1 ne sym.info)
- sym.copySymDenotation(info = info1).installAfter(thisTransformer)
- }
}
private def transformSelect(tree: Select, targs: List[Tree])(implicit ctx: Context): Tree = {
diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala
index 321c275d7..ca62ed0a9 100644
--- a/compiler/src/dotty/tools/dotc/typer/Checking.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala
@@ -415,6 +415,8 @@ object Checking {
/** Verify classes extending AnyVal meet the requirements */
def checkDerivedValueClass(clazz: Symbol, stats: List[Tree])(implicit ctx: Context) = {
def checkValueClassMember(stat: Tree) = stat match {
+ case _: TypeDef if stat.symbol.isClass =>
+ ctx.error(s"value class may not define an inner class", stat.pos)
case _: ValDef if !stat.symbol.is(ParamAccessor) =>
ctx.error(s"value class may not define non-parameter field", stat.pos)
case d: DefDef if d.symbol.isConstructor =>
diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala
index 4039c8b81..000cfd026 100644
--- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala
@@ -7,10 +7,13 @@ import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.ast.untpd
import dotty.tools.dotc.core.Constants.Constant
import dotty.tools.dotc.core.Contexts.Context
-import dotty.tools.dotc.core.Names.Name
+import dotty.tools.dotc.core.Names.{Name, TermName}
import dotty.tools.dotc.core.StdNames._
import dotty.tools.dotc.core.Types._
import dotty.tools.dotc.core.Decorators._
+import core.Symbols._
+import core.Definitions
+import Inferencing._
import ErrorReporting._
object Dynamic {
@@ -18,7 +21,10 @@ object Dynamic {
name == nme.applyDynamic || name == nme.selectDynamic || name == nme.updateDynamic || name == nme.applyDynamicNamed
}
-/** Translates selection that does not typecheck according to the scala.Dynamic rules:
+/** Handles programmable member selections of `Dynamic` instances and values
+ * with structural types. Two functionalities:
+ *
+ * 1. Translates selection that does not typecheck according to the scala.Dynamic rules:
* foo.bar(baz) = quux ~~> foo.selectDynamic(bar).update(baz, quux)
* foo.bar = baz ~~> foo.updateDynamic("bar")(baz)
* foo.bar(x = bazX, y = bazY, baz, ...) ~~> foo.applyDynamicNamed("bar")(("x", bazX), ("y", bazY), ("", baz), ...)
@@ -26,6 +32,10 @@ object Dynamic {
* foo.bar ~~> foo.selectDynamic(bar)
*
* The first matching rule of is applied.
+ *
+ * 2. Translates member selections on structural types to calls of `selectDynamic`
+ * or `selectDynamicMethod` on a `Selectable` instance. @See handleStructural.
+ *
*/
trait Dynamic { self: Typer with Applications =>
import Dynamic._
@@ -100,4 +110,56 @@ trait Dynamic { self: Typer with Applications =>
else untpd.TypeApply(select, targs)
untpd.Apply(selectWithTypes, Literal(Constant(name.toString)))
}
+
+ /** Handle reflection-based dispatch for members of structural types.
+ * Given `x.a`, where `x` is of (widened) type `T` and `x.a` is of type `U`:
+ *
+ * If `U` is a value type, map `x.a` to the equivalent of:
+ *
+ * (x: Selectable).selectDynamic(x, "a").asInstanceOf[U]
+ *
+ * If `U` is a method type (T1,...,Tn)R, map `x.a` to the equivalent of:
+ *
+ * (x: Selectable).selectDynamicMethod("a", CT1, ..., CTn).asInstanceOf[(T1,...,Tn) => R]
+ *
+ * where CT1,...,CTn are the class tags representing the erasure of T1,...,Tn.
+ *
+ * It's an error if U is neither a value nor a method type, or a dependent method
+ * type, or of too large arity (limit is Definitions.MaxStructuralMethodArity).
+ */
+ def handleStructural(tree: Tree)(implicit ctx: Context): Tree = {
+ val Select(qual, name) = tree
+
+ def structuralCall(selectorName: TermName, formals: List[Tree]) = {
+ val selectable = adapt(qual, defn.SelectableType)
+ val scall = untpd.Apply(
+ untpd.TypedSplice(selectable.select(selectorName)),
+ (Literal(Constant(name.toString)) :: formals).map(untpd.TypedSplice(_)))
+ typed(scall)
+ }
+
+ def fail(reason: String) =
+ errorTree(tree, em"Structural access not allowed on method $name because it $reason")
+
+ tree.tpe.widen match {
+ case tpe: MethodType =>
+ if (tpe.isDependent)
+ fail(i"has a dependent method type")
+ else if (tpe.paramNames.length > Definitions.MaxStructuralMethodArity)
+ fail(i"""takes too many parameters.
+ |Structural types only support methods taking up to ${Definitions.MaxStructuralMethodArity} arguments""")
+ else {
+ def issueError(msgFn: String => String): Unit = ctx.error(msgFn(""), tree.pos)
+ val ctags = tpe.paramTypes.map(pt =>
+ inferImplicitArg(defn.ClassTagType.appliedTo(pt :: Nil), issueError, tree.pos.endPos))
+ structuralCall(nme.selectDynamicMethod, ctags).asInstance(tpe.toFunctionType())
+ }
+ case tpe: ValueType =>
+ structuralCall(nme.selectDynamic, Nil).asInstance(tpe)
+ case tpe: PolyType =>
+ fail("is polymorphic")
+ case tpe =>
+ fail(i"has an unsupported type: $tpe")
+ }
+ }
}
diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
index c390ae808..e7e7ece78 100644
--- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
+++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
@@ -144,7 +144,7 @@ object EtaExpansion {
ids = ids.init :+ repeated(ids.last)
var body: Tree = Apply(lifted, ids)
mt.resultType match {
- case rt: MethodType if !rt.isImplicit => body = PostfixOp(body, nme.WILDCARD)
+ case rt: MethodType if !rt.isImplicit => body = PostfixOp(body, Ident(nme.WILDCARD))
case _ =>
}
val fn = untpd.Function(params, body)
diff --git a/compiler/src/dotty/tools/dotc/typer/Implicits.scala b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
index f7d8556a7..6949221fb 100644
--- a/compiler/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Implicits.scala
@@ -69,9 +69,9 @@ object Implicits {
case mt: MethodType =>
mt.isImplicit ||
mt.paramTypes.length != 1 ||
- !(argType relaxed_<:< wildApprox(mt.paramTypes.head)(ctx.fresh.setExploreTyperState))
+ !(argType relaxed_<:< wildApprox(mt.paramTypes.head, null, Set.empty)(ctx.fresh.setExploreTyperState))
case rtp =>
- discardForView(wildApprox(rtp), argType)
+ discardForView(wildApprox(rtp, null, Set.empty), argType)
}
case tpw: TermRef =>
false // can't discard overloaded refs
@@ -664,7 +664,7 @@ trait Implicits { self: Typer =>
}
/** The expected type where parameters and uninstantiated typevars are replaced by wildcard types */
- val wildProto = implicitProto(pt, wildApprox(_))
+ val wildProto = implicitProto(pt, wildApprox(_, null, Set.empty))
/** Search failures; overridden in ExplainedImplicitSearch */
protected def nonMatchingImplicit(ref: TermRef, trail: List[MessageContainer]): SearchFailure = NoImplicitMatches
diff --git a/compiler/src/dotty/tools/dotc/typer/Inliner.scala b/compiler/src/dotty/tools/dotc/typer/Inliner.scala
index 09487570d..cfc0003c6 100644
--- a/compiler/src/dotty/tools/dotc/typer/Inliner.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Inliner.scala
@@ -327,7 +327,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
(tp.paramNames, tp.paramTypes, argss.head).zipped.foreach { (name, paramtp, arg) =>
def isByName = paramtp.dealias.isInstanceOf[ExprType]
paramBinding(name) = arg.tpe.stripAnnots.stripTypeVar match {
- case argtpe: SingletonType if isByName || isIdempotentExpr(arg) => argtpe
+ case argtpe: SingletonType if isIdempotentExpr(arg) => argtpe
case argtpe =>
val inlineFlag = if (paramtp.hasAnnotation(defn.InlineParamAnnot)) Inline else EmptyFlags
val (bindingFlags, bindingType) =
diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala
index 068ef3e4b..3860ba225 100644
--- a/compiler/src/dotty/tools/dotc/typer/Namer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala
@@ -491,22 +491,26 @@ class Namer { typer: Typer =>
if (cdef.isClassDef) {
classDef(name) = cdef
cdef.attachmentOrElse(ExpandedTree, cdef) match {
- case Thicket(cls :: mval :: (mcls @ TypeDef(_, _: Template)) :: crest) =>
+ case Thicket(cls :: mval :: (mcls @ TypeDef(mname, _: Template)) :: crest)
+ if name.moduleClassName == mname =>
moduleDef(name) = mcls
case _ =>
}
}
for (mdef @ ModuleDef(name, _) <- stats if !mdef.mods.is(Flags.Package)) {
val typName = name.toTypeName
- val Thicket(vdef :: (mcls @ TypeDef(_, impl: Template)) :: Nil) = mdef.attachment(ExpandedTree)
+ // Expansion of object is a flattened thicket with the first two elements being:
+ // module val :: module class :: rest
+ val Thicket(vdef :: (mcls @ TypeDef(_, impl: Template)) :: rest) = expanded(mdef)
moduleDef(typName) = mcls
classDef get name.toTypeName match {
case Some(cdef) =>
cdef.attachmentOrElse(ExpandedTree, cdef) match {
- case Thicket(cls :: mval :: TypeDef(_, compimpl: Template) :: crest) =>
+ case Thicket(cls :: mval :: TypeDef(mname, compimpl: Template) :: crest)
+ if name.moduleClassName == mname =>
val mcls1 = cpy.TypeDef(mcls)(
rhs = cpy.Template(impl)(body = compimpl.body ++ impl.body))
- mdef.putAttachment(ExpandedTree, Thicket(vdef :: mcls1 :: Nil))
+ mdef.putAttachment(ExpandedTree, Thicket(vdef :: mcls1 :: rest))
moduleDef(typName) = mcls1
cdef.putAttachment(ExpandedTree, Thicket(cls :: crest))
case _ =>
@@ -668,13 +672,15 @@ class Namer { typer: Typer =>
* to pick up the context at the point where the completer was created.
*/
def completeInCreationContext(denot: SymDenotation): Unit = {
+ val sym = denot.symbol
original match {
- case original: MemberDef => addAnnotations(denot.symbol, original)
+ case original: MemberDef => addAnnotations(sym, original)
case _ =>
}
addInlineInfo(denot)
- denot.info = typeSig(denot.symbol)
- Checking.checkWellFormed(denot.symbol)
+ denot.info = typeSig(sym)
+ Checking.checkWellFormed(sym)
+ denot.info = avoidPrivateLeaks(sym, sym.pos)
}
}
@@ -854,6 +860,7 @@ class Namer { typer: Typer =>
if (isDerivedValueClass(cls)) cls.setFlag(Final)
cls.setApplicableFlags(
(NoInitsInterface /: impl.body)((fs, stat) => fs & defKind(stat)))
+ cls.info = avoidPrivateLeaks(cls, cls.pos)
}
}
@@ -965,7 +972,7 @@ class Namer { typer: Typer =>
ctx.defContext(sym).denotNamed(original)
def paramProto(paramss: List[List[Type]], idx: Int): Type = paramss match {
case params :: paramss1 =>
- if (idx < params.length) wildApprox(params(idx))
+ if (idx < params.length) wildApprox(params(idx), null, Set.empty)
else paramProto(paramss1, idx - params.length)
case nil =>
WildcardType
diff --git a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
index eb46a131f..d666b563e 100644
--- a/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -437,65 +437,82 @@ object ProtoTypes {
/** Approximate occurrences of parameter types and uninstantiated typevars
* by wildcard types.
*/
- final def wildApprox(tp: Type, theMap: WildApproxMap = null)(implicit ctx: Context): Type = tp match {
+ final def wildApprox(tp: Type, theMap: WildApproxMap, seen: Set[PolyParam])(implicit ctx: Context): Type = tp match {
case tp: NamedType => // default case, inlined for speed
if (tp.symbol.isStatic) tp
- else tp.derivedSelect(wildApprox(tp.prefix, theMap))
+ else tp.derivedSelect(wildApprox(tp.prefix, theMap, seen))
case tp: RefinedType => // default case, inlined for speed
- tp.derivedRefinedType(wildApprox(tp.parent, theMap), tp.refinedName, wildApprox(tp.refinedInfo, theMap))
+ tp.derivedRefinedType(
+ wildApprox(tp.parent, theMap, seen),
+ tp.refinedName,
+ wildApprox(tp.refinedInfo, theMap, seen))
case tp: TypeAlias => // default case, inlined for speed
- tp.derivedTypeAlias(wildApprox(tp.alias, theMap))
+ tp.derivedTypeAlias(wildApprox(tp.alias, theMap, seen))
case tp @ PolyParam(poly, pnum) =>
- def unconstrainedApprox = WildcardType(wildApprox(poly.paramBounds(pnum)).bounds)
- if (ctx.mode.is(Mode.TypevarsMissContext))
- unconstrainedApprox
- else
- ctx.typerState.constraint.entry(tp) match {
- case bounds: TypeBounds => wildApprox(WildcardType(bounds))
- case NoType => unconstrainedApprox
- case inst => wildApprox(inst)
- }
+ def wildApproxBounds(bounds: TypeBounds) =
+ if (bounds.lo.isInstanceOf[NamedType] && bounds.hi.isInstanceOf[NamedType])
+ WildcardType(wildApprox(bounds, theMap, seen).bounds)
+ else if (seen.contains(tp)) WildcardType
+ else WildcardType(wildApprox(bounds, theMap, seen + tp).bounds)
+ def unconstrainedApprox = wildApproxBounds(poly.paramBounds(pnum))
+ def approxPoly =
+ if (ctx.mode.is(Mode.TypevarsMissContext)) unconstrainedApprox
+ else
+ ctx.typerState.constraint.entry(tp) match {
+ case bounds: TypeBounds => wildApproxBounds(bounds)
+ case NoType => unconstrainedApprox
+ case inst => wildApprox(inst, theMap, seen)
+ }
+ approxPoly
case MethodParam(mt, pnum) =>
- WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum))))
+ WildcardType(TypeBounds.upper(wildApprox(mt.paramTypes(pnum), theMap, seen)))
case tp: TypeVar =>
- wildApprox(tp.underlying)
+ wildApprox(tp.underlying, theMap, seen)
case tp @ HKApply(tycon, args) =>
- wildApprox(tycon) match {
+ wildApprox(tycon, theMap, seen) match {
case _: WildcardType => WildcardType // this ensures we get a * type
- case tycon1 => tp.derivedAppliedType(tycon1, args.mapConserve(wildApprox(_)))
+ case tycon1 => tp.derivedAppliedType(tycon1, args.mapConserve(wildApprox(_, theMap, seen)))
}
case tp: AndType =>
- val tp1a = wildApprox(tp.tp1)
- val tp2a = wildApprox(tp.tp2)
- def wildBounds(tp: Type) =
- if (tp.isInstanceOf[WildcardType]) tp.bounds else TypeBounds.upper(tp)
- if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
- WildcardType(wildBounds(tp1a) & wildBounds(tp2a))
- else
- tp.derivedAndType(tp1a, tp2a)
+ def approxAnd = {
+ val tp1a = wildApprox(tp.tp1, theMap, seen)
+ val tp2a = wildApprox(tp.tp2, theMap, seen)
+ def wildBounds(tp: Type) =
+ if (tp.isInstanceOf[WildcardType]) tp.bounds else TypeBounds.upper(tp)
+ if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
+ WildcardType(wildBounds(tp1a) & wildBounds(tp2a))
+ else
+ tp.derivedAndType(tp1a, tp2a)
+ }
+ approxAnd
case tp: OrType =>
- val tp1a = wildApprox(tp.tp1)
- val tp2a = wildApprox(tp.tp2)
- if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
- WildcardType(tp1a.bounds | tp2a.bounds)
- else
- tp.derivedOrType(tp1a, tp2a)
+ def approxOr = {
+ val tp1a = wildApprox(tp.tp1, theMap, seen)
+ val tp2a = wildApprox(tp.tp2, theMap, seen)
+ if (tp1a.isInstanceOf[WildcardType] || tp2a.isInstanceOf[WildcardType])
+ WildcardType(tp1a.bounds | tp2a.bounds)
+ else
+ tp.derivedOrType(tp1a, tp2a)
+ }
+ approxOr
case tp: LazyRef =>
WildcardType
case tp: SelectionProto =>
- tp.derivedSelectionProto(tp.name, wildApprox(tp.memberProto), NoViewsAllowed)
+ tp.derivedSelectionProto(tp.name, wildApprox(tp.memberProto, theMap, seen), NoViewsAllowed)
case tp: ViewProto =>
- tp.derivedViewProto(wildApprox(tp.argType), wildApprox(tp.resultType))
+ tp.derivedViewProto(
+ wildApprox(tp.argType, theMap, seen),
+ wildApprox(tp.resultType, theMap, seen))
case _: ThisType | _: BoundType | NoPrefix => // default case, inlined for speed
tp
case _ =>
- (if (theMap != null) theMap else new WildApproxMap).mapOver(tp)
+ (if (theMap != null) theMap else new WildApproxMap(seen)).mapOver(tp)
}
@sharable object AssignProto extends UncachedGroundType with MatchAlways
- private[ProtoTypes] class WildApproxMap(implicit ctx: Context) extends TypeMap {
- def apply(tp: Type) = wildApprox(tp, this)
+ private[ProtoTypes] class WildApproxMap(val seen: Set[PolyParam])(implicit ctx: Context) extends TypeMap {
+ def apply(tp: Type) = wildApprox(tp, this, seen)
}
/** Dummy tree to be used as an argument of a FunProto or ViewProto type */
diff --git a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
index 5c07b7bcf..53ce5555b 100644
--- a/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -132,6 +132,11 @@ trait TypeAssigner {
def avoidingType(expr: Tree, bindings: List[Tree])(implicit ctx: Context): Type =
avoid(expr.tpe, localSyms(bindings).filter(_.isTerm))
+ def avoidPrivateLeaks(sym: Symbol, pos: Position)(implicit ctx: Context): Type =
+ if (!sym.is(SyntheticOrPrivate) && sym.owner.isClass)
+ Checking.checkNoPrivateLeaks(sym, pos)
+ else sym.info
+
def seqToRepeated(tree: Tree)(implicit ctx: Context): Tree =
Typed(tree, TypeTree(tree.tpe.widen.translateParameterized(defn.SeqClass, defn.RepeatedParamClass)))
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index 22a4221ba..652c89094 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -1040,9 +1040,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
typr.println(s"adding refinement $refinement")
checkRefinementNonCyclic(refinement, refineCls, seen)
val rsym = refinement.symbol
- if (rsym.is(Method) && rsym.allOverriddenSymbols.isEmpty)
- ctx.error(i"refinement $rsym without matching type in parent $tpt1", refinement.pos)
- }
+ if (rsym.info.isInstanceOf[PolyType] && rsym.allOverriddenSymbols.isEmpty)
+ ctx.error(i"polymorphic refinement $rsym without matching type in parent $tpt1 is no longer allowed", refinement.pos) }
assignType(cpy.RefinedTypeTree(tree)(tpt1, refinements1), tpt1, refinements1, refineCls)
}
@@ -1441,7 +1440,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedAsFunction(tree: untpd.PostfixOp, pt: Type)(implicit ctx: Context): Tree = {
- val untpd.PostfixOp(qual, nme.WILDCARD) = tree
+ val untpd.PostfixOp(qual, Ident(nme.WILDCARD)) = tree
val pt1 = if (defn.isFunctionType(pt)) pt else AnyFunctionProto
var res = typed(qual, pt1)
if (pt1.eq(AnyFunctionProto) && !defn.isFunctionClass(res.tpe.classSymbol)) {
@@ -1542,7 +1541,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case tree: untpd.Annotated => typedAnnotated(tree, pt)
case tree: untpd.TypedSplice => typedTypedSplice(tree)
case tree: untpd.UnApply => typedUnApply(tree, pt)
- case tree @ untpd.PostfixOp(qual, nme.WILDCARD) => typedAsFunction(tree, pt)
+ case tree @ untpd.PostfixOp(qual, Ident(nme.WILDCARD)) => typedAsFunction(tree, pt)
case untpd.EmptyTree => tpd.EmptyTree
case _ => typedUnadapted(desugar(tree), pt)
}
@@ -2068,7 +2067,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
adaptInterpolated(tree.appliedToTypeTrees(typeArgs), pt, original))
}
case wtp =>
- pt match {
+ if (isStructuralTermSelect(tree)) adapt(handleStructural(tree), pt)
+ else pt match {
case pt: FunProto =>
adaptToArgs(wtp, pt)
case pt: PolyProto =>