aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala2
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala21
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala27
-rw-r--r--src/dotty/tools/dotc/transform/ExplicitOuter.scala2
-rw-r--r--src/dotty/tools/dotc/typer/RefChecks.scala15
5 files changed, 31 insertions, 36 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index 2f6b6b914..6401c01c1 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -33,7 +33,7 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
}
def isOpAssign(tree: Tree) = unsplice(tree) match {
- case Apply(fn, _ :: Nil) =>
+ case Apply(fn, _ :: _) =>
unsplice(fn) match {
case Select(_, name) if name.isOpAssignmentName => true
case _ => false
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index e38de458a..defcf4838 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -326,23 +326,24 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def ref(tp: NamedType)(implicit ctx: Context): Tree =
if (tp.isType) TypeTree(tp)
else if (prefixIsElidable(tp)) Ident(tp)
+ else if (tp.symbol.is(Module) && ctx.owner.isContainedIn(tp.symbol.moduleClass))
+ followOuterLinks(This(tp.symbol.moduleClass.asClass))
else tp.prefix match {
- case pre: SingletonType =>
- val prefix =
- singleton(pre) match {
- case t: This if ctx.erasedTypes && !(t.symbol == ctx.owner.enclosingClass || t.symbol.isStaticOwner) =>
- // after erasure outer paths should be respected
- new ExplicitOuter.OuterOps(ctx).path(t.tpe.widen.classSymbol)
- case t =>
- t
- }
- prefix.select(tp)
+ case pre: SingletonType => followOuterLinks(singleton(pre)).select(tp)
case pre => SelectFromTypeTree(TypeTree(pre), tp)
} // no checks necessary
def ref(sym: Symbol)(implicit ctx: Context): Tree =
ref(NamedType(sym.owner.thisType, sym.name, sym.denot))
+ private def followOuterLinks(t: Tree)(implicit ctx: Context) = t match {
+ case t: This if ctx.erasedTypes && !(t.symbol == ctx.owner.enclosingClass || t.symbol.isStaticOwner) =>
+ // after erasure outer paths should be respected
+ new ExplicitOuter.OuterOps(ctx).path(t.tpe.widen.classSymbol)
+ case t =>
+ t
+ }
+
def singleton(tp: Type)(implicit ctx: Context): Tree = tp match {
case tp: TermRef => ref(tp)
case tp: ThisType => This(tp.cls)
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 4d475fe2b..9cbac9115 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -274,24 +274,17 @@ object Denotations {
val sym1 = denot1.symbol
val sym2 = denot2.symbol
val sym2Accessible = sym2.isAccessibleFrom(pre)
- def shadows(sym1: Symbol, sym2: Symbol) = {
- val owner1 = sym1.owner
- val owner2 = sym2.owner
- owner1.derivesFrom(owner2) && owner1.ne(owner2)
+ def unshadowed(sym: Symbol, from: Symbol) = {
+ val symOwner = sym.owner
+ val fromOwner = from.owner
+ !fromOwner.derivesFrom(symOwner) || fromOwner.eq(symOwner)
}
- /** Preference according to order (overrides, isAsConcrete, shadows)*/
+ /** Preference according to partial pre-order (isConcrete, unshadowed) */
+ def preferSym(sym1: Symbol, sym2: Symbol) =
+ sym1.isAsConcrete(sym2) && (!sym2.isAsConcrete(sym1) || unshadowed(sym1, sym2))
+ /** Sym preference provided types also override */
def prefer(info1: Type, sym1: Symbol, info2: Type, sym2: Symbol) =
- info1.overrides(info2) && (
- // non-standard ordering of tests for efficiency -
- // overrides is costlier to compute than the others, so its 2nd test comes last.
- sym1.isAsConcrete(sym2) && (
- !sym2.isAsConcrete(sym1)
- ||
- shadows(sym1, sym2)
- )
- ||
- !info2.overrides(info1)
- )
+ preferSym(sym1, sym2) && info1.overrides(info2)
if (sym2Accessible && prefer(info2, sym2, info1, sym1)) denot2
else {
val sym1Accessible = sym1.isAccessibleFrom(pre)
@@ -302,7 +295,7 @@ object Denotations {
val sym =
if (!sym1.exists) sym2
else if (!sym2.exists) sym1
- else if (sym2 isAsConcrete sym1) sym2
+ else if (preferSym(sym2, sym1)) sym2
else sym1
new JointRefDenotation(sym, info1 & info2, denot1.validFor & denot2.validFor)
}
diff --git a/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/src/dotty/tools/dotc/transform/ExplicitOuter.scala
index 0fa429d6e..912bc9b7f 100644
--- a/src/dotty/tools/dotc/transform/ExplicitOuter.scala
+++ b/src/dotty/tools/dotc/transform/ExplicitOuter.scala
@@ -221,7 +221,7 @@ object ExplicitOuter {
case nw: New =>
isOuter(nw.tpe.classSymbol.owner.enclosingClass)
case _ =>
- false
+ false
}
}
diff --git a/src/dotty/tools/dotc/typer/RefChecks.scala b/src/dotty/tools/dotc/typer/RefChecks.scala
index 97d005112..3633a7279 100644
--- a/src/dotty/tools/dotc/typer/RefChecks.scala
+++ b/src/dotty/tools/dotc/typer/RefChecks.scala
@@ -420,7 +420,7 @@ object RefChecks {
for (member <- missing) {
val memberSym = member.symbol
def undefined(msg: String) =
- abstractClassError(false, member.showDcl + " is not defined" + msg)
+ abstractClassError(false, s"${member.showDcl} is not defined $msg")
val underlying = memberSym.underlyingSymbol
// Give a specific error message for abstract vars based on why it fails:
@@ -456,9 +456,8 @@ object RefChecks {
case (pa, pc) :: Nil =>
val abstractSym = pa.typeSymbol
val concreteSym = pc.typeSymbol
- def subclassMsg(c1: Symbol, c2: Symbol) = (
- ": %s is a subclass of %s, but method parameter types must match exactly.".format(
- c1.showLocated, c2.showLocated))
+ def subclassMsg(c1: Symbol, c2: Symbol) =
+ s": ${c1.showLocated} is a subclass of ${c2.showLocated}, but method parameter types must match exactly."
val addendum =
if (abstractSym == concreteSym) {
val paArgs = pa.argInfos
@@ -478,12 +477,14 @@ object RefChecks {
subclassMsg(concreteSym, abstractSym)
else ""
- undefined("\n(Note that %s does not match %s%s)".format(pa, pc, addendum))
+ undefined(s"\n(Note that $pa does not match $pc$addendum)")
case xs =>
- undefined("")
+ undefined(s"\n(The class implements a member with a different type: ${concrete.showDcl})")
}
- case _ =>
+ case Nil =>
undefined("")
+ case concretes =>
+ undefined(s"\n(The class implements members with different types: ${concretes.map(_.showDcl)}%\n %)")
}
} else undefined("")
}