diff options
-rw-r--r-- | src/dotty/tools/dotc/typer/Implicits.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Mode.scala | 5 | ||||
-rw-r--r-- | test/dotc/tests.scala | 1 | ||||
-rw-r--r-- | tests/neg/arrayclone-new.scala | 38 |
4 files changed, 47 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala index b03bcfcf9..841390ef1 100644 --- a/src/dotty/tools/dotc/typer/Implicits.scala +++ b/src/dotty/tools/dotc/typer/Implicits.scala @@ -491,7 +491,7 @@ trait Implicits { self: Typer => pt) val generated1 = adapt(generated, pt) lazy val shadowing = - typed(untpd.Ident(ref.name) withPos pos.toSynthetic, funProto)(nestedContext.setNewTyperState) + typed(untpd.Ident(ref.name) withPos pos.toSynthetic, funProto)(nestedContext.setNewTyperState.addMode(Mode.ImplicitShadowing)) def refMatches(shadowing: Tree): Boolean = ref.symbol == closureBody(shadowing).symbol || { shadowing match { @@ -501,7 +501,8 @@ trait Implicits { self: Typer => } if (ctx.typerState.reporter.hasErrors) nonMatchingImplicit(ref) - else if (contextual && !shadowing.tpe.isError && !refMatches(shadowing)) { + else if (contextual && !ctx.mode.is(Mode.ImplicitShadowing) && + !shadowing.tpe.isError && !refMatches(shadowing)) { implicits.println(i"SHADOWING $ref in ${ref.termSymbol.owner} is shadowed by $shadowing in ${shadowing.symbol.owner}") shadowedImplicit(ref, methPart(shadowing).tpe) } diff --git a/src/dotty/tools/dotc/typer/Mode.scala b/src/dotty/tools/dotc/typer/Mode.scala index 8889cf604..e84ef2784 100644 --- a/src/dotty/tools/dotc/typer/Mode.scala +++ b/src/dotty/tools/dotc/typer/Mode.scala @@ -68,5 +68,10 @@ object Mode { */ val Printing = newMode(10, "Printing") + /** We are currently typechecking an ident to determine whether some implicit + * is shadowed - don't do any other shadowing tests. + */ + val ImplicitShadowing = newMode(11, "ImplicitShadowing") + val PatternOrType = Pattern | Type } diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index a7123602b..0a6127580 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -137,6 +137,7 @@ class tests extends CompilerTest { @Test def neg_escapingRefs = compileFile(negDir, "escapingRefs", xerrors = 2) @Test def neg_instantiateAbstract = compileFile(negDir, "instantiateAbstract", xerrors = 8) @Test def neg_selfInheritance = compileFile(negDir, "selfInheritance", xerrors = 5) + @Test def neg_shadowedImplicits = compileFile(negDir, "arrayclone-new", xerrors = 2) @Test def run_all = runFiles(runDir) diff --git a/tests/neg/arrayclone-new.scala b/tests/neg/arrayclone-new.scala new file mode 100644 index 000000000..4e33a7d8c --- /dev/null +++ b/tests/neg/arrayclone-new.scala @@ -0,0 +1,38 @@ +// Run with -explaintypes to see information about shadowing failures +import scala.reflect.{ClassTag, classTag} + +object Test extends dotty.runtime.LegacyApp{ + ObjectArrayClone; + PolymorphicArrayClone; +} + +object ObjectArrayClone{ + val it : Array[String] = Array("1", "0"); + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = "0"; + assert(it(0) == "1") +} + +object PolymorphicArrayClone{ + def testIt[T](it : Array[T], one : T, zero : T) = { + val cloned = it.clone(); + assert(cloned.sameElements(it)); + cloned(0) = zero; + assert(it(0) == one) + } + + testIt(Array("one", "two"), "one", "two"); + + class Mangler[T: ClassTag](ts : T*){ + // this will always be a BoxedAnyArray even after we've unboxed its contents. + val it = ts.toArray[T]; + } + + val mangled = new Mangler[Int](0, 1); + + val y : Array[Int] = mangled.it; // make sure it's unboxed + + testIt(mangled.it, 0, 1); +} + |