From 7abeacab53286233d4b150e713ca253c08f38bfd Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 4 May 2010 13:53:09 +0000 Subject: closes #3373, #3177: validity check of an impli... closes #3373, #3177: validity check of an implicit value should consider the value as well as its accessor review by odersky --- .../scala/tools/nsc/typechecker/Implicits.scala | 14 +++++--- test/files/pos/t3177.scala | 39 ++++++++++++++++++++++ test/files/pos/t3373.scala | 11 ++++++ 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 test/files/pos/t3177.scala create mode 100644 test/files/pos/t3373.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 9a6c4cc401..862f9adaec 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -520,7 +520,7 @@ self: Analyzer => * - the symbol's type is initialized * - the symbol comes from a classfile * - the symbol comes from a different sourcefile than the current one - * - the symbol's definition comes before, and does not contain the closest enclosing definition, + * - the symbol and the accessed symbol's definitions come before, and do not contain the closest enclosing definition, // see #3373 * - the symbol's definition is a val, var, or def with an explicit result type * The aim of this method is to prevent premature cyclic reference errors * by computing the types of only those implicits for which one of these @@ -539,9 +539,15 @@ self: Analyzer => case _ => true } } - def comesBefore(sym: Symbol, owner: Symbol) = - sym.pos.pointOrElse(0) < owner.pos.pointOrElse(Integer.MAX_VALUE) && - !(owner.ownerChain contains sym) + def comesBefore(sym: Symbol, owner: Symbol) = { + val ownerPos = owner.pos.pointOrElse(Integer.MAX_VALUE) + sym.pos.pointOrElse(0) < ownerPos && + if(sym isGetterOrSetter) { + val symAcc = sym.accessed // #3373 + symAcc.pos.pointOrElse(0) < ownerPos && + !(owner.ownerChain exists (o => (o eq sym) || (o eq symAcc))) // probably faster to iterate only once, don't feel like duplicating hasTransOwner for this case + } else !(owner hasTransOwner sym) // faster than owner.ownerChain contains sym + } sym.isInitialized || sym.sourceFile == null || diff --git a/test/files/pos/t3177.scala b/test/files/pos/t3177.scala new file mode 100644 index 0000000000..9f9528faec --- /dev/null +++ b/test/files/pos/t3177.scala @@ -0,0 +1,39 @@ +trait InvariantFunctor[F[_]] { + def xmap[A, B](ma: F[A], f: A => B, g: B => A): F[B] +} + +object InvariantFunctor { + import Endo._ + + implicit val EndoInvariantFunctor = new InvariantFunctor[Endo] { + def xmap[A, B](ma: Endo[A], f: A => B, g: B => A): Endo[B] = (b: B) => f(ma(g(b))) + } + + // The definition about fails with: + // anon-type.scala:9: error: not found: value b + // def xmap[A, B](ma: Endo[A], f: A => B, g: B => A): Endo[B] = (b: B) => f(ma(g(b))) + // ^ + // anon-type.scala:8: error: not found: type $anon + // implicit val EndoInvariantFunctor = new InvariantFunctor[Endo] { + // ^ + + + // These both work: + // implicit val EndoInvariantFunctorAscribed: InvariantFunctor[Endo] = new InvariantFunctor[Endo] { + // def xmap[A, B](ma: Endo[A], f: A => B, g: B => A): Endo[B] = (b: B) => f(ma(g(b))) + // } + // + // implicit val EndoInvariantFunctorStubbed = new InvariantFunctor[Endo] { + // def xmap[A, B](ma: Endo[A], f: A => B, g: B => A): Endo[B] = error("stub") + // } +} + +trait Endo[X] + +object Endo { + implicit def EndoTo[A](f: A => A): Endo[A] = new Endo[A] { + def apply(a: A) = f(a) + } + + implicit def EndoFrom[A](e: Endo[A]): A => A = e.apply(_) +} \ No newline at end of file diff --git a/test/files/pos/t3373.scala b/test/files/pos/t3373.scala new file mode 100644 index 0000000000..b4af3610bb --- /dev/null +++ b/test/files/pos/t3373.scala @@ -0,0 +1,11 @@ +class Entry(time: Long) { + def getTime: Long = time +} + +object Test { + def extractTime(e: Entry) = e.getTime + + implicit val orderEntries = new Ordering[Entry] { + def compare(first: Entry, second: Entry) = extractTime(first) compare extractTime(second) + } +} \ No newline at end of file -- cgit v1.2.3