aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/typer/ImportInfo.scala8
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala41
-rw-r--r--test/dotc/tests.scala3
-rw-r--r--tests/neg/typedIdents.scala34
-rw-r--r--tests/pos/typedIdents.scala34
5 files changed, 98 insertions, 22 deletions
diff --git a/src/dotty/tools/dotc/typer/ImportInfo.scala b/src/dotty/tools/dotc/typer/ImportInfo.scala
index 14e2980d5..9942e1915 100644
--- a/src/dotty/tools/dotc/typer/ImportInfo.scala
+++ b/src/dotty/tools/dotc/typer/ImportInfo.scala
@@ -15,7 +15,7 @@ object ImportInfo {
val expr = tpd.Ident(sym.valRef)
val selectors = untpd.Ident(nme.WILDCARD) :: Nil
val imp = tpd.Import(expr, selectors)
- new ImportInfo(imp.symbol, selectors, rootImport = true)
+ new ImportInfo(imp.symbol, selectors, isRootImport = true)
}
}
@@ -25,7 +25,7 @@ object ImportInfo {
* @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) {
+class ImportInfo(val sym: Symbol, val selectors: List[untpd.Tree], val isRootImport: Boolean = false)(implicit ctx: Context) {
/** The (TermRef) type of the qualifier of the import clause */
def site(implicit ctx: Context): Type = {
@@ -43,7 +43,7 @@ class ImportInfo(val sym: Symbol, val selectors: List[untpd.Tree], val rootImpor
def originals: Set[TermName] = { ensureInitialized(); myOriginals }
/** Does the import clause end with wildcard? */
- def wildcardImport = { ensureInitialized(); myWildcardImport }
+ def isWildcardImport = { ensureInitialized(); myWildcardImport }
private var myExcluded: Set[TermName] = null
private var myMapped: SimpleMap[TermName, TermName] = null
@@ -78,7 +78,7 @@ class ImportInfo(val sym: Symbol, val selectors: List[untpd.Tree], val rootImpor
/** The implicit references imported by this import clause */
def importedImplicits: List[TermRef] = {
val pre = site
- if (wildcardImport) {
+ if (isWildcardImport) {
val refs = pre.implicitMembers
if (excluded.isEmpty) refs
else refs filterNot (ref => excluded contains ref.name.toTermName)
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index b6c8bc9e8..2abea02cb 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -72,12 +72,12 @@ class Typer extends Namer with Applications with Implicits {
*/
private var importedFromRoot: Set[Symbol] = Set()
- /** A denotation exists really if it exists and does not point to a stale symbol. */
- def reallyExists(denot: Denotation)(implicit ctx: Context): Boolean =
- denot.exists && {
- val sym = denot.symbol
- (sym eq NoSymbol) || !sym.isAbsent
- }
+ /** A denotation exists really if it exists and does not point to a stale symbol. */
+ def reallyExists(denot: Denotation)(implicit ctx: Context): Boolean =
+ denot.exists && {
+ val sym = denot.symbol
+ (sym eq NoSymbol) || !sym.isAbsent
+ }
/** The type of a selection with `name` of a tree with type `site`.
*/
@@ -158,11 +158,12 @@ class Typer extends Namer with Applications with Implicits {
NoSymbol
}
- /** Attribute an identifier consisting of a simple name.
+ /** Attribute an identifier consisting of a simple name or wildcard
*
* @param tree The tree representing the identifier.
* Transformations: (1) Prefix class members with this.
* (2) Change imported symbols to selections.
+ * (3) Change pattern Idents id (but not wildcards) to id @ _
*/
def typedIdent(tree: untpd.Ident, pt: Type)(implicit ctx: Context): Tree = track("typedIdent") {
val name = tree.name
@@ -178,7 +179,7 @@ class Typer extends Namer with Applications with Implicits {
def isDisabled(imp: ImportInfo, site: Type): Boolean = {
val qualSym = site.termSymbol
if (defn.RootImports contains qualSym) {
- if (imp.rootImport && (importedFromRoot contains qualSym)) return true
+ if (imp.isRootImport && (importedFromRoot contains qualSym)) return true
importedFromRoot += qualSym
}
false
@@ -227,13 +228,18 @@ class Typer extends Namer with Applications with Implicits {
*/
def checkNewOrShadowed(found: Type, newPrec: Int): Type =
if (!previous.exists || (previous == found)) found
+ else if (newPrec == definition && (prevCtx.scope eq ctx.scope)) {
+ // special case: definitions beat imports if both are in contexts with same scope
+ found
+ }
else {
- if (!previous.isError && !found.isError)
+ if (!previous.isError && !found.isError) {
error(
i"""reference to $name is ambiguous;
|it is both ${bindingString(newPrec, ctx, "")}
|and ${bindingString(prevPrec, prevCtx, " subsequently")}""".stripMargin,
tree.pos)
+ }
previous
}
@@ -243,9 +249,8 @@ class Typer extends Namer with Applications with Implicits {
def namedImportRef(site: Type, selectors: List[untpd.Tree]): Type = {
def checkUnambiguous(found: Type) = {
val other = namedImportRef(site, selectors.tail)
- if (other.exists && (found != other))
- error(i"""reference to $name is ambiguous; it is imported twice in
- |${ctx.tree}""".stripMargin,
+ if (other.exists && found.exists && (found != other))
+ error(i"reference to $name is ambiguous; it is imported twice in ${ctx.tree}",
tree.pos)
found
}
@@ -266,7 +271,7 @@ class Typer extends Namer with Applications with Implicits {
* from given import info
*/
def wildImportRef(imp: ImportInfo): Type = {
- if (imp.wildcardImport && !(imp.excluded contains name.toTermName)) {
+ if (imp.isWildcardImport && !(imp.excluded contains name.toTermName)) {
val pre = imp.site
if (!isDisabled(imp, pre)) {
val denot = pre.member(name)
@@ -300,7 +305,7 @@ class Typer extends Namer with Applications with Implicits {
}
}
val curImport = ctx.importInfo
- if (curImport != null && curImport.rootImport && previous.exists) return previous
+ if (curImport != null && curImport.isRootImport && previous.exists) return previous
if (prevPrec < namedImport && (curImport ne outer.importInfo)) {
val namedImp = namedImportRef(curImport.site, curImport.selectors)
if (namedImp.exists)
@@ -316,8 +321,8 @@ class Typer extends Namer with Applications with Implicits {
}
// begin typedIdent
- def kind = if (name.isTermName) "term" else "type" // !!! DEBUG
- println(s"typed ident $kind $name in ${ctx.owner}")
+ def kind = if (name.isTermName) "" else "type "
+ println(s"typed ident $kind$name in ${ctx.owner}") // !!! DEBUG
if (ctx.mode is Mode.Pattern) {
if (name == nme.WILDCARD)
return tree.withType(pt)
@@ -326,7 +331,7 @@ class Typer extends Namer with Applications with Implicits {
}
val saved = importedFromRoot
- importedFromRoot = Set()
+ importedFromRoot = Set.empty
val rawType =
try findRef(NoType, BindingPrec.nothingBound, NoContext)
@@ -337,7 +342,7 @@ class Typer extends Namer with Applications with Implicits {
if (rawType.exists)
checkAccessible(rawType, superAccess = false, tree.pos)
else {
- error(i"not found: $name", tree.pos)
+ error(i"not found: $kind$name", tree.pos)
ErrorType
}
tree.withType(ownType.underlyingIfRepeated)
diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala
index 72c708363..eb7aede1c 100644
--- a/test/dotc/tests.scala
+++ b/test/dotc/tests.scala
@@ -26,7 +26,10 @@ class tests extends CompilerTest {
@Test def pos_nameddefaults() = compileFile(posDir, "nameddefaults")
@Test def pos_desugar() = compileFile(posDir, "desugar")
@Test def pos_sigs() = compileFile(posDir, "sigs")
+ @Test def pos_typers() = compileFile(posDir, "typers")
+ @Test def pos_typedidents() = compileFile(posDir, "typedidents")
@Test def neg_blockescapes() = compileFile(negDir, "blockescapesNeg", xerrors = 2)
@Test def neg_typedapply() = compileFile(negDir, "typedapply", xerrors = 4)
+ @Test def neg_typedidents() = compileFile(negDir, "typedidents", xerrors = 2)
} \ No newline at end of file
diff --git a/tests/neg/typedIdents.scala b/tests/neg/typedIdents.scala
new file mode 100644
index 000000000..b664da42d
--- /dev/null
+++ b/tests/neg/typedIdents.scala
@@ -0,0 +1,34 @@
+package P {
+ object X { val x = 1; val y = 2 }
+}
+package Q {
+ object X { val x = true; val y = "" }
+}
+package P { // `X' bound by package clause
+ import Console._ // `println' bound by wildcard import
+ object A {
+ println("L4: " + X) // `X' refers to `P.X' here
+ object B {
+ import Q._ // `X' bound by wildcard import
+ println("L7: " + X) // `X' refers to `Q.X' here
+ import X._ // `x' and `y' bound by wildcard import
+ println("L8: " + x) // `x' refers to `Q.X.x' here
+ object C {
+ val x = 3 // `x' bound by local definition
+ println("L12: " + x) // `x' refers to constant `3' here
+ locally {
+ import Q.X._ // `x' and `y' bound by wildcard import
+ println("L14: "+x) // reference to `x' is ambiguous here
+ import X.y // `y' bound by explicit import
+ println("L16: " + y) // `y' refers to `Q.X.y' here
+ locally {
+ import P.X._ // `x' and `y' bound by wildcard import
+ val x = "abc" // `x' bound by local definition
+ println("L19: "+y) // reference to `y' is ambiguous here
+ println("L20: " + x) // `x' refers to string ``abc'' here
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/pos/typedIdents.scala b/tests/pos/typedIdents.scala
new file mode 100644
index 000000000..f6c88379b
--- /dev/null
+++ b/tests/pos/typedIdents.scala
@@ -0,0 +1,34 @@
+package P {
+ object X { val x = 1; val y = 2 }
+}
+package Q {
+ object X { val x = true; val y = "" }
+}
+package P { // `X' bound by package clause
+ import Console._ // `println' bound by wildcard import
+ object A {
+ println("L4: " + X) // `X' refers to `P.X' here
+ object B {
+ import Q._ // `X' bound by wildcard import
+ println("L7: " + X) // `X' refers to `Q.X' here
+ import X._ // `x' and `y' bound by wildcard import
+ println("L8: " + x) // `x' refers to `Q.X.x' here
+ object C {
+ val x = 3 // `x' bound by local definition
+ println("L12: " + x) // `x' refers to constant `3' here
+ locally {
+ import Q.X._ // `x' and `y' bound by wildcard import
+ // println("L14: "+x) // reference to `x' is ambiguous here
+ import X.y // `y' bound by explicit import
+ println("L16: " + y) // `y' refers to `Q.X.y' here
+ locally {
+ val x = "abc" // `x' bound by local definition
+ import P.X._ // `x' and `y' bound by wildcard import
+ // println("L19: "+y) // reference to `y' is ambiguous here
+ println("L20: " + x) // `x' refers to string ``abc'' here
+ }
+ }
+ }
+ }
+ }
+} \ No newline at end of file