|
1 | 1 | package scala.reflect.internal
|
2 | 2 |
|
3 | 3 | import org.junit.Assert._
|
4 |
| -import org.junit.{Assert, Test} |
| 4 | +import org.junit.{After, Assert, Before, Test} |
5 | 5 | import org.junit.runner.RunWith
|
6 | 6 | import org.junit.runners.JUnit4
|
7 | 7 | import scala.collection.mutable
|
@@ -139,4 +139,196 @@ class TypesTest {
|
139 | 139 | assert(ts.forall(_ <:< merged2))
|
140 | 140 | assert(merged1 =:= merged2)
|
141 | 141 | }
|
| 142 | + |
| 143 | + |
| 144 | + |
| 145 | + class Foo[A] |
| 146 | + class Bar[+T, A] |
| 147 | + class Baz { |
| 148 | + def f[F[_]] = () |
| 149 | + def g[G[_, _]] = () |
| 150 | + } |
| 151 | + |
| 152 | + var storedYhkTypevarUnification = false |
| 153 | + @Before |
| 154 | + def storeYhkTypevarUnification: Unit = { |
| 155 | + storedYhkTypevarUnification = settings.YhkTypevarUnification |
| 156 | + } |
| 157 | + @After |
| 158 | + def restoreYhkTypevarUnification: Unit = { |
| 159 | + settings.YhkTypevarUnification.value = storedYhkTypevarUnification |
| 160 | + } |
| 161 | + |
| 162 | + @Test |
| 163 | + def testHigherKindedTypeVarUnification(): Unit = { |
| 164 | + import rootMirror.EmptyPackageClass |
| 165 | + import Flags._ |
| 166 | + |
| 167 | + val FooTpe = typeOf[Foo[Int]] match { |
| 168 | + case TypeRef(pre, sym, _) => |
| 169 | + sym.typeParams // doing it for the side effect |
| 170 | + TypeRef(pre, sym, Nil) |
| 171 | + } |
| 172 | + val BarTpe = typeOf[Bar[Int, Int]] match { |
| 173 | + case TypeRef(pre, sym, _) => |
| 174 | + sym.typeParams // doing it for the side effect |
| 175 | + TypeRef(pre, sym, Nil) |
| 176 | + } |
| 177 | + |
| 178 | + // apply Foo to type arugment A |
| 179 | + def Foo(A: Type) = FooTpe match { |
| 180 | + case TypeRef(pre, sym, Nil) => TypeRef(pre, sym, A :: Nil) |
| 181 | + } |
| 182 | + |
| 183 | + // apply Bar to type arguments A, B |
| 184 | + def Bar(A: Type, B: Type) = BarTpe match { |
| 185 | + case TypeRef(pre, sym, Nil) => TypeRef(pre, sym, A :: B :: Nil) |
| 186 | + } |
| 187 | + |
| 188 | + val F0 = typeOf[Baz].member(TermName("f")).typeSignature.typeParams.head |
| 189 | + val G0 = typeOf[Baz].member(TermName("g")).typeSignature.typeParams.head |
| 190 | + |
| 191 | + // since TypeVars are mutable, we will be creating fresh ones |
| 192 | + def F() = TypeVar(F0) |
| 193 | + def G() = TypeVar(G0) |
| 194 | + |
| 195 | + def polyType(f: TypeVar => Type, flags: Long = 0L): Type = { |
| 196 | + val A = EmptyPackageClass.newTypeParameter(newTypeName("A"), newFlags = flags) |
| 197 | + A.setInfo(TypeBounds.empty) |
| 198 | + val A_ = TypeVar(A) |
| 199 | + PolyType(A :: Nil, f(A_)) |
| 200 | + } |
| 201 | + |
| 202 | + def coPolyType(f: TypeVar => Type): Type = |
| 203 | + polyType(f, COVARIANT) |
| 204 | + |
| 205 | + def polyType2(f: (TypeVar, TypeVar) => Type): Type = { |
| 206 | + val A = EmptyPackageClass.newTypeParameter(newTypeName("A")) |
| 207 | + val B = EmptyPackageClass.newTypeParameter(newTypeName("B")) |
| 208 | + A.setInfo(TypeBounds.empty) |
| 209 | + B.setInfo(TypeBounds.empty) |
| 210 | + val A_ = TypeVar(A) |
| 211 | + val B_ = TypeVar(B) |
| 212 | + PolyType(A :: B :: Nil, f(A_, B_)) |
| 213 | + } |
| 214 | + |
| 215 | + val Any = typeOf[Any] |
| 216 | + val Int = typeOf[Int] |
| 217 | + |
| 218 | + settings.YhkTypevarUnification.value = true |
| 219 | + |
| 220 | + // test that ?F unifies with Foo |
| 221 | + assert(F() <:< FooTpe) |
| 222 | + assert(FooTpe <:< F()) |
| 223 | + assert(F() =:= FooTpe) |
| 224 | + assert(FooTpe =:= F) |
| 225 | + |
| 226 | + // test that ?F unifies with [A]Foo[A] |
| 227 | + assert(F() <:< polyType(A => Foo(A))) |
| 228 | + assert(polyType(A => Foo(A)) <:< F()) |
| 229 | + assert(F() =:= polyType(A => Foo(A))) |
| 230 | + assert(polyType(A => Foo(A)) =:= F()) |
| 231 | + |
| 232 | + // test that ?F unifies with [A]Bar[Int, A] |
| 233 | + assert(F<
9E88
/span>() <:< polyType(A => Bar(Int, A))) |
| 234 | + assert(polyType(A => Bar(Int, A)) <:< F()) |
| 235 | + assert(F() =:= polyType(A => Bar(Int, A))) |
| 236 | + assert(polyType(A => Bar(Int, A)) =:= F()) |
| 237 | + |
| 238 | + // test that ?F unifies with [A]Bar[A, Int] |
| 239 | + assert(F() <:< polyType(A => Bar(A, Int))) |
| 240 | + assert(polyType(A => Bar(A, Int)) <:< F()) |
| 241 | + assert(F() =:= polyType(A => Bar(A, Int))) |
| 242 | + assert(polyType(A => Bar(A, Int)) =:= F()) |
| 243 | + |
| 244 | + // test that ?F unifies with [+A]Bar[A, Int] |
| 245 | + assert(F() <:< coPolyType(A => Bar(A, Int))) |
| 246 | + assert(coPolyType(A => Bar(A, Int)) <:< F()) |
| 247 | + assert(F() =:= coPolyType(A => Bar(A, Int))) |
| 248 | + assert(coPolyType(A => Bar(A, Int)) =:= F()) |
| 249 | + |
| 250 | + // test that ?F unifies with [A]Foo[Foo[A]] |
| 251 | + assert(F() <:< polyType(A => Foo(Foo(A)))) |
| 252 | + assert(polyType(A => Foo(Foo(A))) <:< F()) |
| 253 | + assert(F() =:= polyType(A => Foo(Foo(A)))) |
| 254 | + assert(polyType(A => Foo(Foo(A))) =:= F()) |
| 255 | + |
| 256 | + // test that ?F unifies with [A]Foo[Bar[A, A]] |
| 257 | + assert(F() <:< polyType(A => Foo(Bar(A, A)))) |
| 258 | + assert(polyType(A => Foo(Bar(A, A))) <:< F()) |
| 259 | + assert(F() =:= polyType(A => Foo(Bar(A, A)))) |
| 260 | + assert(polyType(A => Foo(Bar(A, A))) =:= F()) |
| 261 | + |
| 262 | + // test that ?F unifies with [A]Bar[Foo[A], Foo[A]] |
| 263 | + assert(F() <:< polyType(A => Bar(Foo(A), Foo(A)))) |
| 264 | + assert(polyType(A => Bar(Foo(A), Foo(A))) <:< F()) |
| 265 | + assert(F() =:= polyType(A => Bar(Foo(A), Foo(A)))) |
| 266 | + assert(polyType(A => Bar(Foo(A), Foo(A))) =:= F()) |
| 267 | + |
| 268 | + // test that ?F unifies with [A]A |
| 269 | + assert(F() <:< polyType(A => A)) |
| 270 | + assert(polyType(A => A) <:< F()) |
| 271 | + assert(F() =:= polyType(A => A)) |
| 272 | + assert(polyType(A => A) =:= F()) |
| 273 | + |
| 274 | + // test that ?F unifies with [A]Int |
| 275 | + assert(F() <:< polyType(A => Int)) |
| 276 | + assert(polyType(A => Int) <:< F()) |
| 277 | + assert(F() =:= polyType(A => Int)) |
| 278 | + assert(polyType(A => Int) =:= F()) |
| 279 | + |
| 280 | + // test that ?F unifies with [A]Foo[Int] |
| 281 | + assert(F() <:< polyType(A => Foo(Int))) |
| 282 | + assert(polyType(A => Foo(Int)) <:< F()) |
| 283 | + assert(F() =:= polyType(A => Foo(Int))) |
| 284 | + assert(polyType(A => Foo(Int)) =:= F()) |
| 285 | + |
| 286 | + // test that ?G unifies with Bar |
| 287 | + assert(G() <:< BarTpe) |
| 288 | + assert(BarTpe <:< G()) |
| 289 | + assert(G() =:= BarTpe) |
| 290 | + assert(BarTpe =:= G()) |
| 291 | + |
| 292 | + // test that ?G unifies with [A, B]Bar[A, B] |
| 293 | + assert(G() <:< polyType2((A, B) => Bar(A, B))) |
| 294 | + assert(polyType2((A, B) => Bar(A, B)) <:< G()) |
| 295 | + assert(G() =:= polyType2((A, B) => Bar(A, B))) |
| 296 | + assert(polyType2((A, B) => Bar(A, B)) =:= G()) |
| 297 | + |
| 298 | + // test that ?G unifies with [A, B]Bar[B, A] |
| 299 | + assert(G() <:< polyType2((A, B) => Bar(B, A))) |
| 300 | + assert(polyType2((B, A) => Bar(A, B)) <:< G()) |
| 301 | + assert(G() =:= polyType2((A, B) => Bar(B, A))) |
| 302 | + assert(polyType2((B, A) => Bar(A, B)) =:= G()) |
| 303 | + |
| 304 | + // test that ?G unifies with [A, B]Bar[Bar[B, A], A] |
| 305 | + assert(G() <:< polyType2((A, B) => Bar(Bar(B, A), A))) |
| 306 | + assert(polyType2((A, B) => Bar(Bar(B, A), A)) <:< G()) |
| 307 | + assert(G() =:= polyType2((A, B) => Bar(Bar(B, A), A))) |
| 308 | + assert(polyType2((A, B) => Bar(Bar(B, A), A)) =:= G()) |
| 309 | + |
| 310 | + // test that ?G doesn't unify with [A]Bar[A, A] |
| 311 | + assertFalse(G() <:< polyType(A => Bar(A, A))) |
| 312 | + assertFalse(polyType(A => Bar(A, A)) <:< G()) |
| 313 | + // These fail, but shouldn't. |
| 314 | + // Probably a bug in TypeVar#registerTypeEquality: not checking the number of type parameters. |
| 315 | + //assertFalse(G() =:= polyType(A => Bar(A, A))) |
| 316 | + //assertFalse(polyType(A => Bar(A, A)) =:= G()) |
| 317 | + |
| 318 | + // test that [A]Bar[Int, A] <:< ?F <:< [A]Bar[Any, A] |
| 319 | + F() match { case _F => |
| 320 | + assert(polyType(A => Bar(Int, A)) <:< _F && _F <:< polyType(A => Bar(Any, A))) |
| 321 | + } |
| 322 | + |
| 323 | + // Test that both |
| 324 | + // Foo <:< ?F |
| 325 | + // ?F <:< [A]Bar[Int, A] |
| 326 | + // but not at the same time, which by transitivity would mean |
| 327 | + // Foo <:< [A]Bar[Int, A] |
| 328 | + // which is wrong. |
| 329 | + assert(FooTpe <:< F() && F() <:< polyType(A => Bar(Int, A))) |
| 330 | + F() match { case _F => |
| 331 | + assertFalse(FooTpe <:< _F && _F <:< polyType(A => Bar(Int, A))) |
| 332 | + } |
| 333 | + } |
142 | 334 | }
|
0 commit comments