aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-08-21 11:57:27 +0200
committerMartin Odersky <odersky@gmail.com>2013-08-21 11:57:27 +0200
commitdb35ebf5519fe1c7f2f2870691139edc93c3d0a3 (patch)
tree113c3627f21e36cffb999b90ebd0fa287d480cc4 /src/dotty/tools
parent1128d72e9b6ccc766c53b5f4872249aedafc00be (diff)
downloaddotty-db35ebf5519fe1c7f2f2870691139edc93c3d0a3.tar.gz
dotty-db35ebf5519fe1c7f2f2870691139edc93c3d0a3.tar.bz2
dotty-db35ebf5519fe1c7f2f2870691139edc93c3d0a3.zip
Refactoring to prototype scheme
- all prototypes now defined in Inferencing - there is a hook in type comparers which delegates to prototype comparison method isMatchedBy.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/core/Types.scala7
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala58
-rw-r--r--src/dotty/tools/dotc/typer/ErrorReporting.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Inferencing.scala76
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala31
6 files changed, 90 insertions, 88 deletions
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 6afd4e92d..94810a2a2 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -1131,7 +1131,7 @@ object Types {
trait BindingType extends Type
/** A trait for proto-types, used as expected types in typer */
- trait ProtoType extends UncachedGroundType {
+ trait ProtoType extends Type {
def isMatchedBy(tp: Type)(implicit ctx: Context): Boolean
}
@@ -1381,11 +1381,6 @@ object Types {
override def underlying(implicit ctx: Context) = parent
- /** Does goves type match `refinedInfo`. Translates to a subtype check here,
- * but is overridden in SelectionProto
- */
- def matchesInfo(tp: Type)(implicit ctx: Context): Boolean = tp <:< refinedInfo
-
def derivedRefinedType(parent: Type, refinedName: Name, refinedInfo: Type)(implicit ctx: Context): RefinedType = {
def originalName = parent.typeParams.apply(refinedName.hkParamIndex).name
if ((parent eq this.parent) && (refinedName eq this.refinedName) && (refinedInfo eq this.refinedInfo))
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 439210af4..66fb4c3e1 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -31,52 +31,6 @@ object Applications {
private val isNamedArg = (arg: Any) => arg.isInstanceOf[Trees.NamedArg[_]]
def hasNamedArg(args: List[Any]) = args exists isNamedArg
-
- /** A trait defining an `isCompatible` method. */
- trait Compatibility {
-
- /** Is there an implicit conversion from `tp` to `pt`? */
- def viewExists(tp: Type, pt: Type)(implicit ctx: Context): Boolean
-
- /** A type `tp` is compatible with a type `pt` if one of the following holds:
- * 1. `tp` is a subtype of `pt`
- * 2. `pt` is by name parameter type, and `tp` is compatible with its underlying type
- * 3. there is an implicit conversion from `tp` to `pt`.
- */
- def isCompatible(tp: Type, pt: Type)(implicit ctx: Context): Boolean = (
- tp <:< pt
- || pt.typeSymbol == defn.ByNameParamClass && tp <:< pt.typeArgs.head
- || viewExists(tp, pt))
- }
-
- /** The normalized form of a type
- * - unwraps polymorphic types, tracking their parameters in the current constraint
- * - skips implicit parameters
- * - converts non-dependent method types to the corresponding function types
- * - dereferences parameterless method types
- */
- def normalize(tp: Type)(implicit ctx: Context): Type = tp.widen match {
- case pt: PolyType => normalize(ctx.track(pt).resultType)
- case mt: MethodType if !mt.isDependent =>
- if (mt.isImplicit) mt.resultType
- else defn.FunctionType(mt.paramTypes, mt.resultType)
- case et: ExprType => et.resultType
- case _ => tp
- }
-
- case class FunProtoType(args: List[untpd.Tree], override val resultType: Type, typer: Typer)(implicit ctx: Context) extends UncachedGroundType {
- private var myTypedArgs: List[Tree] = null
-
- def argsAreTyped: Boolean = myTypedArgs != null
-
- def typedArgs: List[Tree] = {
- if (myTypedArgs == null)
- myTypedArgs = args mapconserve (typer.typed(_))
- myTypedArgs
- }
- }
-
- case class PolyProtoType(nargs: Int, override val resultType: Type) extends UncachedGroundType
}
import Applications._
@@ -328,7 +282,7 @@ trait Applications extends Compatibility { self: Typer =>
* must fit the given expected result type.
*/
def constrainResult(mt: Type, pt: Type): Boolean = pt match {
- case FunProtoType(_, result, _) =>
+ case FunProto(_, result, _) =>
mt match {
case mt: MethodType if !mt.isDependent =>
constrainResult(mt.resultType, pt.resultType)
@@ -503,7 +457,7 @@ trait Applications extends Compatibility { self: Typer =>
else {
def realApply(implicit ctx: Context) = {
- val proto = new FunProtoType(tree.args, pt, this)
+ val proto = new FunProto(tree.args, pt, this)
val fun1 = typedExpr(tree.fun, proto)
methPart(fun1).tpe match {
case funRef: TermRef =>
@@ -545,7 +499,7 @@ trait Applications extends Compatibility { self: Typer =>
}
def typedTypeApply(tree: untpd.TypeApply, pt: Type)(implicit ctx: Context): Tree = {
- val typedFn = typedExpr(tree.fun, PolyProtoType(tree.args.length, pt))
+ val typedFn = typedExpr(tree.fun, PolyProto(tree.args.length, pt))
val typedArgs = tree.args mapconserve (typedType(_))
val ownType = typedFn.tpe.widen match {
case pt: PolyType =>
@@ -598,7 +552,7 @@ trait Applications extends Compatibility { self: Typer =>
val unapply = {
val dummyArg = untpd.TypedSplice(dummyTreeOfType(WildcardType))
- val unappProto = FunProtoType(dummyArg :: Nil, pt, this)
+ val unappProto = FunProto(dummyArg :: Nil, pt, this)
tryEither {
implicit ctx => typedExpr(untpd.Select(qual, nme.unapply), unappProto)
} {
@@ -773,7 +727,7 @@ trait Applications extends Compatibility { self: Typer =>
alts filter (isApplicableToTypes(_, argTypes, resultType))
val candidates = pt match {
- case pt @ FunProtoType(args, resultType, _) =>
+ case pt @ FunProto(args, resultType, _) =>
val numArgs = args.length
def sizeFits(alt: TermRef, tp: Type): Boolean = tp match {
@@ -811,7 +765,7 @@ trait Applications extends Compatibility { self: Typer =>
else narrowByTrees(alts2, pt.typedArgs, resultType)
}
- case pt @ PolyProtoType(nargs, _) =>
+ case pt @ PolyProto(nargs, _) =>
alts filter (alt => alt.widen match {
case PolyType(pnames) if pnames.length == nargs => true
case _ => false
diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala
index 8bbf1eba0..d95807e3c 100644
--- a/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -5,7 +5,7 @@ package typer
import ast._
import core._
import Trees._
-import Types._, Contexts._, Decorators._, Denotations._, Symbols._
+import Types._, Inferencing._, Contexts._, Decorators._, Denotations._, Symbols._
import Applications._
import util.Positions._
import printing.Showable
@@ -26,7 +26,7 @@ object ErrorReporting {
class Errors(implicit ctx: Context) {
def expectedTypeStr(tp: Type): String = tp match {
- case tp: FunProtoType =>
+ case tp: FunProto =>
val result = tp.resultType match {
case tp: WildcardType => ""
case tp => i"and expected result type $tp"
diff --git a/src/dotty/tools/dotc/typer/Inferencing.scala b/src/dotty/tools/dotc/typer/Inferencing.scala
index fe388cc40..86cd2a9c4 100644
--- a/src/dotty/tools/dotc/typer/Inferencing.scala
+++ b/src/dotty/tools/dotc/typer/Inferencing.scala
@@ -4,7 +4,7 @@ package typer
import core._
import ast._
-import Contexts._, Types._, Flags._, Denotations._, NameOps._, Symbols._
+import Contexts._, Types._, Flags._, Denotations._, Names._, StdNames._, NameOps._, Symbols._
import Trees._
import annotation.unchecked
import util.Positions._
@@ -15,6 +15,80 @@ object Inferencing {
import tpd._
+ /** A trait defining an `isCompatible` method. */
+ trait Compatibility {
+
+ /** Is there an implicit conversion from `tp` to `pt`? */
+ def viewExists(tp: Type, pt: Type)(implicit ctx: Context): Boolean
+
+ /** A type `tp` is compatible with a type `pt` if one of the following holds:
+ * 1. `tp` is a subtype of `pt`
+ * 2. `pt` is by name parameter type, and `tp` is compatible with its underlying type
+ * 3. there is an implicit conversion from `tp` to `pt`.
+ */
+ def isCompatible(tp: Type, pt: Type)(implicit ctx: Context): Boolean = (
+ tp <:< pt
+ || pt.typeSymbol == defn.ByNameParamClass && tp <:< pt.typeArgs.head
+ || viewExists(tp, pt))
+ }
+
+ class SelectionProto(name: Name, proto: Type)
+ extends RefinedType(WildcardType, name)(_ => proto) with ProtoType with Compatibility {
+ override def viewExists(tp: Type, pt: Type)(implicit ctx: Context): Boolean = false
+ override def isMatchedBy(tp1: Type)(implicit ctx: Context) = {
+ def testCompatible(mbrType: Type)(implicit ctx: Context) =
+ isCompatible(normalize(mbrType), /*(new WildApprox) apply (needed?)*/ proto)
+ name == nme.WILDCARD || {
+ val mbr = tp1.member(name)
+ mbr.exists && mbr.hasAltWith(m => testCompatible(m.info)(ctx.fresh.withNewTyperState))
+ }
+ }
+ }
+
+ /** Create a selection proto-type, but only one level deep;
+ * treat constructors specially
+ */
+ def selectionProto(name: Name, tp: Type) =
+ if (name.isConstructorName) WildcardType
+ else {
+ val rtp = tp match {
+ case tp: ProtoType => WildcardType
+ case _ => tp
+ }
+ new SelectionProto(name, rtp)
+ }
+
+ object AnySelectionProto extends SelectionProto(nme.WILDCARD, WildcardType)
+
+ case class FunProto(args: List[untpd.Tree], override val resultType: Type, typer: Typer)(implicit ctx: Context) extends UncachedGroundType {
+ private var myTypedArgs: List[Tree] = null
+
+ def argsAreTyped: Boolean = myTypedArgs != null
+
+ def typedArgs: List[Tree] = {
+ if (myTypedArgs == null)
+ myTypedArgs = args mapconserve (typer.typed(_))
+ myTypedArgs
+ }
+ }
+
+ case class PolyProto(nargs: Int, override val resultType: Type) extends UncachedGroundType
+
+ /** The normalized form of a type
+ * - unwraps polymorphic types, tracking their parameters in the current constraint
+ * - skips implicit parameters
+ * - converts non-dependent method types to the corresponding function types
+ * - dereferences parameterless method types
+ */
+ def normalize(tp: Type)(implicit ctx: Context): Type = tp.widen match {
+ case pt: PolyType => normalize(ctx.track(pt).resultType)
+ case mt: MethodType if !mt.isDependent =>
+ if (mt.isImplicit) mt.resultType
+ else defn.FunctionType(mt.paramTypes, mt.resultType)
+ case et: ExprType => et.resultType
+ case _ => tp
+ }
+
/** Is type fully defined, meaning the type does not contain wildcard types
* or uninstantiated type variables. As a side effect, this will minimize
* any uninstantiated type variables, provided that
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 0bd841098..cc5d041b9 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -7,7 +7,7 @@ import ast._
import Trees._, Constants._, StdNames._, Scopes._, Denotations._
import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._
import ast.desugar, ast.desugar._
-import Typer.AnySelectionProto
+import Inferencing.AnySelectionProto
import util.Positions._
import util.SourcePosition
import collection.mutable
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index cdcf43272..7702b1750 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -20,7 +20,7 @@ import NameOps._
import Flags._
import Decorators._
import ErrorReporting._
-import Applications.{FunProtoType, PolyProtoType, Compatibility, normalize}
+import Inferencing.{FunProto, PolyProto, Compatibility, normalize}
import EtaExpansion.etaExpand
import util.Positions._
import util.SourcePosition
@@ -56,27 +56,6 @@ object Typer {
value
}
}
-
- class SelectionProto(name: Name, tp: Type) extends RefinedType(WildcardType, name)(_ => tp) with Compatibility {
- override def viewExists(tp: Type, pt: Type)(implicit ctx: Context): Boolean = false
- override def matchesInfo(tp: Type)(implicit ctx: Context) = {
- def test(implicit ctx: Context) =
- isCompatible(normalize(tp), /*(new WildApprox) apply (needed?)*/ refinedInfo)
- test(ctx.fresh.withNewTyperState)
- }
- }
-
- def selectionProto(name: Name, tp: Type) =
- if (name.isConstructorName) WildcardType
- else {
- val rtp = tp match {
- case tp: SelectionProto => WildcardType
- case _ => tp
- }
- new SelectionProto(name, rtp)
- }
-
- object AnySelectionProto extends SelectionProto(nme.WILDCARD, WildcardType)
}
class Typer extends Namer with Applications with Implicits {
@@ -965,7 +944,7 @@ class Typer extends Namer with Applications with Implicits {
i"""none of the ${err.overloadedAltsStr(altDenots)}
|match $expectedStr""".stripMargin)
pt match {
- case pt: FunProtoType => tryInsertApply(tree, pt)(_ => noMatches)
+ case pt: FunProto => tryInsertApply(tree, pt)(_ => noMatches)
case _ => noMatches
}
case alts =>
@@ -975,7 +954,7 @@ class Typer extends Namer with Applications with Implicits {
}
}
- def adaptToArgs(tp: Type, pt: FunProtoType) = tp match {
+ def adaptToArgs(tp: Type, pt: FunProto) = tp match {
case _: MethodType => tree
case _ => tryInsertApply(tree, pt) {
def fn = err.refStr(methPart(tree).tpe)
@@ -1041,7 +1020,7 @@ class Typer extends Namer with Applications with Implicits {
case ref: TermRef =>
adaptOverloaded(ref)
case poly: PolyType =>
- if (pt.isInstanceOf[PolyProtoType]) tree
+ if (pt.isInstanceOf[PolyProto]) tree
else {
val tracked = ctx.track(poly)
val tvars = ctx.newTypeVars(tracked, tree.pos)
@@ -1049,7 +1028,7 @@ class Typer extends Namer with Applications with Implicits {
}
case tp =>
pt match {
- case pt: FunProtoType => adaptToArgs(tp, pt)
+ case pt: FunProto => adaptToArgs(tp, pt)
case _ => adaptNoArgs(tp)
}
}