diff options
-rw-r--r-- | src/reflect/scala/reflect/internal/Definitions.scala | 15 | ||||
-rw-r--r-- | test/files/pos/t8128.scala | 15 | ||||
-rw-r--r-- | test/pending/pos/t8128b.scala | 18 |
3 files changed, 44 insertions, 4 deletions
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index b7e67bc377..3ccf321227 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -819,11 +819,18 @@ trait Definitions extends api.StandardDefinitions { // FYI the long clunky name is because it's really hard to put "get" into the // name of a method without it sounding like the method "get"s something, whereas // this method is about a type member which just happens to be named get. - def typeOfMemberNamedGet(tp: Type) = resultOfMatchingMethod(tp, nme.get)() - def typeOfMemberNamedHead(tp: Type) = resultOfMatchingMethod(tp, nme.head)() - def typeOfMemberNamedApply(tp: Type) = resultOfMatchingMethod(tp, nme.apply)(IntTpe) - def typeOfMemberNamedDrop(tp: Type) = resultOfMatchingMethod(tp, nme.drop)(IntTpe) + def typeOfMemberNamedGet(tp: Type) = typeArgOfBaseTypeOr(tp, OptionClass)(resultOfMatchingMethod(tp, nme.get)()) + def typeOfMemberNamedHead(tp: Type) = typeArgOfBaseTypeOr(tp, SeqClass)(resultOfMatchingMethod(tp, nme.head)()) + def typeOfMemberNamedApply(tp: Type) = typeArgOfBaseTypeOr(tp, SeqClass)(resultOfMatchingMethod(tp, nme.apply)(IntTpe)) + def typeOfMemberNamedDrop(tp: Type) = typeArgOfBaseTypeOr(tp, SeqClass)(resultOfMatchingMethod(tp, nme.drop)(IntTpe)) def typesOfSelectors(tp: Type) = getterMemberTypes(tp, productSelectors(tp)) + // SI-8128 Still using the type argument of the base type at Seq/Option if this is an old-style (2.10 compatible) + // extractor to limit exposure to regressions like the reported problem with existentials. + // TODO fix the existential problem in the general case, see test/pending/pos/t8128.scala + private def typeArgOfBaseTypeOr(tp: Type, baseClass: Symbol)(or: => Type): Type = (tp baseType baseClass).typeArgs match { + case x :: Nil => x + case _ => or + } // Can't only check for _1 thanks to pos/t796. def hasSelectors(tp: Type) = ( diff --git a/test/files/pos/t8128.scala b/test/files/pos/t8128.scala new file mode 100644 index 0000000000..b6f76691b0 --- /dev/null +++ b/test/files/pos/t8128.scala @@ -0,0 +1,15 @@ +object G { + def unapply(m: Any): Option[_] = Some("") +} + +object H { + def unapplySeq(m: Any): Option[Seq[_]] = None +} + +object Test { + (0: Any) match { + case G(v) => v + case H(v) => v + case _ => + } +} diff --git a/test/pending/pos/t8128b.scala b/test/pending/pos/t8128b.scala new file mode 100644 index 0000000000..dd44a25a90 --- /dev/null +++ b/test/pending/pos/t8128b.scala @@ -0,0 +1,18 @@ +class Optiony[X] { def isEmpty = true; def get: X = ??? } +class Seqy[X] { def head: X = ???; def length = 0; def apply(i: Int): X = ??? } + +object G { + def unapply(m: Any): Optiony[_] = ??? +} + +object H { + def unapplySeq(m: Any): Optiony[Seqy[_]] = ??? +} + +object Test { + (0: Any) match { + case G(v) => v + case H(v) => v + case _ => + } +} |