aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/src/dotty/tools/dotc/ast/Trees.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/Contexts.scala20
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala7
-rw-r--r--compiler/src/dotty/tools/dotc/core/Phases.scala5
-rw-r--r--compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala8
-rw-r--r--compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/repl/InterpreterLoop.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/typer/FrontEnd.scala11
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ImportInfo.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Namer.scala109
-rw-r--r--compiler/src/dotty/tools/dotc/typer/ReTyper.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/typer/Typer.scala108
-rw-r--r--compiler/src/dotty/tools/dotc/util/Chars.scala9
-rw-r--r--tests/neg/i1647.scala4
-rw-r--r--tests/neg/i1649.scala2
-rw-r--r--tests/neg/nopredef.scala5
17 files changed, 227 insertions, 85 deletions
diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala
index 2801bcae2..c4b2b2122 100644
--- a/compiler/src/dotty/tools/dotc/ast/Trees.scala
+++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala
@@ -32,7 +32,7 @@ object Trees {
/** Property key for trees with documentation strings attached */
val DocComment = new Property.Key[Comment]
- @sharable private var nextId = 0 // for debugging
+ @sharable private var nextId = 0 // for debugging
type LazyTree = AnyRef /* really: Tree | Lazy[Tree] */
type LazyTreeList = AnyRef /* really: List[Tree] | Lazy[List[Tree]] */
diff --git a/compiler/src/dotty/tools/dotc/core/Contexts.scala b/compiler/src/dotty/tools/dotc/core/Contexts.scala
index 639c4d111..a1b99d16d 100644
--- a/compiler/src/dotty/tools/dotc/core/Contexts.scala
+++ b/compiler/src/dotty/tools/dotc/core/Contexts.scala
@@ -216,8 +216,8 @@ object Contexts {
else if (isNonEmptyScopeContext) scope.implicitDecls
else Nil
val outerImplicits =
- if (isImportContext && importInfo.hiddenRoot.exists)
- outer.implicits exclude importInfo.hiddenRoot
+ if (isImportContext && importInfo.unimported.exists)
+ outer.implicits exclude importInfo.unimported
else
outer.implicits
if (implicitRefs.isEmpty) outerImplicits
@@ -422,9 +422,18 @@ object Contexts {
final def withOwner(owner: Symbol): Context =
if (owner ne this.owner) fresh.setOwner(owner) else this
- override def toString =
+ final def withProperty[T](key: Key[T], value: Option[T]): Context =
+ if (property(key) == value) this
+ else value match {
+ case Some(v) => fresh.setProperty(key, v)
+ case None => fresh.dropProperty(key)
+ }
+
+ override def toString = {
+ def iinfo(implicit ctx: Context) = if (ctx.importInfo == null) "" else i"${ctx.importInfo.selectors}%, %"
"Context(\n" +
- (outersIterator map ( ctx => s" owner = ${ctx.owner}, scope = ${ctx.scope}") mkString "\n")
+ (outersIterator map ( ctx => s" owner = ${ctx.owner}, scope = ${ctx.scope}, import = ${iinfo(ctx)}") mkString "\n")
+ }
}
/** A condensed context provides only a small memory footprint over
@@ -468,6 +477,9 @@ object Contexts {
def setProperty[T](key: Key[T], value: T): this.type =
setMoreProperties(moreProperties.updated(key, value))
+ def dropProperty(key: Key[_]): this.type =
+ setMoreProperties(moreProperties - key)
+
def setPhase(pid: PhaseId): this.type = setPeriod(Period(runId, pid))
def setPhase(phase: Phase): this.type = setPeriod(Period(runId, phase.start, phase.end))
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index 4b090d9b1..c5ccab261 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -650,6 +650,13 @@ class Definitions {
def isTupleClass(cls: Symbol) = isVarArityClass(cls, tpnme.Tuple)
def isProductClass(cls: Symbol) = isVarArityClass(cls, tpnme.Product)
+ val predefClassNames: Set[Name] =
+ Set("Predef$", "DeprecatedPredef", "LowPriorityImplicits").map(_.toTypeName)
+
+ /** Is `cls` the predef module class, or a class inherited by Predef? */
+ def isPredefClass(cls: Symbol) =
+ (cls.owner eq ScalaPackageClass) && predefClassNames.contains(cls.name)
+
val StaticRootImportFns = List[() => TermRef](
() => JavaLangPackageVal.termRef,
() => ScalaPackageVal.termRef
diff --git a/compiler/src/dotty/tools/dotc/core/Phases.scala b/compiler/src/dotty/tools/dotc/core/Phases.scala
index 222e2235d..6a53e1b30 100644
--- a/compiler/src/dotty/tools/dotc/core/Phases.scala
+++ b/compiler/src/dotty/tools/dotc/core/Phases.scala
@@ -26,7 +26,10 @@ trait Phases {
def phasesStack: List[Phase] =
if ((this eq NoContext) || !phase.exists) Nil
- else phase :: outersIterator.dropWhile(_.phase == phase).next.phasesStack
+ else {
+ val rest = outersIterator.dropWhile(_.phase == phase)
+ phase :: (if (rest.hasNext) rest.next.phasesStack else Nil)
+ }
/** Execute `op` at given phase */
def atPhase[T](phase: Phase)(op: Context => T): T =
diff --git a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 00627fc28..1ddf3cd6d 100644
--- a/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -614,14 +614,12 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
(sym.allOverriddenSymbols exists (_ is TypeParam))
override def toText(sym: Symbol): Text = {
- if (sym.isImport) {
- def importString(tree: untpd.Tree) = s"import ${tree.show}"
+ if (sym.isImport)
sym.infoOrCompleter match {
- case info: Namer#Completer => return importString(info.original)
- case info: ImportType => return importString(info.expr)
+ case info: Namer#Completer => return info.original.show
+ case info: ImportType => return s"import $info.expr.show"
case _ =>
}
- }
if (sym.is(ModuleClass))
kindString(sym) ~~ (nameString(sym.name.stripModuleClassSuffix) + idString(sym))
else
diff --git a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala
index f269fef64..d849ea370 100644
--- a/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala
+++ b/compiler/src/dotty/tools/dotc/repl/CompilingInterpreter.scala
@@ -6,7 +6,7 @@ import java.io.{
File, PrintWriter, PrintStream, StringWriter, Writer, OutputStream,
ByteArrayOutputStream => ByteOutputStream
}
-import java.lang.{Class, ClassLoader}
+import java.lang.{Class, ClassLoader, Thread, System, StringBuffer}
import java.net.{URL, URLClassLoader}
import scala.collection.immutable.ListSet
diff --git a/compiler/src/dotty/tools/dotc/repl/InterpreterLoop.scala b/compiler/src/dotty/tools/dotc/repl/InterpreterLoop.scala
index b3ac41c55..cfe8d892d 100644
--- a/compiler/src/dotty/tools/dotc/repl/InterpreterLoop.scala
+++ b/compiler/src/dotty/tools/dotc/repl/InterpreterLoop.scala
@@ -4,7 +4,7 @@ package repl
import java.io.{BufferedReader, File, FileReader, PrintWriter}
import java.io.IOException
-import java.lang.{ClassLoader, System}
+import java.lang.{ClassLoader, System, Thread}
import scala.concurrent.{Future, Await}
import scala.concurrent.duration.Duration
import reporting.Reporter
diff --git a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
index 714255962..331fce46a 100644
--- a/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
+++ b/compiler/src/dotty/tools/dotc/transform/CollectEntryPoints.scala
@@ -9,7 +9,6 @@ import dotty.tools.dotc.core.Symbols.NoSymbol
import scala.annotation.tailrec
import dotty.tools.dotc.core._
import Symbols._
-import scala.Some
import dotty.tools.dotc.transform.TreeTransforms.{NXTransformations, TransformerInfo, TreeTransform, TreeTransformer}
import dotty.tools.dotc.ast.tpd
import dotty.tools.dotc.core.Contexts.Context
diff --git a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala
index c444631ae..cd374e32c 100644
--- a/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala
+++ b/compiler/src/dotty/tools/dotc/typer/FrontEnd.scala
@@ -44,6 +44,12 @@ class FrontEnd extends Phase {
typr.println("entered: " + unit.source)
}
+ def enterAnnotations(implicit ctx: Context) = monitor("annotating") {
+ val unit = ctx.compilationUnit
+ ctx.typer.annotate(unit.untpdTree :: Nil)
+ typr.println("annotated: " + unit.source)
+ }
+
def typeCheck(implicit ctx: Context) = monitor("typechecking") {
val unit = ctx.compilationUnit
unit.tpdTree = ctx.typer.typedExpr(unit.untpdTree)
@@ -69,8 +75,9 @@ class FrontEnd extends Phase {
}
unitContexts foreach (parse(_))
record("parsedTrees", ast.Trees.ntrees)
- unitContexts foreach (enterSyms(_))
- unitContexts foreach (typeCheck(_))
+ unitContexts.foreach(enterSyms(_))
+ unitContexts.foreach(enterAnnotations(_))
+ unitContexts.foreach(typeCheck(_))
record("total trees after typer", ast.Trees.ntrees)
unitContexts.map(_.compilationUnit).filterNot(discardAfterTyper)
}
diff --git a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala
index 3aa289181..b4ec3390e 100644
--- a/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ImportInfo.scala
@@ -95,14 +95,22 @@ class ImportInfo(symf: => Symbol, val selectors: List[untpd.Tree], val isRootImp
/** The root import symbol hidden by this symbol, or NoSymbol if no such symbol is hidden.
* Note: this computation needs to work even for un-initialized import infos, and
* is not allowed to force initialization.
+ *
+ * TODO: Once we have fully bootstrapped, I would prefer if we expressed
+ * unimport with an `override` modifier, and generalized it to all imports.
+ * I believe this would be more transparent than the curren set of conditions. E.g.
+ *
+ * override import Predef.{any2stringAdd => _, StringAdd => _, _} // disables String +
+ * override import java.lang.{} // disables all imports
*/
- lazy val hiddenRoot: Symbol = {
- val sym = site.termSymbol
- def hasMaskingSelector = selectors exists {
+ lazy val unimported: Symbol = {
+ lazy val sym = site.termSymbol
+ val hasMaskingSelector = selectors exists {
case Thicket(_ :: Ident(nme.WILDCARD) :: Nil) => true
case _ => false
}
- if ((defn.RootImportTypes exists (_.symbol == sym)) && hasMaskingSelector) sym else NoSymbol
+ if (hasMaskingSelector && defn.RootImportTypes.exists(_.symbol == sym)) sym
+ else NoSymbol
}
override def toString = {
diff --git a/compiler/src/dotty/tools/dotc/typer/Namer.scala b/compiler/src/dotty/tools/dotc/typer/Namer.scala
index 148cf1da7..b8fe46745 100644
--- a/compiler/src/dotty/tools/dotc/typer/Namer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Namer.scala
@@ -528,18 +528,96 @@ class Namer { typer: Typer =>
}
}
- stats foreach expand
+ stats.foreach(expand)
mergeCompanionDefs()
val ctxWithStats = (ctx /: stats) ((ctx, stat) => indexExpanded(stat)(ctx))
createCompanionLinks(ctxWithStats)
ctxWithStats
}
+ /** Add all annotations of definitions in `stats` to the defined symbols */
+ def annotate(stats: List[Tree])(implicit ctx: Context): Unit = {
+ def recur(stat: Tree): Unit = stat match {
+ case pcl: PackageDef =>
+ annotate(pcl.stats)
+ case stat: untpd.MemberDef =>
+ stat.getAttachment(SymOfTree) match {
+ case Some(sym) =>
+ sym.infoOrCompleter match {
+ case info: Completer if !defn.isPredefClass(sym.owner) =>
+ // Annotate Predef methods only when they are completed;
+ // This is necessary to break a cyclic dependence between `Predef`
+ // and `deprecated` in test `compileStdLib`.
+ addAnnotations(sym, stat)(info.creationContext)
+ case _ =>
+ // Annotations were already added as part of the symbol's completion
+ }
+ case none =>
+ assert(stat.typeOpt.exists, i"no symbol for $stat")
+ }
+ case stat: untpd.Thicket =>
+ stat.trees.foreach(recur)
+ case _ =>
+ }
+
+ for (stat <- stats) recur(expanded(stat))
+ }
+
+ /** Add annotations of `stat` to `sym`.
+ * This method can be called twice on a symbol (e.g. once
+ * during the `annotate` phase and then again during completion).
+ * Therefore, care needs to be taken not to add annotations again
+ * that are already added to the symbol.
+ */
+ def addAnnotations(sym: Symbol, stat: MemberDef)(implicit ctx: Context) = {
+ // (1) The context in which an annotation of a top-level class or module is evaluated
+ // is the closest enclosing context which has the enclosing package as owner.
+ // (2) The context in which an annotation for any other symbol is evaluated is the
+ // closest enclosing context which has the owner of the class enclosing the symbol as owner.
+ // E.g in
+ //
+ // package p
+ // import a.b
+ // class C {
+ // import d.e
+ // @ann m() ...
+ // }
+ //
+ // `@ann` is evaluated in the context just outside `C`, where the `a.b`
+ // import is visible but the `d.e` import is forgotten. This measure is necessary
+ // in order to avoid cycles.
+ lazy val annotCtx = {
+ var target = sym.owner.lexicallyEnclosingClass
+ if (!target.is(PackageClass)) target = target.owner
+ var c = ctx
+ while (c.owner != target) c = c.outer
+ c
+ }
+ for (annotTree <- untpd.modsDeco(stat).mods.annotations) {
+ val cls = typedAheadAnnotation(annotTree)(annotCtx)
+ if (sym.unforcedAnnotation(cls).isEmpty) {
+ val ann = Annotation.deferred(cls, implicit ctx => typedAnnotation(annotTree))
+ sym.addAnnotation(ann)
+ if (cls == defn.InlineAnnot && sym.is(Method, butNot = Accessor))
+ sym.setFlag(Inline)
+ }
+ }
+ }
+
+ def indexAndAnnotate(stats: List[Tree])(implicit ctx: Context): Context = {
+ val localCtx = index(stats)
+ annotate(stats)
+ localCtx
+ }
+
/** The completer of a symbol defined by a member def or import (except ClassSymbols) */
class Completer(val original: Tree)(implicit ctx: Context) extends LazyType {
protected def localContext(owner: Symbol) = ctx.fresh.setOwner(owner).setTree(original)
+ /** The context with which this completer was created */
+ def creationContext = ctx
+
protected def typeSig(sym: Symbol): Type = original match {
case original: ValDef =>
if (sym is Module) moduleValSig(sym)
@@ -572,19 +650,6 @@ class Namer { typer: Typer =>
completeInCreationContext(denot)
}
- protected def addAnnotations(denot: SymDenotation): Unit = original match {
- case original: untpd.MemberDef =>
- var hasInlineAnnot = false
- for (annotTree <- untpd.modsDeco(original).mods.annotations) {
- val cls = typedAheadAnnotation(annotTree)
- val ann = Annotation.deferred(cls, implicit ctx => typedAnnotation(annotTree))
- denot.addAnnotation(ann)
- if (cls == defn.InlineAnnot && denot.is(Method, butNot = Accessor))
- denot.setFlag(Inline)
- }
- case _ =>
- }
-
private def addInlineInfo(denot: SymDenotation) = original match {
case original: untpd.DefDef if denot.isInlineMethod =>
Inliner.registerInlineInfo(
@@ -598,7 +663,10 @@ class Namer { typer: Typer =>
* to pick up the context at the point where the completer was created.
*/
def completeInCreationContext(denot: SymDenotation): Unit = {
- addAnnotations(denot)
+ original match {
+ case original: MemberDef => addAnnotations(denot.symbol, original)
+ case _ =>
+ }
addInlineInfo(denot)
denot.info = typeSig(denot.symbol)
Checking.checkWellFormed(denot.symbol)
@@ -742,7 +810,7 @@ class Namer { typer: Typer =>
ok
}
- addAnnotations(denot)
+ addAnnotations(denot.symbol, original)
val selfInfo =
if (self.isEmpty) NoType
@@ -765,9 +833,10 @@ class Namer { typer: Typer =>
// accessors, that's why the constructor needs to be completed before
// the parent types are elaborated.
index(constr)
+ annotate(constr :: params)
symbolOfTree(constr).ensureCompleted()
- index(rest)(inClassContext(selfInfo))
+ indexAndAnnotate(rest)(inClassContext(selfInfo))
val tparamAccessors = decls.filter(_ is TypeParamAccessor).toList
val parentTypes = ensureFirstIsClass(parents.map(checkedParentType(_, tparamAccessors)))
@@ -790,7 +859,7 @@ class Namer { typer: Typer =>
case Some(ttree) => ttree
case none =>
val ttree = typer.typed(tree, pt)
- xtree.pushAttachment(TypedAhead, ttree)
+ xtree.putAttachment(TypedAhead, ttree)
ttree
}
}
@@ -810,7 +879,7 @@ class Namer { typer: Typer =>
/** Enter and typecheck parameter list */
def completeParams(params: List[MemberDef])(implicit ctx: Context) = {
- index(params)
+ indexAndAnnotate(params)
for (param <- params) typedAheadExpr(param)
}
@@ -990,7 +1059,7 @@ class Namer { typer: Typer =>
// 3. Info of CP is computed (to be copied to DP).
// 4. CP is completed.
// 5. Info of CP is copied to DP and DP is completed.
- index(tparams)
+ indexAndAnnotate(tparams)
if (isConstructor) sym.owner.typeParams.foreach(_.ensureCompleted())
for (tparam <- tparams) typedAheadExpr(tparam)
diff --git a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
index 2413c0c22..f0acdef12 100644
--- a/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
+++ b/compiler/src/dotty/tools/dotc/typer/ReTyper.scala
@@ -72,6 +72,7 @@ class ReTyper extends Typer {
override def localTyper(sym: Symbol) = this
override def index(trees: List[untpd.Tree])(implicit ctx: Context) = ctx
+ override def annotate(trees: List[untpd.Tree])(implicit ctx: Context) = ()
override def tryInsertApplyOrImplicit(tree: Tree, pt: ProtoType)(fallBack: (Tree, TyperState) => Tree)(implicit ctx: Context): Tree =
fallBack(tree, ctx.typerState)
diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala
index ccc74cfff..4ec1c460f 100644
--- a/compiler/src/dotty/tools/dotc/typer/Typer.scala
+++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala
@@ -27,7 +27,7 @@ import EtaExpansion.etaExpand
import dotty.tools.dotc.transform.Erasure.Boxing
import util.Positions._
import util.common._
-import util.SourcePosition
+import util.{SourcePosition, Property}
import collection.mutable
import annotation.tailrec
import Implicits._
@@ -57,6 +57,8 @@ object Typer {
def assertPositioned(tree: untpd.Tree)(implicit ctx: Context) =
if (!tree.isEmpty && !tree.isInstanceOf[untpd.TypedSplice] && ctx.typerState.isGlobalCommittable)
assert(tree.pos.exists, s"position not set for $tree # ${tree.uniqueId}")
+
+ private val ExprOwner = new Property.Key[Symbol]
}
class Typer extends Namer with TypeAssigner with Applications with Implicits with Dynamic with Checking with Docstrings {
@@ -74,7 +76,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
* Note: It would be more proper to move importedFromRoot into typedIdent.
* We should check that this has no performance degradation, however.
*/
- private var importedFromRoot: Set[Symbol] = Set()
+ private var unimported: Set[Symbol] = Set()
/** Temporary data item for single call to typed ident:
* This symbol would be found under Scala2 mode, but is not
@@ -102,15 +104,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
*/
def error(msg: => Message, pos: Position) = ctx.error(msg, pos)
- /** 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 = {
- if (imp.isRootImport && (importedFromRoot contains site.termSymbol)) return true
- if (imp.hiddenRoot.exists) importedFromRoot += imp.hiddenRoot
- false
- }
-
/** Does this identifier appear as a constructor of a pattern? */
def isPatternConstr =
if (ctx.mode.isExpr && (ctx.outer.mode is Mode.Pattern))
@@ -188,32 +181,44 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
/** The type representing a named import with enclosing name when imported
* from given `site` and `selectors`.
*/
- def namedImportRef(site: Type, selectors: List[untpd.Tree])(implicit ctx: Context): Type = {
- def checkUnambiguous(found: Type) = {
- val other = namedImportRef(site, selectors.tail)
- if (other.exists && found.exists && (found != other))
- error(em"reference to `$name` is ambiguous; it is imported twice in ${ctx.tree}",
- tree.pos)
- found
- }
+ def namedImportRef(imp: ImportInfo)(implicit ctx: Context): Type = {
val Name = name.toTermName.decode
- selectors match {
+ def recur(selectors: List[untpd.Tree]): Type = selectors match {
case selector :: rest =>
+ def checkUnambiguous(found: Type) = {
+ val other = recur(selectors.tail)
+ if (other.exists && found.exists && (found != other))
+ error(em"reference to `$name` is ambiguous; it is imported twice in ${ctx.tree}",
+ tree.pos)
+ found
+ }
+
+ def selection(name: Name) =
+ if (imp.sym.isCompleting) {
+ ctx.warning(i"cyclic ${imp.sym}, ignored", tree.pos)
+ NoType
+ }
+ else if (unimported.nonEmpty && unimported.contains(imp.site.termSymbol))
+ NoType
+ else {
+ // Pass refctx so that any errors are reported in the context of the
+ // reference instead of the
+ checkUnambiguous(selectionType(imp.site, name, tree.pos)(refctx))
+ }
+
selector match {
case Thicket(fromId :: Ident(Name) :: _) =>
val Ident(from) = fromId
- val selName = if (name.isTypeName) from.toTypeName else from
- // Pass refctx so that any errors are reported in the context of the
- // reference instead of the context of the import.
- checkUnambiguous(selectionType(site, selName, tree.pos)(refctx))
+ selection(if (name.isTypeName) from.toTypeName else from)
case Ident(Name) =>
- checkUnambiguous(selectionType(site, name, tree.pos)(refctx))
+ selection(name)
case _ =>
- namedImportRef(site, rest)
+ recur(rest)
}
case nil =>
NoType
}
+ recur(imp.selectors)
}
/** The type representing a wildcard import with enclosing name when imported
@@ -222,7 +227,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def wildImportRef(imp: ImportInfo)(implicit ctx: Context): Type = {
if (imp.isWildcardImport) {
val pre = imp.site
- if (!isDisabled(imp, pre) && !(imp.excluded contains name.toTermName) && name != nme.CONSTRUCTOR) {
+ if (!unimported.contains(pre.termSymbol) &&
+ !imp.excluded.contains(name.toTermName) &&
+ name != nme.CONSTRUCTOR) {
val denot = pre.member(name).accessibleFrom(pre)(refctx)
if (reallyExists(denot)) return pre.select(name, denot)
}
@@ -279,19 +286,27 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
if (result.exists) result
else { // find import
val curImport = ctx.importInfo
+ def updateUnimported() =
+ if (curImport.unimported.exists) unimported += curImport.unimported
if (ctx.owner.is(Package) && curImport != null && curImport.isRootImport && previous.exists)
previous // no more conflicts possible in this case
- else if (isPossibleImport(namedImport) && (curImport ne outer.importInfo) && !curImport.sym.isCompleting) {
- val namedImp = namedImportRef(curImport.site, curImport.selectors)
+ else if (isPossibleImport(namedImport) && (curImport ne outer.importInfo)) {
+ val namedImp = namedImportRef(curImport)
if (namedImp.exists)
findRef(checkNewOrShadowed(namedImp, namedImport), namedImport, ctx)(outer)
- else if (isPossibleImport(wildImport)) {
+ else if (isPossibleImport(wildImport) && !curImport.sym.isCompleting) {
val wildImp = wildImportRef(curImport)
if (wildImp.exists)
findRef(checkNewOrShadowed(wildImp, wildImport), wildImport, ctx)(outer)
- else loop(outer)
+ else {
+ updateUnimported()
+ loop(outer)
+ }
+ }
+ else {
+ updateUnimported()
+ loop(outer)
}
- else loop(outer)
}
else loop(outer)
}
@@ -311,11 +326,10 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
return typed(desugar.patternVar(tree), pt)
}
-
val rawType = {
- val saved1 = importedFromRoot
+ val saved1 = unimported
val saved2 = foundUnderScala2
- importedFromRoot = Set.empty
+ unimported = Set.empty
foundUnderScala2 = NoType
try {
var found = findRef(NoType, BindingPrec.nothingBound, NoContext)
@@ -329,7 +343,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
found
}
finally {
- importedFromRoot = saved1
+ unimported = saved1
foundUnderScala2 = saved2
}
}
@@ -576,7 +590,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
}
def typedBlockStats(stats: List[untpd.Tree])(implicit ctx: Context): (Context, List[tpd.Tree]) =
- (index(stats), typedStats(stats, ctx.owner))
+ (indexAndAnnotate(stats), typedStats(stats, ctx.owner))
def typedBlock(tree: untpd.Block, pt: Type)(implicit ctx: Context) = track("typedBlock") {
val (exprCtx, stats1) = typedBlockStats(tree.stats)
@@ -1058,7 +1072,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedPolyTypeTree(tree: untpd.PolyTypeTree)(implicit ctx: Context): Tree = track("typedPolyTypeTree") {
val PolyTypeTree(tparams, body) = tree
- index(tparams)
+ indexAndAnnotate(tparams)
val tparams1 = tparams.mapconserve(typed(_).asInstanceOf[TypeDef])
val body1 = typedType(tree.body)
assignType(cpy.PolyTypeTree(tree)(tparams1, body1), tparams1, body1)
@@ -1121,7 +1135,17 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def completeAnnotations(mdef: untpd.MemberDef, sym: Symbol)(implicit ctx: Context): Unit = {
// necessary to force annotation trees to be computed.
sym.annotations.foreach(_.ensureCompleted)
- val annotCtx = ctx.outersIterator.dropWhile(_.owner == sym).next
+ lazy val annotCtx = {
+ val c = ctx.outersIterator.dropWhile(_.owner == sym).next
+ c.property(ExprOwner) match {
+ case Some(exprOwner) if c.owner.isClass =>
+ // We need to evaluate annotation arguments in an expression context, since
+ // classes defined in a such arguments should not be entered into the
+ // enclosing class.
+ c.exprContext(mdef, exprOwner)
+ case None => c
+ }
+ }
// necessary in order to mark the typed ahead annotations as definitely typed:
untpd.modsDeco(mdef).mods.annotations.foreach(typedAnnotation(_)(annotCtx))
}
@@ -1540,7 +1564,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
case nil =>
buf.toList
}
- traverse(stats)
+ val localCtx = {
+ val exprOwnerOpt = if (exprOwner == ctx.owner) None else Some(exprOwner)
+ ctx.withProperty(ExprOwner, exprOwnerOpt)
+ }
+ traverse(stats)(localCtx)
}
/** Given an inline method `mdef`, the method rewritten so that its body
diff --git a/compiler/src/dotty/tools/dotc/util/Chars.scala b/compiler/src/dotty/tools/dotc/util/Chars.scala
index bae3b4732..6f95b87c4 100644
--- a/compiler/src/dotty/tools/dotc/util/Chars.scala
+++ b/compiler/src/dotty/tools/dotc/util/Chars.scala
@@ -6,7 +6,6 @@ package dotty.tools.dotc
package util
import scala.annotation.switch
-import java.lang.{ Character => JCharacter }
import java.lang.{Character => JCharacter}
import java.lang.Character.LETTER_NUMBER
import java.lang.Character.LOWERCASE_LETTER
@@ -66,16 +65,16 @@ object Chars {
/** Can character start an alphanumeric Scala identifier? */
def isIdentifierStart(c: Char): Boolean =
- (c == '_') || (c == '$') || Character.isUnicodeIdentifierStart(c)
+ (c == '_') || (c == '$') || JCharacter.isUnicodeIdentifierStart(c)
/** Can character form part of an alphanumeric Scala identifier? */
def isIdentifierPart(c: Char) =
- (c == '$') || Character.isUnicodeIdentifierPart(c)
+ (c == '$') || JCharacter.isUnicodeIdentifierPart(c)
/** Is character a math or other symbol in Unicode? */
def isSpecial(c: Char) = {
- val chtp = Character.getType(c)
- chtp == Character.MATH_SYMBOL.toInt || chtp == Character.OTHER_SYMBOL.toInt
+ val chtp = JCharacter.getType(c)
+ chtp == JCharacter.MATH_SYMBOL.toInt || chtp == JCharacter.OTHER_SYMBOL.toInt
}
private final val otherLetters = Set[Char]('\u0024', '\u005F') // '$' and '_'
diff --git a/tests/neg/i1647.scala b/tests/neg/i1647.scala
new file mode 100644
index 000000000..b6910cc70
--- /dev/null
+++ b/tests/neg/i1647.scala
@@ -0,0 +1,4 @@
+class ann {
+ @ann({ def baz }) // error: missing return type
+ def foo(): Unit
+}
diff --git a/tests/neg/i1649.scala b/tests/neg/i1649.scala
new file mode 100644
index 000000000..e60a2376a
--- /dev/null
+++ b/tests/neg/i1649.scala
@@ -0,0 +1,2 @@
+class Two[@A A] // error
+
diff --git a/tests/neg/nopredef.scala b/tests/neg/nopredef.scala
new file mode 100644
index 000000000..0079be41e
--- /dev/null
+++ b/tests/neg/nopredef.scala
@@ -0,0 +1,5 @@
+import Predef.{assert => _}
+
+object Test {
+ assert("asdf" == "asdf") // error: not found assert
+}