From 0a86c0ae8668070f62df25c7a4ba12369f23b216 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 23 Jul 2013 15:18:32 +0200 Subject: Added scheme to disabled implicit imports (not just Predef) if an explicit one is given for the same package or object. --- src/dotty/tools/dotc/core/Definitions.scala | 2 ++ src/dotty/tools/dotc/typer/ImportInfo.scala | 9 +++++-- src/dotty/tools/dotc/typer/Namer.scala | 2 +- src/dotty/tools/dotc/typer/Typer.scala | 37 ++++++++++++++++++++++++----- 4 files changed, 41 insertions(+), 9 deletions(-) (limited to 'src/dotty/tools/dotc') diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 6bd27590c..41d032f7a 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -303,6 +303,8 @@ class Definitions(implicit ctx: Context) { lazy val asInstanceOfMethods = Set[Symbol](Any_asInstanceOf, Object_asInstanceOf) lazy val isInstanceOfMethods = Set[Symbol](Any_isInstanceOf, Object_isInstanceOf) + lazy val RootImports = Set[Symbol](PredefModule, ScalaPackageVal, JavaLangPackageVal) + // ----- Higher kinds machinery ------------------------------------------ private var _hkTraits: Set[Symbol] = Set() diff --git a/src/dotty/tools/dotc/typer/ImportInfo.scala b/src/dotty/tools/dotc/typer/ImportInfo.scala index 1a720f9d1..50455e97f 100644 --- a/src/dotty/tools/dotc/typer/ImportInfo.scala +++ b/src/dotty/tools/dotc/typer/ImportInfo.scala @@ -8,8 +8,13 @@ import core._ import util.SimpleMap import Symbols._, Names._, Denotations._, Types._, Contexts._, StdNames._, Flags._ -/** Info relating to an import clause */ -case class ImportInfo(sym: Symbol, selectors: List[untpd.Tree])(implicit ctx: Context) { +/** Info relating to an import clause + * @param sym The import symbol defined by the clause + * @param selectors The selector clauses + * @param rootImport true if this is one of the implicit imports of scala, java.lang + * or Predef in the start context, false otherwise. + */ +class ImportInfo(val sym: Symbol, val selectors: List[untpd.Tree], val rootImport: Boolean = false)(implicit ctx: Context) { /** The (TermRef) type of the qualifier of the import clause */ def site(implicit ctx: Context): Type = { diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 529e48080..0b6aa3c9e 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -135,7 +135,7 @@ class Namer { typer: Typer => /** A new context that summarizes an import statement */ def importContext(sym: Symbol, selectors: List[Tree])(implicit ctx: Context) = - ctx.fresh.withImportInfo(ImportInfo(sym, selectors)) + ctx.fresh.withImportInfo(new ImportInfo(sym, selectors)) /** A new context for the interior of a class */ def inClassContext(cls: ClassSymbol, selfName: TermName)(implicit ctx: Context): Context = { diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 8d936743f..f99c08ecb 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -53,6 +53,12 @@ class Typer extends Namer with Applications with Implicits { import tpd._ import Typer._ + /** A temporary data item valid for a single typed ident: + * The set of all root import symbols that have been + * encountered as a qualifier of an import so far. + */ + private var importedFromRoot: Set[Symbol] = Set() + def typedSelection(site: Type, name: Name, pos: Position)(implicit ctx: Context): Type = { val ref = site.member(name) if (ref.exists) NamedType(site, name).withDenot(ref) @@ -99,6 +105,18 @@ class Typer extends Namer with Applications with Implicits { def typedIdent(tree: untpd.Ident)(implicit ctx: Context): Tree = { val name = tree.name + /** Is this import a root import that has been shadowed by an explicit + * import in the same program? + */ + def isDisabled(imp: ImportInfo, site: Type): Boolean = { + val qualSym = site.termSymbol + if (defn.RootImports contains qualSym) { + if (imp.rootImport && (importedFromRoot contains qualSym)) return true + importedFromRoot += qualSym + } + false + } + /** Does this identifier appear as a constructor of a pattern? */ def isPatternConstr = if (ctx.mode.isExpr && (ctx.outer.mode is Mode.Pattern)) @@ -181,14 +199,16 @@ class Typer extends Namer with Applications with Implicits { /** The type representing a wildcard import with enclosing name when imported * from given import info */ - def wildImportRef(imp: ImportInfo): Type = + def wildImportRef(imp: ImportInfo): Type = { if (imp.wildcardImport && !(imp.excluded contains name.toTermName)) { val pre = imp.site - val denot = pre.member(name) - if (denot.exists) return NamedType(pre, name).withDenot(denot) - else NoType + if (!isDisabled(imp, pre)) { + val denot = pre.member(name) + if (denot.exists) return NamedType(pre, name).withDenot(denot) + } } - else NoType + NoType + } /** Is (some alternative of) the given predenotation `denot` * defined in current compilation unit? @@ -232,8 +252,13 @@ class Typer extends Namer with Applications with Implicits { // begin typedIdent val startingContext = // ignore current variable scope in patterns to enforce linearity if (ctx.mode is Mode.Pattern) ctx.outer else ctx + val saved = importedFromRoot + importedFromRoot = Set() - val rawType = findRef(NoType, BindingPrec.nothingBound, NoContext) + val rawType = + try findRef(NoType, BindingPrec.nothingBound, NoContext) + finally importedFromRoot = saved + val ownType = if (rawType.exists) checkAccessible(rawType, superAccess = false, tree.pos) else { -- cgit v1.2.3