From 02394593cf6ed5c092c398cdb1908ea5b0928d6a Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 21 Aug 2013 11:16:59 +0200 Subject: Fixes to import handling and adaptation and implicits --- src/dotty/tools/dotc/core/Contexts.scala | 2 -- src/dotty/tools/dotc/core/Denotations.scala | 8 ++--- src/dotty/tools/dotc/core/SymDenotations.scala | 19 +++++++----- src/dotty/tools/dotc/core/TypeComparer.scala | 5 ++- src/dotty/tools/dotc/core/Types.scala | 11 +++++-- src/dotty/tools/dotc/typer/Implicits.scala | 10 +++--- src/dotty/tools/dotc/typer/ImportInfo.scala | 11 +++++++ src/dotty/tools/dotc/typer/Typer.scala | 43 ++++++++++++++------------ 8 files changed, 66 insertions(+), 43 deletions(-) diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index ed86849b9..ebfde1a62 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -255,8 +255,6 @@ object Contexts { _condensed } - def implicitsEnabled: Boolean = ??? - /** A fresh clone of this context. */ def fresh: FreshContext = { val newctx = super.clone.asInstanceOf[FreshContext] diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 272b6f505..208c59213 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -159,7 +159,7 @@ object Denotations { def suchThat(p: Symbol => Boolean): SingleDenotation /** Does this denotation have an alternative that satisfies the predicate `p`? */ - def hasAltWith(p: Symbol => Boolean): Boolean + def hasAltWith(p: SingleDenotation => Boolean): Boolean /** The denotation made up from the alternatives of this denotation that * are accessible from prefix `pre`, or NoDenotation if no accessible alternative exists. @@ -352,7 +352,7 @@ object Denotations { else sd1 else sd2 } - def hasAltWith(p: Symbol => Boolean): Boolean = + def hasAltWith(p: SingleDenotation => Boolean): Boolean = denot1.hasAltWith(p) || denot2.hasAltWith(p) def accessibleFrom(pre: Type, superAccess: Boolean)(implicit ctx: Context): Denotation = { val d1 = denot1 accessibleFrom (pre, superAccess) @@ -400,8 +400,8 @@ object Denotations { def suchThat(p: Symbol => Boolean): SingleDenotation = if (p(symbol)) this else NoDenotation - def hasAltWith(p: Symbol => Boolean): Boolean = - p(symbol) + def hasAltWith(p: SingleDenotation => Boolean): Boolean = + p(this) def accessibleFrom(pre: Type, superAccess: Boolean)(implicit ctx: Context): Denotation = if (symbol isAccessibleFrom (pre, superAccess)) this else NoDenotation diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 621023ab7..06544d0ed 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -524,20 +524,23 @@ object SymDenotations { * and which is also defined in the same scope and compilation unit. * NoSymbol if this module does not exist. */ - final def companionModule(implicit ctx: Context): Symbol = { - owner.info.decl(name.stripModuleClassSuffix.toTermName) - .suchThat(sym => (sym is Module) && sym.isCoDefinedWith(symbol)) - .symbol - } + final def companionModule(implicit ctx: Context): Symbol = + if (owner.exists) + owner.info.decl(name.stripModuleClassSuffix.toTermName) + .suchThat(sym => (sym is Module) && sym.isCoDefinedWith(symbol)) + .symbol + else NoSymbol /** The class with the same (type-) name as this module or module class, * and which is also defined in the same scope and compilation unit. * NoSymbol if this class does not exist. */ final def companionClass(implicit ctx: Context): Symbol = - owner.info.decl(name.stripModuleClassSuffix.toTypeName) - .suchThat(sym => sym.isClass && sym.isCoDefinedWith(symbol)) - .symbol + if (owner.exists) + owner.info.decl(name.stripModuleClassSuffix.toTypeName) + .suchThat(sym => sym.isClass && sym.isCoDefinedWith(symbol)) + .symbol + else NoSymbol /** If this is a class, the module class of its companion object. * If this is a module class, its companion class. diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 17204bf1c..3cf15479d 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -138,6 +138,8 @@ class TypeComparer(implicit val ctx: Context) extends DotClass { } case tp2: AnnotatedType => isSubType(tp1, tp2.tpe) // todo: refine? + case tp2: ProtoType => + tp2.isMatchedBy(tp1) case ErrorType => true case _ => @@ -184,7 +186,8 @@ class TypeComparer(implicit val ctx: Context) extends DotClass { case tp2: RefinedType => isSubType(tp1, tp2.parent) && ( tp2.refinedName == nme.WILDCARD || - tp2.matchesInfo(tp1.member(tp2.refinedName).info)) + tp1.member(tp2.refinedName).hasAltWith(alt => + isSubType(alt.info, tp2.refinedInfo))) case AndType(tp21, tp22) => isSubType(tp1, tp21) && isSubType(tp1, tp22) case OrType(tp21, tp22) => diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index e263cf076..6afd4e92d 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1130,6 +1130,11 @@ object Types { */ trait BindingType extends Type + /** A trait for proto-types, used as expected types in typer */ + trait ProtoType extends UncachedGroundType { + def isMatchedBy(tp: Type)(implicit ctx: Context): Boolean + } + // --- NamedTypes ------------------------------------------------------------------ /** A NamedType of the form Prefix # name */ @@ -1952,8 +1957,8 @@ object Types { if (annots.isEmpty) underlying else (underlying /: annots)((tp, ann) => AnnotatedType(ann, tp)) } - // Special type objects and classes ----------------------------------------------------- + // Special type objects and classes ----------------------------------------------------- /** The type of an import clause tree */ case class ImportType(expr: Tree) extends UncachedGroundType @@ -2222,7 +2227,7 @@ object Types { /** A filter for names of deferred term definitions of a given type */ object abstractTermNameFilter extends NameFilter { def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean = - name.isTermName && (pre member name).hasAltWith(_ is Deferred) + name.isTermName && (pre member name).hasAltWith(_.symbol is Deferred) } object typeNameFilter extends NameFilter { @@ -2235,7 +2240,7 @@ object Types { object implicitFilter extends NameFilter { def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean = - (pre member name).hasAltWith(_ is Implicit) + (pre member name).hasAltWith(_.symbol is Implicit) } // ----- Exceptions ------------------------------------------------------------- diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index 9f7956203..b98ea5dc9 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -163,11 +163,11 @@ trait Implicits { self: Typer => import tpd._ - override def viewExists(from: Type, to: Type)(implicit ctx: Context): Boolean = ( - !from.isError - && !to.isError - && ctx.implicitsEnabled - && inferView(dummyTreeOfType(from), to) != EmptyTree + override def viewExists(from: Type, to: Type)(implicit ctx: Context): Boolean = !( + from.isError + || to.isError + || (ctx.mode is Mode.ImplicitsDisabled) + || (inferView(dummyTreeOfType(from), to) eq EmptyTree) ) /** Find an implicit conversion to apply to given tree `from` so that the diff --git a/src/dotty/tools/dotc/typer/ImportInfo.scala b/src/dotty/tools/dotc/typer/ImportInfo.scala index 1b8cd115d..89ffc1f29 100644 --- a/src/dotty/tools/dotc/typer/ImportInfo.scala +++ b/src/dotty/tools/dotc/typer/ImportInfo.scala @@ -7,6 +7,7 @@ import ast.Trees._ import core._ import util.SimpleMap import Symbols._, Names._, Denotations._, Types._, Contexts._, StdNames._, Flags._ +import typer.ErrorReporting.InfoString object ImportInfo { /** The import info for a root import from given symbol `sym` */ @@ -87,4 +88,14 @@ class ImportInfo(val sym: Symbol, val selectors: List[untpd.Tree], val rootImpor denot <- pre.member(name).altsWith(_ is Implicit) } yield TermRef(pre, name) withDenot denot } + + override def toString = { + val siteStr = site.show + val exprStr = if (siteStr endsWith ".type") siteStr dropRight 5 else siteStr + val selectorStr = selectors match { + case Ident(name) :: Nil => name.show + case _ => "{...}" + } + i"import $exprStr.$selectorStr" + } } \ No newline at end of file diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index abdc041fa..cdcf43272 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -224,7 +224,7 @@ class Typer extends Namer with Applications with Implicits { * or defined in */ def bindingString(prec: Int, whereFound: Context, qualifier: String = "") = - if (prec == wildImport || prec == namedImport) i"imported$qualifier by ${whereFound.tree}" + if (prec == wildImport || prec == namedImport) i"imported$qualifier by ${whereFound.importInfo}" else i"defined$qualifier in ${whereFound.owner}" /** Check that any previously found result from an inner context @@ -254,10 +254,11 @@ class Typer extends Namer with Applications with Implicits { tree.pos) found } + val Name = name.toTermName selectors match { - case Pair(Ident(from), Ident(`name`)) :: rest => + case Pair(Ident(from), Ident(Name)) :: rest => checkUnambiguous(selectionType(site, name, tree.pos)) - case Ident(`name`) :: rest => + case Ident(Name) :: rest => checkUnambiguous(selectionType(site, name, tree.pos)) case _ :: rest => namedImportRef(site, rest) @@ -305,6 +306,7 @@ class Typer extends Namer with Applications with Implicits { } } val curImport = ctx.importInfo + if (curImport != null && curImport.rootImport && previous.exists) return previous if (prevPrec < namedImport && (curImport ne outer.importInfo)) { val namedImp = namedImportRef(curImport.site, curImport.selectors) if (namedImp.exists) @@ -1033,23 +1035,24 @@ class Typer extends Namer with Applications with Implicits { err.typeMismatch(tree, pt) } - tree.tpe.widen match { - case ref: TermRef => - adaptOverloaded(ref) - case poly: PolyType => - if (pt.isInstanceOf[PolyProtoType]) tree - else { - val tracked = ctx.track(poly) - val tvars = ctx.newTypeVars(tracked, tree.pos) - adapt(tpd.TypeApply(tree, tvars map (tpd.TypeTree(_))), pt) - } - case NoType if tree.isInstanceOf[WithoutType[_]] => - tree - case tp => - pt match { - case pt: FunProtoType => adaptToArgs(tp, pt) - case _ => adaptNoArgs(tp) - } + tree match { + case _: MemberDef | _: PackageDef | _: Import | _: WithoutType[_] => tree + case _ => tree.tpe.widen match { + case ref: TermRef => + adaptOverloaded(ref) + case poly: PolyType => + if (pt.isInstanceOf[PolyProtoType]) tree + else { + val tracked = ctx.track(poly) + val tvars = ctx.newTypeVars(tracked, tree.pos) + adapt(tpd.TypeApply(tree, tvars map (tpd.TypeTree(_))), pt) + } + case tp => + pt match { + case pt: FunProtoType => adaptToArgs(tp, pt) + case _ => adaptNoArgs(tp) + } + } } } } \ No newline at end of file -- cgit v1.2.3