diff options
Diffstat (limited to 'src/dotty/tools')
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 7 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Applications.scala | 58 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/ErrorReporting.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Inferencing.scala | 76 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 31 |
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) } } |