{"push_id":1190816615,"size":5,"distinct_size":5,"ref":"refs/heads/review/5041","head":"d81f8e98076ab9c94f0cd139a1122271c4d0609d","before":"a92aab1605c19aad5b1ea0ba6151408f0982e12b","commits":[{"sha":"022509dbe40bcf14d458ad07abd02bcd7299369e","author":{"name":"Jason Zaugg","email":"ed7c853e8cee0d3b3580a0be792529cf101f03e4@gmail.com"},"message":"Type#contains should peer into RefinementTypeRef-s\n\nUsually, `contains` should not look into class symbol infos.\nFor instance, we expect that:\n\n```\nscala> trait C { def foo: Int }; typeOf[C].contains(IntClass)\ndefined trait C\nres1: Boolean = false\n```\n\nWe do, however, look at the decls of a `RefinedType` in contains:\n\n```\nscala> typeOf[{ def foo: Int }].contains(IntClass)\nres2: Boolean = true\n```\n\nThings get a little vauge, however, when we consider a type ref\nto the refinement class symbol of a refined type.\n\n```\nscala> TypeRef(NoPrefix, typeOf[{ def foo: Int }].typeSymbol, Nil)\nres3: $r.intp.global.Type = AnyRef{def foo: Int}\n\nscala> .contains(IntClass)\nres4: Boolean = false\n```\n\nThese show up in the first element of the base type seq of a refined\ntype, e.g:\n\n```\nscala> typeOf[{ def foo: Int }].typeSymbol.tpe_*\nres5: $r.intp.global.Type = AnyRef{def foo: Int}\n\nscala> typeOf[{ def foo: Int }].baseTypeSeq(0).getClass\nres7: Class[_ <: $r.intp.global.Type] = class scala.reflect.internal.Types$RefinementTypeRef\n\nscala> typeOf[{ def foo: Int }].typeSymbol.tpe_*.getClass\nres6: Class[_ <: $r.intp.global.Type] = class scala.reflect.internal.Types$RefinementTypeRef\n```\n\nThis commit takes the opinion that a `RefinementTypeRef` should be\ntransparent with respect to `contains`. This paves the way for fixing\nthe base type sequences of existential types over refinement types.\nThe implementation of `ContainsCollector` was already calling\n`normalize`, which goes from `RefinementTypeRef` to `RefinedType`.\nThis commit maps over the result, which looks in the parents and\ndecls.\n\nfixup contains","distinct":true,"url":"https://api.github.com/repos/retronym/scala/commits/022509dbe40bcf14d458ad07abd02bcd7299369e"},{"sha":"59611a0b6ed6546547e5f2137406dae124bb8f7d","author":{"name":"Jason Zaugg","email":"ed7c853e8cee0d3b3580a0be792529cf101f03e4@gmail.com"},"message":"Improved refinement type and existential type handling\n\nLazy base type seq elements are encoded as a refined type with\nan empty scope and a list of type refs over some common type\nsymbol that will be merged when `BaseTypeSeq#apply` is called.\n\nThe first change in this commit is to mark the creation and consumption\nof such elements with calls to `[is]IntersectionTypeForBaseTypeSeq`. They\nare distinguished by using the actual type symbol rather than a refinement\nclass symbol, which in turn simplifies the code in\n`BaseTypeSeq#typeSymbol`.\n\nI have also made `lub` aware of this encoding: it is now able to \"see through\"\nto the parents of such refined types and merge them with other base types\nof the same class symbol (even other refined types representing lazy BTS\nelements.)\n\nFurthermore, I have fixed the computation of the base type sequences of\nexistential types over refinement types, in order to maintain the invariant\nthat each slot of the base type sequence of a existential has the same\ntype symbol as that of its underlying type. Before, what I've now called\na `RefinementTypeRef` was transformed into a `RefinedType` during\nrewrapping in the existential, which led to it being wrongly considered as\na lazy element of the base type sequence. The first change above should\nalso be sufficient to avoid the bug, but I felt it was worth cleaning up\n`maybeRewrap` as an extra line of defence.\n\nFinally, I have added another special case to `BaseTypeSeq#apply` to\nbe able to lazily compute elements that have been wrapped in an existential.\n\nThe unit test cases in `TypesTest` rely on these changes. A subsequent commit\nwill build on this foundation to make a fix to `asSeenFrom`.","distinct":true,"url":"https://api.github.com/repos/retronym/scala/commits/59611a0b6ed6546547e5f2137406dae124bb8f7d"},{"sha":"ebff7b832108a2d0c85a1cd76c557538ccd62ac6","author":{"name":"Jason Zaugg","email":"ed7c853e8cee0d3b3580a0be792529cf101f03e4@gmail.com"},"message":"SI-5294 Use bounds of abstract prefix in asSeenFrom\n\nASF was failing to recognize the correspondence between a\nprefix if it has an abstract type symbol, even if it is bounded by\nthe currently considered class.\n\nDistilling the test cases, this led to incorrect typechecking of the\nRHS of `G` in:\n\n```\ntrait T {\n  type A\n  trait HasH { type H[U] <: U }\n  type F[N <: HasH] = N#H[T]\n  type G[N <: HasH] = F[N]#A // RHS was incorrectly reduced to T.this.A\n}\n```\n\nIn the fuller examples (included as test cases), this meant that\ntype level functions written as members of `HList` could not be\nimplemented in terms of each other, e.g. defining `Apply[N]` as\n`Drop[N]#Head` had the wrong semantics.\n\nThis commit checks checks if the prefix has the candidate class\nas a base type, rather than checking if its type symbol has this\nas a base class. The latter formulation discarded information about\nthe instantation of the abstract type.\n\nUsing the example above:\n\n```\nscala> val F = typeOf[T].member(TypeName(\"F\")).info\nF: $r.intp.global.Type = [N <: T.this.HasH]N#H[T]\n\nscala> F.resultType.typeSymbol.baseClasses // old approach\nres14: List[$r.intp.global.Symbol] = List(class Any)\n\nscala> F.resultType.baseClasses // new approach\nres13: List[$r.intp.global.Symbol] = List(trait T, class Object, class Any)\n```\n\nIt is worth noting that dotty rejects some of these programs,\nas it introduces the rule that:\n\n> // A type T is a legal prefix in a type selection T#A if\n> // T is stable or T contains no abstract types except possibly A.\n> final def isLegalPrefixFor(selector: Name)(implicit ctx: Context)\n\nHowever, typechecking the program above in this comment in dotty\nyields:\n\n    <trait> trait T() extends Object {\n      type A\n      <trait> trait HasH() extends Object {\n        type H <: [HK$0] =>  <: HK$0\n      }\n      type F = [HK$0] => HK$0#H{HK$0 = T}#Apply\n      type G = [HK$0] => HK$0#H{HK$0 = T}#Apply#A\n    }\n\nAs the equivalent code [1] in dotc's `asSeenFrom` already looks for a base type\nof the prefix, rather than looking for a superclass of the prefix's\ntype symbol.\n\n[1] https://github.com/lampepfl/dotty/blob/d2c96d02fccef3a82b88ee1ff31253b6ef17f900/src/dotty/tools/dotc/core/TypeOps.scala#L62","distinct":true,"url":"https://api.github.com/repos/retronym/scala/commits/ebff7b832108a2d0c85a1cd76c557538ccd62ac6"},{"sha":"6d5d382d00797a8da661bf35d2bb1e6932292406","author":{"name":"Jason Zaugg","email":"ed7c853e8cee0d3b3580a0be792529cf101f03e4@gmail.com"},"message":"Harden companionSymbolOf against NoSymbol","distinct":true,"url":"https://api.github.com/repos/retronym/scala/commits/6d5d382d00797a8da661bf35d2bb1e6932292406"},{"sha":"d81f8e98076ab9c94f0cd139a1122271c4d0609d","author":{"name":"Jason Zaugg","email":"ed7c853e8cee0d3b3580a0be792529cf101f03e4@gmail.com"},"message":"Test expectation changes, TODO figure out why","distinct":true,"url":"https://api.github.com/repos/retronym/scala/commits/d81f8e98076ab9c94f0cd139a1122271c4d0609d"}]}
{"actor":{"display_login":"retronym"}}