From 6eba6c9f0980ce4f4cacb399295234e2f22b2bbe Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 5 Mar 2014 16:24:05 +0100 Subject: [PATCH 1/6] Made TypeBoundsTrees to be TypTrees so they are eliminated by PostTyperTransform --- src/dotty/tools/dotc/ast/Trees.scala | 2 +- src/dotty/tools/dotc/typer/Typer.scala | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index c1cb474a3405..8ca6cedf43a2 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -644,7 +644,7 @@ object Trees { /** >: lo <: hi */ case class TypeBoundsTree[-T >: Untyped] private[ast] (lo: Tree[T], hi: Tree[T]) - extends Tree[T] { + extends TypTree[T] { type ThisTree[-T >: Untyped] = TypeBoundsTree[T] } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 6cc3a226e3d5..e6f566193182 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -88,7 +88,6 @@ class Typer extends Namer with Applications with Implicits { if (reallyExists(mbr)) site.select(name, mbr) else { if (!site.isErroneous) { - typr.println(s"site = $site, baseClasses = ${site.baseClasses}") ctx.error( if (name == nme.CONSTRUCTOR) i"$site does not have a constructor" else i"$name is not a member of $site", pos) From f041ae03b86f324f831ab868e17843ba8fdc10ca Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 6 Mar 2014 09:43:14 +0100 Subject: [PATCH 2/6] Fix problem in TermRef.alternatives Rewrap needs to produce alternatives with signatures. Otgerwise the new denotation will simply overwrite the old because both the overloaded TermRef and the alternative will hash to the same unique TermRef. --- src/dotty/tools/dotc/core/Types.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index f9c8aad5cb68..bb30d9a9c7a6 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -1140,7 +1140,7 @@ object Types { override def isOverloaded(implicit ctx: Context) = denot.isOverloaded private def rewrap(sd: SingleDenotation)(implicit ctx: Context) = - TermRef(prefix, name, sd) + TermRef.withSig(prefix, name, sd.signature, sd) def alternatives(implicit ctx: Context): List[TermRef] = denot.alternatives map rewrap From 00c3cb74f65474739bc49fe318b5b959296ee8a5 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 6 Mar 2014 09:46:07 +0100 Subject: [PATCH 3/6] Fix problem comparing overloaded TermRefs Overloaded TermRefs do not have an info, and consequently do not support =:=. Yet in Typer#checkNewOrShadowed we compared termrefs with =:=. This gives an exception if the termrefs are overloaded. The fix is to provide a new method isSameRef in TypeComparer which is called instead of =:= in Typer#checkNewOrShadowed. --- src/dotty/tools/dotc/core/TypeComparer.scala | 22 +++++++++++++++++--- src/dotty/tools/dotc/typer/Typer.scala | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index d46a8387fdf0..ffb20cbadc7d 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -715,9 +715,25 @@ class TypeComparer(initctx: Context) extends DotClass { /** Two types are the same if are mutual subtypes of each other */ def isSameType(tp1: Type, tp2: Type): Boolean = - if (tp1 == NoType || tp2 == NoType) false - else if (tp1 eq tp2) true - else isSubType(tp1, tp2) && isSubType(tp2, tp1) + isSubType(tp1, tp2) && isSubType(tp2, tp1) + + /** Same as `isSameType` but also can be applied to overloaded TermRefs, where + * two overloaded refs are the same if they have pairwise equal alternatives + */ + def isSameRef(tp1: Type, tp2: Type): Boolean = ctx.traceIndented(s"isSameRef($tp1, $tp2") { + def isSubRef(tp1: Type, tp2: Type): Boolean = tp1 match { + case tp1: TermRef if tp1.isOverloaded => + tp1.alternatives forall (isSubRef(_, tp2)) + case _ => + tp2 match { + case tp2: TermRef if tp2.isOverloaded => + tp2.alternatives exists (isSubRef(tp1, _)) + case _ => + isSubType(tp1, tp2) + } + } + isSubRef(tp1, tp2) && isSubRef(tp2, tp1) + } /** The greatest lower bound of two types */ def glb(tp1: Type, tp2: Type): Type = /*>|>*/ ctx.traceIndented(s"glb(${tp1.show}, ${tp2.show})", typr, show = true) /*<|<*/ { diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index e6f566193182..aabcde94dfe1 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -244,7 +244,7 @@ class Typer extends Namer with Applications with Implicits { * does properly shadow the new one from an outer context. */ def checkNewOrShadowed(found: Type, newPrec: Int): Type = - if (!previous.exists || (previous =:= found)) found + if (!previous.exists || ctx.typeComparer.isSameRef(previous, found)) found else if ((prevCtx.scope eq ctx.scope) && (newPrec == definition || newPrec == namedImport && prevPrec == wildImport)) { From f37550d4e2f0788bce5ca001df373c806145384e Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 6 Mar 2014 10:06:50 +0100 Subject: [PATCH 4/6] Added test for overloaded access with import/inheritance conflict --- test/dotc/tests.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 88c39231b97f..9914485ac3cb 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -41,6 +41,7 @@ class tests extends CompilerTest { @Test def pos_templateParents() = compileFile(posDir, "templateParents") @Test def pos_structural() = compileFile(posDir, "structural") @Test def pos_i39 = compileFile(posDir, "i39") + @Test def pos_overloadedAccess = compileFile(posDir, "overloadedAccess") @Test def neg_blockescapes() = compileFile(negDir, "blockescapesNeg", xerrors = 1) @Test def neg_typedapply() = compileFile(negDir, "typedapply", xerrors = 4) From cd60a3d3470f311a4591efc5ba0f0efbdead1f8d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 6 Mar 2014 10:11:36 +0100 Subject: [PATCH 5/6] Fix of accidental omission in TypeComparer --- src/dotty/tools/dotc/core/TypeComparer.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index ffb20cbadc7d..da8263ac1a3f 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -715,7 +715,9 @@ class TypeComparer(initctx: Context) extends DotClass { /** Two types are the same if are mutual subtypes of each other */ def isSameType(tp1: Type, tp2: Type): Boolean = - isSubType(tp1, tp2) && isSubType(tp2, tp1) + if (tp1 eq NoType) false + else if (tp1 eq tp2) true + else isSubType(tp1, tp2) && isSubType(tp2, tp1) /** Same as `isSameType` but also can be applied to overloaded TermRefs, where * two overloaded refs are the same if they have pairwise equal alternatives From 4acf8ad8dde22f1ad9ba3f6c6e9cb8dd4b49b3cb Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 6 Mar 2014 10:17:37 +0100 Subject: [PATCH 6/6] Removed useless ValDef flagged by @samuelgruetter in previous pull request --- src/dotty/tools/dotc/typer/Typer.scala | 3 +-- tests/pos/overloadedAccess.scala | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tests/pos/overloadedAccess.scala diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index aabcde94dfe1..4c4920e5ba40 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -138,8 +138,7 @@ class Typer extends Namer with Applications with Implicits { } val where = if (ctx.owner.exists) s" from ${ctx.owner.enclosingClass}" else "" val whyNot = new StringBuffer - val addendum = - alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot)) + alts foreach (_.isAccessibleFrom(pre, superAccess, whyNot)) if (!tpe.isError) ctx.error(i"$what cannot be accessed as a member of $pre$where.$whyNot", pos) ErrorType diff --git a/tests/pos/overloadedAccess.scala b/tests/pos/overloadedAccess.scala new file mode 100644 index 000000000000..a2d72f583ea2 --- /dev/null +++ b/tests/pos/overloadedAccess.scala @@ -0,0 +1,18 @@ +object overloadedAccess { + + trait ST { + def f(x: Object): Int = 1 + def f(x: Int): Unit = () + } + + object O extends ST { + def f(x: String): Unit = () + } + + class C extends ST { + import O._ // needs to pick inherited member because they are made visible in same scope. + val x = f("abc") + val y: Int = x + } + +}