Skip to content

Fix/#34 pathresolvers #38

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 3, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/dotty/tools/dotc/ast/CheckTrees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ object CheckTrees {
check(finalizer.isTerm)
check(handler.isTerm)
check(handler.tpe derivesFrom defn.FunctionClass(1))
check(handler.tpe.baseTypeArgs(defn.FunctionClass(1)).head <:< defn.ThrowableType)
check(handler.tpe.baseArgInfos(defn.FunctionClass(1)).head <:< defn.ThrowableType)
case Throw(expr) =>
check(expr.isValue)
check(expr.tpe.derivesFrom(defn.ThrowableClass))
Expand Down Expand Up @@ -210,9 +210,9 @@ object CheckTrees {
check(args.isEmpty)
else {
check(rtp isRef defn.OptionClass)
val normArgs = rtp.typeArgs match {
val normArgs = rtp.argTypesHi match {
case optionArg :: Nil =>
optionArg.typeArgs match {
optionArg.argTypesHi match {
case Nil =>
optionArg :: Nil
case tupleArgs if defn.isTupleType(optionArg) =>
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {

/** new C(args) */
def New(tp: Type, args: List[Tree])(implicit ctx: Context): Apply = {
val targs = tp.typeArgs
val targs = tp.argTypes
Apply(
Select(
New(tp withoutArgs targs),
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ object untpd extends Trees.Instance[Untyped] with TreeInfo[Untyped] {
case TypedSplice(AppliedTypeTree(tycon, targs)) =>
(TypedSplice(tycon), targs map TypedSplice)
case TypedSplice(tpt1: Tree) =>
val argTypes = tpt1.tpe.typeArgs
val argTypes = tpt1.tpe.argTypes
val tycon = tpt1.tpe.withoutArgs(argTypes)
def wrap(tpe: Type) = TypeTree(tpe) withPos tpt.pos
(wrap(tycon), argTypes map wrap)
Expand Down
6 changes: 3 additions & 3 deletions src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ class Definitions {
def unapply(ft: Type): Option[(List[Type], Type)] = { // Dotty deviation: Type annotation needed because inferred type
// is Some[(List[Type], Type)] | None, which is not a legal unapply type.
val tsym = ft.typeSymbol
lazy val targs = ft.typeArgs
lazy val targs = ft.argInfos
if ((FunctionClasses contains tsym) &&
(targs.length - 1 <= MaxFunctionArity) &&
(FunctionClass(targs.length - 1) == tsym)) Some((targs.init, targs.last)) // Dotty deviation: no auto-tupling
Expand Down Expand Up @@ -317,7 +317,7 @@ class Definitions {
lazy val RootImports = List[Symbol](JavaLangPackageVal, ScalaPackageVal, ScalaPredefModule, DottyPredefModule)

def isTupleType(tp: Type) = {
val arity = tp.dealias.typeArgs.length
val arity = tp.dealias.argInfos.length
arity <= MaxTupleArity && (tp isRef TupleClass(arity))
}

Expand All @@ -329,7 +329,7 @@ class Definitions {
0 <= arity && arity <= MaxFunctionArity && (tp isRef FunctionClass(arity))
}

def functionArity(tp: Type) = tp.dealias.typeArgs.length - 1
def functionArity(tp: Type) = tp.dealias.argInfos.length - 1

// ----- Higher kinds machinery ------------------------------------------

Expand Down
80 changes: 66 additions & 14 deletions src/dotty/tools/dotc/core/TypeApplications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,29 @@ import Flags._
import util.Positions.Position
import collection.mutable

object TypeApplications {

/** Assert type is not a TypeBounds instance and return it unchanged */
val noBounds = (tp: Type) => tp match {
case tp: TypeBounds => throw new AssertionError("no TypeBounds allowed")
case _ => tp
}

/** If `tp` is a TypeBounds instance return its lower bound else return `tp` */
val boundsToLo = (tp: Type) => tp match {
case tp: TypeBounds => tp.lo
case _ => tp
}

/** If `tp` is a TypeBounds instance return its upper bound else return `tp` */
val boundsToHi = (tp: Type) => tp match {
case tp: TypeBounds => tp.hi
case _ => tp
}
}

import TypeApplications._

/** A decorator that provides methods for modeling type application */
class TypeApplications(val self: Type) extends AnyVal {

Expand Down Expand Up @@ -135,24 +158,43 @@ class TypeApplications(val self: Type) extends AnyVal {
else TypeAlias(self, v)
}

/** The type arguments of the base type instance wrt `base` of this type */
final def baseTypeArgs(base: Symbol)(implicit ctx: Context): List[Type] =
/** The type arguments of this type's base type instance wrt.`base`.
* Existential types in arguments are returned as TypeBounds instances.
*/
final def baseArgInfos(base: Symbol)(implicit ctx: Context): List[Type] =
if (self derivesFrom base)
base.typeParams map (param => self.member(param.name).info.argType(param))
base.typeParams map (param => self.member(param.name).info.argInfo(param))
else
Nil

/** The type arguments of this type's base type instance wrt.`base`.
* Existential types in arguments are disallowed.
*/
final def baseArgTypes(base: Symbol)(implicit ctx: Context): List[Type] = baseArgInfos(base) mapConserve noBounds

/** The type arguments of this type's base type instance wrt.`base`.
* Existential types in arguments are approximanted by their lower bound.
*/
final def baseArgTypesLo(base: Symbol)(implicit ctx: Context): List[Type] = baseArgInfos(base) mapConserve boundsToLo

/** The type arguments of this type's base type instance wrt.`base`.
* Existential types in arguments are approximanted by their upper bound.
*/
final def baseArgTypesHi(base: Symbol)(implicit ctx: Context): List[Type] = baseArgInfos(base) mapConserve boundsToHi

/** The first type argument of the base type instance wrt `base` of this type */
final def firstBaseTypeArg(base: Symbol)(implicit ctx: Context): Type = base.typeParams match {
final def firstBaseArgInfo(base: Symbol)(implicit ctx: Context): Type = base.typeParams match {
case param :: _ if self derivesFrom base =>
self.member(param.name).info.argType(param)
self.member(param.name).info.argInfo(param)
case _ =>
NoType
}

/** The base type including all type arguments of this type */
/** The base type including all type arguments of this type.
* Existential types in arguments are returned as TypeBounds instances.
*/
final def baseTypeWithArgs(base: Symbol)(implicit ctx: Context): Type =
self.baseTypeRef(base).appliedTo(baseTypeArgs(base))
self.baseTypeRef(base).appliedTo(baseArgInfos(base))

/** Translate a type of the form From[T] to To[T], keep other types as they are.
* `from` and `to` must be static classes, both with one type parameter, and the same variance.
Expand All @@ -163,9 +205,10 @@ class TypeApplications(val self: Type) extends AnyVal {
else self

/** If this is an encoding of a (partially) applied type, return its arguments,
* otherwise return Nil
* otherwise return Nil.
* Existential types in arguments are returned as TypeBounds instances.
*/
final def typeArgs(implicit ctx: Context): List[Type] = {
final def argInfos(implicit ctx: Context): List[Type] = {
var tparams: List[TypeSymbol] = null
def recur(tp: Type, refineCount: Int): mutable.ListBuffer[Type] = tp.stripTypeVar match {
case tp @ RefinedType(tycon, name) =>
Expand All @@ -175,7 +218,7 @@ class TypeApplications(val self: Type) extends AnyVal {
if (tparams == null) tparams = tycon.typeParams
if (buf.size < tparams.length) {
val tparam = tparams(buf.size)
if (name == tparam.name) buf += tp.refinedInfo.argType(tparam)
if (name == tparam.name) buf += tp.refinedInfo.argInfo(tparam)
else null
} else null
}
Expand All @@ -187,6 +230,15 @@ class TypeApplications(val self: Type) extends AnyVal {
if (buf == null) Nil else buf.toList
}

/** Argument types where existential types in arguments are disallowed */
def argTypes(implicit ctx: Context) = argInfos mapConserve noBounds

/** Argument types where existential types in arguments are approximated by their lower bound */
def argTypesLo(implicit ctx: Context) = argInfos mapConserve boundsToLo

/** Argument types where existential types in arguments are approximated by their upper bound */
def argTypesHi(implicit ctx: Context) = argInfos mapConserve boundsToHi

/** The core type without any type arguments.
* @param `typeArgs` must be the type arguments of this type.
*/
Expand All @@ -201,7 +253,7 @@ class TypeApplications(val self: Type) extends AnyVal {
/** If this is the image of a type argument to type parameter `tparam`,
* recover the type argument, otherwise NoType.
*/
final def argType(tparam: Symbol)(implicit ctx: Context): Type = self match {
final def argInfo(tparam: Symbol)(implicit ctx: Context): Type = self match {
case TypeBounds(lo, hi) =>
if (lo eq hi) hi
else {
Expand All @@ -216,7 +268,7 @@ class TypeApplications(val self: Type) extends AnyVal {

/** The element type of a sequence or array */
def elemType(implicit ctx: Context): Type =
firstBaseTypeArg(defn.SeqClass) orElse firstBaseTypeArg(defn.ArrayClass)
firstBaseArgInfo(defn.SeqClass) orElse firstBaseArgInfo(defn.ArrayClass)

/** If this type is of the normalized form Array[...[Array[T]...]
* return the number of Array wrappers and T.
Expand All @@ -225,7 +277,7 @@ class TypeApplications(val self: Type) extends AnyVal {
final def splitArray(implicit ctx: Context): (Int, Type) = {
def recur(n: Int, tp: Type): (Int, Type) = tp.stripTypeVar match {
case RefinedType(tycon, _) if tycon isRef defn.ArrayClass =>
tp.typeArgs match {
tp.argInfos match {
case arg :: Nil => recur(n + 1, arg)
case _ => (n, tp)
}
Expand Down Expand Up @@ -274,7 +326,7 @@ class TypeApplications(val self: Type) extends AnyVal {

val correspondingParamName: Map[Symbol, TypeName] = {
for {
(tparam, targ: TypeRef) <- cls.typeParams zip typeArgs
(tparam, targ: TypeRef) <- cls.typeParams zip argInfos
if boundSyms contains targ.symbol
} yield targ.symbol -> tparam.name
}.toMap
Expand Down
5 changes: 3 additions & 2 deletions src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ class TypeComparer(initctx: Context) extends DotClass {
*/
def isSubTypeHK(tp1: Type, tp2: Type): Boolean = {
val tparams = tp1.typeParams
val hkArgs = tp2.typeArgs
val hkArgs = tp2.argInfos
(hkArgs.length == tparams.length) && {
val base = tp1.narrow
(tparams, hkArgs).zipped.forall { (tparam, hkArg) =>
Expand Down Expand Up @@ -752,7 +752,7 @@ class TypeComparer(initctx: Context) extends DotClass {
/** The least upper bound of two types
* @note We do not admit singleton types in or-types as lubs.
*/
def lub(tp1: Type, tp2: Type): Type =
def lub(tp1: Type, tp2: Type): Type = /*>|>*/ ctx.traceIndented(s"lub(${tp1.show}, ${tp2.show})", typr, show = true) /*<|<*/ {
if (tp1 eq tp2) tp1
else if (!tp1.exists) tp1
else if (!tp2.exists) tp2
Expand All @@ -772,6 +772,7 @@ class TypeComparer(initctx: Context) extends DotClass {
}
}
}
}

/** The least upper bound of a list of types */
final def lub(tps: List[Type]): Type =
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ object Types {
else thissym eq sym
case this1: RefinedType =>
// make sure all refinements are type arguments
this1.parent.isRef(sym) && this.typeArgs.nonEmpty
this1.parent.isRef(sym) && this.argInfos.nonEmpty
case _ =>
false
}
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/core/pickling/UnPickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ object UnPickler {
case tp @ MethodType(paramNames, paramTypes) =>
val lastArg = paramTypes.last
assert(lastArg isRef defn.ArrayClass)
val elemtp0 :: Nil = lastArg.baseTypeArgs(defn.ArrayClass)
val elemtp0 :: Nil = lastArg.baseArgInfos(defn.ArrayClass)
val elemtp = elemtp0 match {
case AndType(t1, t2) if t1.typeSymbol.isAbstractType && (t2 isRef defn.ObjectClass) =>
t1 // drop intersection with Object for abstract types in varargs. UnCurry can handle them.
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/printing/RefinedPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
tp match {
case tp: RefinedType =>
val args = tp.typeArgs
val args = tp.argInfos
if (args.nonEmpty) {
val tycon = tp.unrefine
val cls = tycon.typeSymbol
Expand Down
8 changes: 5 additions & 3 deletions src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import EtaExpansion._
import collection.mutable
import reflect.ClassTag
import config.Printers._
import TypeApplications._
import language.implicitConversions

object Applications {
Expand Down Expand Up @@ -266,7 +267,7 @@ trait Applications extends Compatibility { self: Typer =>
case arg :: Nil if isVarArg(arg) =>
addTyped(arg, formal)
case _ =>
val elemFormal = formal.typeArgs.head
val elemFormal = formal.argTypesLo.head
args foreach (addTyped(_, elemFormal))
makeVarArg(args.length, elemFormal)
}
Expand Down Expand Up @@ -609,7 +610,7 @@ trait Applications extends Compatibility { self: Typer =>
if (extractorMemberType(unapplyResult, nme.isDefined) isRef defn.BooleanClass) {
if (getTp.exists)
if (unapply.symbol.name == nme.unapplySeq) {
val seqArg = getTp.firstBaseTypeArg(defn.SeqClass)
val seqArg = boundsToHi(getTp.firstBaseArgInfo(defn.SeqClass))
if (seqArg.exists) return args map Function.const(seqArg)
}
else return getSelectors(getTp)
Expand Down Expand Up @@ -683,6 +684,7 @@ trait Applications extends Compatibility { self: Typer =>
}

var argTypes = unapplyArgs(unapplyApp.tpe)
for (argType <- argTypes) assert(!argType.isInstanceOf[TypeBounds], unapplyApp.tpe.show)
val bunchedArgs = argTypes match {
case argType :: Nil if argType.isRepeatedParam => untpd.SeqLiteral(args) :: Nil
case _ => args
Expand Down Expand Up @@ -770,7 +772,7 @@ trait Applications extends Compatibility { self: Typer =>
val tparams = ctx.newTypeParams(alt1.symbol.owner, tp1.paramNames, EmptyFlags, bounds)
isAsSpecific(alt1, tp1.instantiate(tparams map (_.typeRef)), alt2, tp2)
case tp1: MethodType =>
def repeatedToSingle(tp: Type) = if (tp.isRepeatedParam) tp.typeArgs.head else tp
def repeatedToSingle(tp: Type) = if (tp.isRepeatedParam) tp.argTypesHi.head else tp
isApplicable(alt2, tp1.paramTypes map repeatedToSingle, WildcardType) ||
tp1.paramTypes.isEmpty && tp2.isInstanceOf[MethodOrPoly]
case _ =>
Expand Down
6 changes: 3 additions & 3 deletions src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ class Typer extends Namer with Applications with Implicits {
}

def typedPair(tree: untpd.Pair, pt: Type)(implicit ctx: Context) = track("typedPair") {
val (leftProto, rightProto) = pt.typeArgs match {
val (leftProto, rightProto) = pt.argTypesLo match {
case l :: r :: Nil if pt isRef defn.PairClass => (l, r)
case _ => (WildcardType, WildcardType)
}
Expand Down Expand Up @@ -561,7 +561,7 @@ class Typer extends Namer with Applications with Implicits {
val params = args.asInstanceOf[List[untpd.ValDef]]
val (protoFormals, protoResult): (List[Type], Type) = pt match {
case _ if defn.isFunctionType(pt) =>
(pt.dealias.typeArgs.init, pt.dealias.typeArgs.last)
(pt.dealias.argInfos.init, pt.dealias.argInfos.last)
case SAMType(meth) =>
val mt @ MethodType(_, paramTypes) = meth.info
(paramTypes, mt.resultType)
Expand Down Expand Up @@ -750,7 +750,7 @@ class Typer extends Namer with Applications with Implicits {
val expr1 = typed(tree.expr, pt)
val handler1 = typed(tree.handler, defn.FunctionType(defn.ThrowableType :: Nil, pt))
val finalizer1 = typed(tree.finalizer, defn.UnitType)
val handlerTypeArgs = handler1.tpe.baseTypeArgs(defn.FunctionClass(1))
val handlerTypeArgs = handler1.tpe.baseArgTypesHi(defn.FunctionClass(1))
val ownType = if (handlerTypeArgs.nonEmpty) expr1.tpe | handlerTypeArgs(1) else expr1.tpe
cpy.Try(tree, expr1, handler1, finalizer1) withType ownType
}
Expand Down
6 changes: 6 additions & 0 deletions test/dotc/tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,11 @@ class tests extends CompilerTest {
"-Ylog:frontend",
"-Xprompt"))

@Test def testIssue_34 = compileArgs(Array(
dotcDir + "tools/dotc/config/Properties.scala",
dotcDir + "tools/dotc/config/PathResolver.scala",
"-Ylog:frontend",
"-Xprompt"))

//@Test def dotc_compilercommand = compileFile(dotcDir + "tools/dotc/config/", "CompilerCommand")
}