aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/Compiler.scala3
-rw-r--r--src/dotty/tools/dotc/ElimLocals.scala2
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala2
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala35
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala4
-rw-r--r--src/dotty/tools/dotc/core/transform/Erasure.scala13
-rw-r--r--src/dotty/tools/dotc/transform/ElimByName.scala113
-rw-r--r--src/dotty/tools/dotc/transform/ElimRepeated.scala2
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala49
-rw-r--r--src/dotty/tools/dotc/transform/ExtensionMethods.scala2
-rw-r--r--src/dotty/tools/dotc/transform/Nullarify.scala147
-rw-r--r--src/dotty/tools/dotc/transform/SymUtils.scala25
-rw-r--r--src/dotty/tools/dotc/transform/TypeTestsCasts.scala2
-rw-r--r--src/dotty/tools/dotc/transform/TypeUtils.scala7
-rw-r--r--src/dotty/tools/dotc/typer/Checking.scala7
-rw-r--r--test/dotc/tests.scala2
-rw-r--r--tests/pos/Patterns.scala6
17 files changed, 207 insertions, 214 deletions
diff --git a/src/dotty/tools/dotc/Compiler.scala b/src/dotty/tools/dotc/Compiler.scala
index cae8c5782..7bf387549 100644
--- a/src/dotty/tools/dotc/Compiler.scala
+++ b/src/dotty/tools/dotc/Compiler.scala
@@ -28,7 +28,8 @@ class Compiler {
List(new PatternMatcher,
// new LazyValTranformContext().transformer, // disabled, awaiting fixes
new Splitter),
- List(new Nullarify,
+ List(new ElimByName),
+ List(
new TypeTestsCasts,
new InterceptedMethods,
new Literalize),
diff --git a/src/dotty/tools/dotc/ElimLocals.scala b/src/dotty/tools/dotc/ElimLocals.scala
index 98da95f61..b5843375a 100644
--- a/src/dotty/tools/dotc/ElimLocals.scala
+++ b/src/dotty/tools/dotc/ElimLocals.scala
@@ -11,7 +11,7 @@ import Flags.Local
/** Widens all private[this] and protected[this] qualifiers to just private/protected */
class ElimLocals extends MiniPhaseTransform with SymTransformer { thisTransformer =>
- override def name = "elimlocals"
+ override def name = "elimLocals"
def transformSym(ref: SymDenotation)(implicit ctx: Context) =
dropLocal(ref)
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index ca2259930..881cc3f6e 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -409,7 +409,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
/** Strips layers of `.asInstanceOf[T]` / `_.$asInstanceOf[T]()` from an expression */
def stripCast(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = {
- def isCast(sel: tpd.Tree) = defn.asInstanceOfMethods contains sel.symbol
+ def isCast(sel: tpd.Tree) = sel.symbol == defn.Any_asInstanceOf
unsplice(tree) match {
case TypeApply(sel @ Select(inner, _), _) if isCast(sel) =>
stripCast(inner)
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index b1e4a0cd3..87cbbc249 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -169,7 +169,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
ta.assignType(untpd.ValDef(Modifiers(sym), sym.name, TypeTree(sym.info), rhs), sym)
def SyntheticValDef(name: TermName, rhs: Tree)(implicit ctx: Context): ValDef =
- ValDef(ctx.newSymbol(ctx.owner, name, Synthetic, rhs.tpe, coord = rhs.pos), rhs)
+ ValDef(ctx.newSymbol(ctx.owner, name, Synthetic, rhs.tpe.widen, coord = rhs.pos), rhs)
def DefDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef =
ta.assignType(DefDef(sym, Function.const(rhs) _), sym)
@@ -348,21 +348,16 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}
- override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = {
- val tree1 = untpd.cpy.Apply(tree)(fun, args)
- tree match {
- case tree: Apply if (fun.tpe.widen eq tree.fun.tpe.widen) && sameTypes(args, tree.args) => tree1.withTypeUnchecked(tree.tpe)
- case _ => ta.assignType(tree1, fun, args)
- }
- }
+ override def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply =
+ ta.assignType(untpd.cpy.Apply(tree)(fun, args), fun, args)
+ // Note: Reassigning the original type if `fun` and `args` have the same types as before
+ // does not work here: The computed type depends on the widened function type, not
+ // the function type itself. A treetransform may keep the function type the
+ // same but its widened type might change.
- override def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = {
- val tree1 = untpd.cpy.TypeApply(tree)(fun, args)
- tree match {
- case tree: TypeApply if (fun.tpe.widen eq tree.fun.tpe.widen) && sameTypes(args, tree.args) => tree1.withTypeUnchecked(tree.tpe)
- case _ => ta.assignType(tree1, fun, args)
- }
- }
+ override def TypeApply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): TypeApply =
+ ta.assignType(untpd.cpy.TypeApply(tree)(fun, args), fun, args)
+ // Same remark as for Apply
override def Literal(tree: Tree)(const: Constant)(implicit ctx: Context): Literal =
ta.assignType(untpd.cpy.Literal(tree)(const))
@@ -403,13 +398,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
}
}
- override def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure = {
- val tree1 = untpd.cpy.Closure(tree)(env, meth, tpt)
- tree match {
- case tree: Closure if (meth.tpe.widen eq tree.meth.tpe.widen) && (tpt eq tree.tpt) => tree1.withTypeUnchecked(tree.tpe)
- case _ => ta.assignType(tree1, meth, tpt)
- }
- }
+ override def Closure(tree: Tree)(env: List[Tree], meth: Tree, tpt: Tree)(implicit ctx: Context): Closure =
+ ta.assignType(untpd.cpy.Closure(tree)(env, meth, tpt), meth, tpt)
+ // Same remark as for Apply
override def Match(tree: Tree)(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = {
val tree1 = untpd.cpy.Match(tree)(selector, cases)
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 82ed3ce1d..9018d4015 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -417,10 +417,6 @@ class Definitions {
lazy val PhantomClasses = Set[Symbol](AnyClass, AnyValClass, NullClass, NothingClass)
- lazy val asInstanceOfMethods = Set[Symbol](Any_asInstanceOf)
- lazy val isInstanceOfMethods = Set[Symbol](Any_isInstanceOf)
- lazy val typeTestsOrCasts = asInstanceOfMethods ++ isInstanceOfMethods
-
lazy val RootImports = List[Symbol](JavaLangPackageVal, ScalaPackageVal, ScalaPredefModule, DottyPredefModule)
lazy val overriddenBySynthetic = Set[Symbol](Any_equals, Any_hashCode, Any_toString, Product_canEqual)
diff --git a/src/dotty/tools/dotc/core/transform/Erasure.scala b/src/dotty/tools/dotc/core/transform/Erasure.scala
index 19662d22a..be7df46a9 100644
--- a/src/dotty/tools/dotc/core/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/core/transform/Erasure.scala
@@ -104,12 +104,14 @@ class Erasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcard
* - For a typeref P.C where C refers to a nested class, |P|.C.
* - For a typeref P.C where C refers to an alias type, the erasure of C's alias.
* - For a typeref P.C where C refers to an abstract type, the erasure of C's upper bound.
- * - For T1 & T2, erasure(T1) (??)
+ * - For T1 & T2, the merge of |T1| and |T2| (see mergeAnd)
* - For T1 | T2, the first base class in the linearization of T which is also a base class of T2
+ * - For => T, ()T
* - For a method type (Fs)scala.Unit, (|Fs|)scala.Unit.
* - For any other uncurried method type (Fs)T, (|Fs|)|T|.
* - For a curried method type (Fs1)(Fs2)T, (|Fs1|,Es2)ET where (Es2)ET = |(Fs2)T|.
- * - For a polymorphic type, the erasure of its result type.
+ * - For a polymorphic type [Ts](Ps)T, |(Ps)T|
+ * _ For a polymorphic type [Ts]T where T is not a method type, ()|T|
* - For the class info type of java.lang.Object, the same type without any parents.
* - For a class info type of a value class, the same type without any parents.
* - For any other class info type with parents Ps, the same type with
@@ -133,6 +135,8 @@ class Erasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcard
else tp.derivedSelect(this(tp.prefix))
case _: ThisType | _: ConstantType =>
tp
+ case ExprType(rt) =>
+ MethodType(Nil, Nil, this(rt))
case tp: TypeProxy =>
this(tp.underlying)
case AndType(tp1, tp2) =>
@@ -149,7 +153,10 @@ class Erasure(isJava: Boolean, isSemi: Boolean, isConstructor: Boolean, wildcard
tp.derivedMethodType(tp.paramNames, formals, rt)
}
case tp: PolyType =>
- this(tp.resultType)
+ this(tp.resultType) match {
+ case rt: MethodType => rt
+ case rt => MethodType(Nil, Nil, rt)
+ }
case tp @ ClassInfo(pre, cls, classParents, decls, _) =>
if (cls is Package) tp
else {
diff --git a/src/dotty/tools/dotc/transform/ElimByName.scala b/src/dotty/tools/dotc/transform/ElimByName.scala
new file mode 100644
index 000000000..80edf8819
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/ElimByName.scala
@@ -0,0 +1,113 @@
+package dotty.tools.dotc
+package transform
+
+import TreeTransforms._
+import core.DenotTransformers._
+import core.Symbols._
+import core.Contexts._
+import core.Types._
+import core.Flags._
+import core.Decorators._
+import SymUtils._
+import core.StdNames.nme
+import ast.Trees._
+
+/** This phase eliminates ExprTypes `=> T` and PolyTypes over value types `[X]T`.
+ * They are expressed in terms of nullary method or function types. More precisely:
+ *
+ * For types:
+ *
+ * => T ==> () => T if T is the type of a parameter
+ * ==> ()T otherwise
+ * [X]T ==> [X]()T
+ *
+ * For definitions:
+ *
+ * def f: R ==> def f(): R
+ * def f[X]: R ==> def f[X](): R
+ * (x: => T) ==> (x: () => T)
+ *
+ * For terms:
+ *
+ * f ==> f() if f had type => T and is not a parameter
+ * x ==> x.apply() if x is a parameter that had type => T
+ * e.apply() ==> e if e.apply() is an argument to a call-by-name parameter
+ * expr ==> () => expr if other expr is an argument to a call-by-name parameter
+ *
+ */
+class ElimByName extends MiniPhaseTransform with InfoTransformer { thisTransformer =>
+ import ast.tpd._
+
+ override def name: String = "elimByName"
+
+ override def runsAfterGroupsOf: Set[String] = Set("splitter")
+ // assumes idents and selects have symbols; interferes with splitter distribution
+ // that's why it's "after group".
+
+ override def treeTransformPhase = thisTransformer.next
+
+ /** The info of the tree's symbol at phase Nullarify (i.e. before transformation) */
+ private def originalDenotation(tree: Tree)(implicit ctx: Context) =
+ tree.symbol.denot(ctx.withPhase(thisTransformer))
+
+ override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree =
+ ctx.traceIndented(s"transforming ${tree.show} at phase ${ctx.phase}", show = true) {
+
+ def transformArg(arg: Tree, formal: Type): Tree = formal match {
+ case _: ExprType =>
+ arg match {
+ case Apply(Select(qual, nme.apply), Nil) if qual.tpe derivesFrom defn.FunctionClass(0) =>
+ qual
+ case _ =>
+ val meth = ctx.newSymbol(
+ ctx.owner, nme.ANON_FUN, Synthetic, MethodType(Nil, Nil, arg.tpe.widen))
+ Closure(meth, _ => arg)
+ }
+ case _ =>
+ arg
+ }
+
+ /** Given that `info` is the possibly curried) method type of the
+ * tree's symbol, the method type that corresponds to the current application.
+ */
+ def matchingMethType(info: Type, tree: Tree): Type = tree match {
+ case Apply(fn, _) => matchingMethType(info.resultType, fn)
+ case _ => info
+ }
+
+ val origMethType = originalDenotation(tree.fun).info match {
+ case pt: PolyType => pt.resultType
+ case mt => mt
+ }
+
+ val MethodType(_, formals) = matchingMethType(origMethType, tree.fun)
+ val args1 = tree.args.zipWithConserve(formals)(transformArg)
+ cpy.Apply(tree)(tree.fun, args1)
+ }
+
+ override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = {
+ val origDenot = originalDenotation(tree)
+ if ((origDenot is Param) && (origDenot.info.isInstanceOf[ExprType]))
+ tree.select(defn.Function0_apply).appliedToNone
+ else tree
+ }
+
+ def elimByNameParams(tp: Type)(implicit ctx: Context): Type = tp match {
+ case tp: PolyType =>
+ tp.derivedPolyType(tp.paramNames, tp.paramBounds, elimByNameParams(tp.resultType))
+ case tp: MethodType =>
+ tp.derivedMethodType(tp.paramNames, tp.paramTypes mapConserve transformParamInfo,
+ elimByNameParams(tp.resultType))
+ case _ =>
+ tp
+ }
+
+ def transformParamInfo(tp: Type)(implicit ctx: Context) = tp match {
+ case ExprType(rt) => defn.FunctionType(Nil, rt)
+ case _ => tp
+ }
+
+ def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
+ if (sym is Param) transformParamInfo(tp)
+ else elimByNameParams(tp)
+}
diff --git a/src/dotty/tools/dotc/transform/ElimRepeated.scala b/src/dotty/tools/dotc/transform/ElimRepeated.scala
index 3635a8741..04ca77a2d 100644
--- a/src/dotty/tools/dotc/transform/ElimRepeated.scala
+++ b/src/dotty/tools/dotc/transform/ElimRepeated.scala
@@ -23,7 +23,7 @@ import TypeUtils._
class ElimRepeated extends MiniPhaseTransform with InfoTransformer { thisTransformer =>
import ast.tpd._
- override def name = "elimrepeated"
+ override def name = "elimRepeated"
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
elimRepeated(tp)
diff --git a/src/dotty/tools/dotc/transform/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala
index f02846735..e85161f2d 100644
--- a/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/transform/Erasure.scala
@@ -30,7 +30,7 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
override def name: String = "erasure"
/** List of names of phases that should precede this phase */
- override def runsAfter: Set[String] = Set("typeTestsCasts", "intercepted", "splitter", "nullarify")
+ override def runsAfter: Set[String] = Set("typeTestsCasts"/*, "intercepted"*/, "splitter", "elimRepeated")
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match {
case ref: SymDenotation =>
@@ -100,8 +100,6 @@ object Erasure {
EmptyTree
}
- def isErasedValueType(tpe: Type)(implicit ctx: Context): Boolean = tpe.isInstanceOf[ErasedValueType]
-
def constant(tree: Tree, const: Tree)(implicit ctx: Context) =
if (isPureExpr(tree)) Block(tree :: Nil, const) else const
@@ -169,25 +167,32 @@ object Erasure {
/** Adaptation of an expression `e` to an expected type `PT`, applying the following
* rewritings exhaustively as long as the type of `e` is not a subtype of `PT`.
*
+ * e -> e() if `e` appears not as the function part of an application
* e -> box(e) if `e` is of erased value type
* e -> unbox(e, PT) otherwise, if `PT` is an erased value type
* e -> box(e) if `e` is of primitive type and `PT` is not a primitive type
* e -> unbox(e, PT) if `PT` is a primitive type and `e` is not of primitive type
* e -> cast(e, PT) otherwise
*/
- def adaptToType(tree: Tree, pt: Type)(implicit ctx: Context): Tree =
- if (tree.tpe <:< pt)
- tree
- else if (tree.tpe.widen.isErasedValueType)
- adaptToType(box(tree), pt)
- else if (pt.isErasedValueType)
- adaptToType(unbox(tree, pt), pt)
- else if (tree.tpe.widen.isPrimitiveValueType && !pt.isPrimitiveValueType)
- adaptToType(box(tree), pt)
- else if (pt.isPrimitiveValueType && !tree.tpe.widen.isPrimitiveValueType)
- adaptToType(unbox(tree, pt), pt)
- else
- cast(tree, pt)
+ def adaptToType(tree: Tree, pt: Type)(implicit ctx: Context): Tree = {
+ def makeConformant(tpw: Type): Tree = tpw match {
+ case MethodType(Nil, _) =>
+ adaptToType(tree.appliedToNone, pt)
+ case _ =>
+ if (tpw.isErasedValueType)
+ adaptToType(box(tree), pt)
+ else if (pt.isErasedValueType)
+ adaptToType(unbox(tree, pt), pt)
+ else if (tpw.isPrimitiveValueType && !pt.isPrimitiveValueType)
+ adaptToType(box(tree), pt)
+ else if (pt.isPrimitiveValueType && !tpw.isPrimitiveValueType)
+ adaptToType(unbox(tree, pt), pt)
+ else
+ cast(tree, pt)
+ }
+ if ((pt eq AnyFunctionProto) || tree.tpe <:< pt) tree
+ else makeConformant(tree.tpe.widen)
+ }
}
class Typer extends typer.ReTyper with NoChecking {
@@ -278,7 +283,7 @@ object Erasure {
Nil
}
val allArgs = args ++ contextArgs(tree)
- val fun1 = typedExpr(fun, WildcardType)
+ val fun1 = typedExpr(fun, AnyFunctionProto)
fun1.tpe.widen match {
case mt: MethodType =>
val allArgs1 = allArgs.zipWithConserve(mt.paramTypes)(typedExpr)
@@ -296,10 +301,12 @@ object Erasure {
block // optimization, no checking needed, as block symbols do not change.
override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = {
- val tpt1 = // keep UnitTypes intact in result position
- if (ddef.tpt.typeOpt isRef defn.UnitClass) untpd.TypeTree(defn.UnitType) withPos ddef.tpt.pos
- else ddef.tpt
- val ddef1 = untpd.cpy.DefDef(ddef)(tparams = Nil, tpt = tpt1)
+ val ddef1 = untpd.cpy.DefDef(ddef)(
+ tparams = Nil,
+ vparamss = if (ddef.vparamss.isEmpty) Nil :: Nil else ddef.vparamss,
+ tpt = // keep UnitTypes intact in result position
+ if (ddef.tpt.typeOpt isRef defn.UnitClass) untpd.TypeTree(defn.UnitType) withPos ddef.tpt.pos
+ else ddef.tpt)
super.typedDefDef(ddef1, sym)
}
diff --git a/src/dotty/tools/dotc/transform/ExtensionMethods.scala b/src/dotty/tools/dotc/transform/ExtensionMethods.scala
index 42e10b126..82db07809 100644
--- a/src/dotty/tools/dotc/transform/ExtensionMethods.scala
+++ b/src/dotty/tools/dotc/transform/ExtensionMethods.scala
@@ -29,7 +29,7 @@ class ExtensionMethods extends MacroTransform with DenotTransformer with FullPar
/** the following two members override abstract members in Transform */
val name: String = "extmethods"
- override def runsAfter: Set[String] = Set("elimrepeated") // TODO: add tailrec
+ override def runsAfter: Set[String] = Set("elimRepeated") // TODO: add tailrec
override def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match {
case ref: ClassDenotation if ref is ModuleClass =>
diff --git a/src/dotty/tools/dotc/transform/Nullarify.scala b/src/dotty/tools/dotc/transform/Nullarify.scala
deleted file mode 100644
index 554a51efb..000000000
--- a/src/dotty/tools/dotc/transform/Nullarify.scala
+++ /dev/null
@@ -1,147 +0,0 @@
-package dotty.tools.dotc
-package transform
-
-import TreeTransforms._
-import core.DenotTransformers._
-import core.Symbols._
-import core.Contexts._
-import core.Types._
-import core.Flags._
-import core.Decorators._
-import core.StdNames.nme
-import ast.Trees._
-
-/** This phase eliminates ExprTypes `=> T` and PolyTypes over value types `[X]T`.
- * They are expressed in terms of nullary method or function types. More precisely:
- *
- * For types:
- *
- * => T ==> () => T if T is the type of a parameter
- * ==> ()T otherwise
- * [X]T ==> [X]()T
- *
- * For definitions:
- *
- * def f: R ==> def f(): R
- * def f[X]: R ==> def f[X](): R
- * (x: => T) ==> (x: () => T)
- *
- * For terms:
- *
- * f ==> f() if f had type => T and is not a parameter
- * x ==> x.apply() if x is a parameter that had type => T
- * e.apply() ==> e if e.apply() is an argument to a call-by-name parameter
- * expr ==> () => expr if other expr is an argument to a call-by-name parameter
- *
- */
-class Nullarify extends MiniPhaseTransform with InfoTransformer {
- import ast.tpd._
-
- override def name: String = "nullarify"
-
- override def runsAfterGroupsOf: Set[String] = Set("splitter")
- // assumes idents and selects have symbols; interferes with splitter distribution
- // that's why it's "after group".
-
- override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree =
- ctx.traceIndented(s"transforming ${tree.show} at phase ${ctx.phase}", show = true) {
-
- def transformArg(arg: Tree, formal: Type): Tree = formal match {
- case _: ExprType =>
- arg match {
- case Apply(Select(qual, nme.apply), Nil) if qual.tpe <:< defn.FunctionClass(0).typeRef => qual
- case _ =>
- val meth = ctx.newSymbol(ctx.owner, nme.ANON_FUN, Synthetic,
- MethodType(Nil, Nil, arg.tpe.widen))
- Closure(meth, _ => arg)
- }
- case _ =>
- arg
- }
-
- // Compute the method type tree had before this phase is run.
- // This is needed to find out which parameters are by-name.
- val funType = tree.fun.symbol.info match {
- case info: PolyType => info.resultType
- case info => info
- }
- def methType(info: Type, tree: Tree): Type = tree match {
- case Apply(fn, args) => methType(info.resultType, fn)
- case _ => info
- }
- val MethodType(_, formals) = methType(funType, tree.fun)
-
- val args1 = tree.args.zipWithConserve(formals)(transformArg)
- cpy.Apply(tree)(tree.fun, args1) withType nullarify(tree.tpe)
- }
-
- /** Insert () or .apply() if the term refers to something that was converted to a
- * nullary method. Also, transform its type.
- */
- def insertParens(tree: Tree)(implicit ctx: Context): Tree = {
- val tp1 = transformInfo(tree.tpe, tree.symbol)
- val tree1 = tree.withType(tp1)
- val origType = tree.tpe.widenSingleton
- def result(implicit ctx: Context) = {
- tp1.widen match {
- case MethodType(Nil, _) if origType.widenExpr.isInstanceOf[ValueType] =>
- tree1.appliedToNone
- case _ =>
- origType match {
- case _: ExprType => // it's a by-name parameter
- tree1.select(defn.Function0_apply).appliedToNone
- case _ =>
- tree1
- }
- }
- }
- result(ctx.withPhase(ctx.phase.next))
- }
-
- override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree =
- insertParens(tree)
-
- override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree =
- insertParens(tree)
-
- override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree =
- insertParens(tree)
-
- override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = {
- val vparamss1 =
- if (tree.vparamss.isEmpty) Nil :: Nil
- else tree.vparamss nestedMap { vparam =>
- val tp = vparam.tpt.tpe
- val tp1 = nullarifyParam(tp)
- if (tp eq tp1) vparam
- else cpy.ValDef(vparam)(tpt = vparam.tpt.withType(tp1))
- }
- cpy.DefDef(tree)(vparamss = vparamss1)
- }
-
- def nullarify(tp: Type)(implicit ctx: Context): Type = tp match {
- case ExprType(rt) =>
- MethodType(Nil, Nil, rt)
- case pt: PolyType =>
- val rt = pt.resultType match {
- case mt: MethodType => nullarify(mt)
- case rt => MethodType(Nil, Nil, rt)
- }
- pt.derivedPolyType(pt.paramNames, pt.paramBounds, rt)
- case mt: MethodType =>
- mt.derivedMethodType(mt.paramNames, mt.paramTypes mapConserve nullarifyParam,
- nullarify(mt.resultType))
- case _ =>
- tp
- }
-
- def nullarifyParam(tp: Type)(implicit ctx: Context) = tp match {
- case ExprType(rt) => defn.FunctionType(Nil, rt)
- case _ => tp
- }
-
- def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type =
- if (defn.typeTestsOrCasts contains sym) tp
- else if (sym is Param) nullarifyParam(tp)
- else nullarify(tp)
-}
diff --git a/src/dotty/tools/dotc/transform/SymUtils.scala b/src/dotty/tools/dotc/transform/SymUtils.scala
new file mode 100644
index 000000000..e5dfd4d4e
--- /dev/null
+++ b/src/dotty/tools/dotc/transform/SymUtils.scala
@@ -0,0 +1,25 @@
+package dotty.tools.dotc
+package transform
+
+import core._
+import core.transform.Erasure.ErasedValueType
+import Types._
+import Contexts._
+import Symbols._
+import Decorators._
+import StdNames.nme
+import NameOps._
+import language.implicitConversions
+
+object SymUtils {
+ implicit def decorateSymUtils(sym: Symbol): SymUtils = new SymUtils(sym)
+}
+
+/** A decorator that provides methods on symbols
+ * that are needed in the transformer pipeline.
+ */
+class SymUtils(val self: Symbol) extends AnyVal {
+
+ def isTypeTestOrCast(implicit ctx: Context): Boolean =
+ self == defn.Any_asInstanceOf || self == defn.Any_isInstanceOf
+}
diff --git a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
index 93acc8e86..8d420546f 100644
--- a/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
+++ b/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
@@ -89,7 +89,7 @@ class TypeTestsCasts extends MiniPhaseTransform {
if (sym eq defn.Any_isInstanceOf)
transformIsInstanceOf(qual, tree.args.head.tpe)
- else if (defn.asInstanceOfMethods contains sym)
+ else if (sym eq defn.Any_asInstanceOf)
transformAsInstanceOf(tree.args.head.tpe)
else tree
diff --git a/src/dotty/tools/dotc/transform/TypeUtils.scala b/src/dotty/tools/dotc/transform/TypeUtils.scala
index d07930661..a07ac9041 100644
--- a/src/dotty/tools/dotc/transform/TypeUtils.scala
+++ b/src/dotty/tools/dotc/transform/TypeUtils.scala
@@ -16,8 +16,8 @@ object TypeUtils {
}
-/** A decorator that provides methods for type transformations
- * that are needed in the transofmer pipeline (not needed right now)
+/** A decorator that provides methods on types
+ * that are needed in the transformer pipeline.
*/
class TypeUtils(val self: Type) extends AnyVal {
@@ -26,5 +26,4 @@ class TypeUtils(val self: Type) extends AnyVal {
def isPrimitiveValueType(implicit ctx: Context): Boolean =
self.classSymbol.isPrimitiveValueClass
-
- }
+}
diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala
index eb202cc15..22129bde2 100644
--- a/src/dotty/tools/dotc/typer/Checking.scala
+++ b/src/dotty/tools/dotc/typer/Checking.scala
@@ -202,14 +202,15 @@ trait Checking {
def checkLegalPrefix(tp: Type, selector: Name, pos: Position)(implicit ctx: Context): Unit =
if (!tp.isLegalPrefixFor(selector)) ctx.error(d"$tp is not a valid prefix for '# $selector'", pos)
- /** Check that `tp` is a class type with a stable prefix. Also, if `isFirst` is
- * false check that `tp` is a trait.
+ /** Check that `tp` is a class type with a stable prefix. Also, if `traitReq` is
+ * true check that `tp` is a trait.
+ * Stability checking is disabled in phases after RefChecks.
* @return `tp` itself if it is a class or trait ref, ObjectClass.typeRef if not.
*/
def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type =
tp.underlyingClassRef match {
case tref: TypeRef =>
- checkStable(tref.prefix, pos)
+ if (ctx.phase <= ctx.refchecksPhase) checkStable(tref.prefix, pos)
if (traitReq && !(tref.symbol is Trait)) ctx.error(d"$tref is not a trait", pos)
tp
case _ =>
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 795e11c75..f973bd1e0 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -14,7 +14,7 @@ class tests extends CompilerTest {
"-pagewidth", "160")
implicit val defaultOptions = noCheckOptions ++ List(
- "-Ycheck:splitter"
+ "-Ycheck:elimByName"
)
val twice = List("#runs", "2", "-YnoDoubleBindings")
diff --git a/tests/pos/Patterns.scala b/tests/pos/Patterns.scala
index 4470eb232..f601b95a8 100644
--- a/tests/pos/Patterns.scala
+++ b/tests/pos/Patterns.scala
@@ -1,4 +1,4 @@
-object Patterns {
+object Patterns {/*
('1', "1") match {
case (digit, str) => true
case _ => false
@@ -25,7 +25,7 @@ object Patterns {
def len[T](xs: List[T]): Int = xs match {
case _ :: xs1 => 1 + len(xs1)
case Nil => 0
- }
+ }*/
final def sameLength[T](xs: List[T], ys: List[T]): Boolean = xs match {
case _ :: xs1 =>
@@ -35,4 +35,4 @@ object Patterns {
}
case _ => ys.isEmpty
}
-} \ No newline at end of file
+}