874d2a95b2ae791019dd5e1ce81ab1b94bbd4588 | a3799c585a78ca8ba9bc0c28c76e76842098cf15 | ||
---|---|---|---|
2466 | /* --- begin unapply --- */ | 2466 | /* --- begin unapply --- */ |
2467 | 2467 | ||
2468 | case otpe if inPatternMode(mode) && unapplyMember(otpe).exists => | 2468 | case otpe if inPatternMode(mode) && unapplyMember(otpe).exists => |
2469 | val unapp = unapplyMember(otpe) | ||
2470 | assert(unapp.exists, tree) | ||
2471 | val unappType = otpe.memberType(unapp) | ||
2472 | val argDummyType = pt // was unappArg | ||
2473 | // @S: do we need to memoize this? | ||
2474 | val argDummy = context.owner.newValue(fun.pos, nme.SELECTOR_DUMMY) | ||
2475 | .setFlag(SYNTHETIC) | ||
2476 | .setInfo(argDummyType) | ||
2477 | if (args.length > MaxTupleArity) | 2469 | if (args.length > MaxTupleArity) |
2478 | error(fun.pos, "too many arguments for unapply pattern, maximum = "+MaxTupleArity) | 2470 | error(fun.pos, "too many arguments for unapply pattern, maximum = "+MaxTupleArity) |
2479 | val arg = Ident(argDummy) setType argDummyType | 2471 | |
2480 | val oldArgType = arg.tpe | 2472 | def freshArgType(tp: Type): (Type, List[Symbol]) = (tp: @unchecked) match { |
2481 | if (!isApplicableSafe(List(), unappType, List(arg.tpe), WildcardType)) { | 2473 | case MethodType(param :: _, _) => |
2474 | (param.tpe, Nil) | ||
2475 | case PolyType(tparams, restype) => | ||
2476 | val tparams1 = cloneSymbols(tparams) | ||
2477 | (freshArgType(restype)._1.substSym(tparams, tparams1), tparams1) | ||
2478 | case OverloadedType(_, _) => | ||
2479 | error(fun.pos, "cannot resolve overloaded unapply") | ||
2480 | (ErrorType, Nil) | ||
2481 | } | ||
2482 | |||
2483 | val unapp = unapplyMember(otpe) | ||
2484 | val unappType = otpe.memberType(unapp) | ||
2485 | val argDummy = context.owner.newValue(fun.pos, nme.SELECTOR_DUMMY) setFlag SYNTHETIC setInfo pt | ||
2486 | val arg = Ident(argDummy) setType pt | ||
2487 | | ||
2488 | if (!isApplicableSafe(Nil, unappType, List(pt), WildcardType)) { | ||
2482 | //Console.println("UNAPP: need to typetest, arg.tpe = "+arg.tpe+", unappType = "+unappType) | 2489 | //Console.println("UNAPP: need to typetest, arg.tpe = "+arg.tpe+", unappType = "+unappType) |
2483 | def freshArgType(tp: Type): (Type, List[Symbol]) = tp match { | ||
2484 | case MethodType(params, _) => | ||
2485 | (params(0).tpe, Nil) | ||
2486 | case PolyType(tparams, restype) => | ||
2487 | val tparams1 = cloneSymbols(tparams) | ||
2488 | (freshArgType(restype)._1.substSym(tparams, tparams1), tparams1) | ||
2489 | case OverloadedType(_, _) => | ||
2490 | error(fun.pos, "cannot resolve overloaded unapply") | ||
2491 | (ErrorType, Nil) | ||
2492 | } | ||
2493 | val (unappFormal, freeVars) = freshArgType(unappType.skolemizeExistential(context.owner, tree)) | 2490 | val (unappFormal, freeVars) = freshArgType(unappType.skolemizeExistential(context.owner, tree)) |
2494 | val context1 = context.makeNewScope(context.tree, context.owner) | 2491 | val context1 = context.makeNewScope(context.tree, context.owner) |
2495 | freeVars foreach context1.scope.enter | 2492 | freeVars foreach context1.scope.enter |
2493 | |||
2496 | val typer1 = newTyper(context1) | 2494 | val typer1 = newTyper(context1) |
2497 | val pattp = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe) | 2495 | val pattp = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe) |
2498 | 2496 | ||
2499 | // turn any unresolved type variables in freevars into existential skolems | 2497 | // turn any unresolved type variables in freevars into existential skolems |
2500 | val skolems = freeVars map { fv => | 2498 | val skolems = freeVars map { fv => |
... | ... | ||
2504 | skolem | 2502 | skolem |
2505 | } | 2503 | } |
2506 | arg.tpe = pattp.substSym(freeVars, skolems) | 2504 | arg.tpe = pattp.substSym(freeVars, skolems) |
2507 | //todo: replace arg with arg.asInstanceOf[inferTypedPattern(unappFormal, arg.tpe)] instead. | 2505 | argDummy setInfo arg.tpe |
2508 | argDummy.setInfo(arg.tpe) // bq: this line fixed #1281. w.r.t. comment ^^^, maybe good enough? | ||
2509 | } | 2506 | } |
2510 | 2507 | ||
2511 | // setType null is necessary so that ref will be stabilized; see bug 881 | 2508 | // setType null is necessary so that ref will be stabilized; see bug 881 |
... | ... | ||
2517 | val formals1 = formalTypes(formals0, args.length) | 2514 | val formals1 = formalTypes(formals0, args.length) |
2518 | if (sameLength(formals1, args)) { | 2515 | if (sameLength(formals1, args)) { |
2519 | val args1 = typedArgs(args, mode, formals0, formals1) | 2516 | val args1 = typedArgs(args, mode, formals0, formals1) |
2520 | if (!isFullyDefined(pt)) assert(false, tree+" ==> "+UnApply(fun1, args1)+", pt = "+pt) | 2517 | assert(isFullyDefined(pt), tree+" ==> "+UnApply(fun1, args1)+", pt = "+pt) |
2521 | val itype = glb(List(pt, arg.tpe)) | 2518 | |
2522 | // restore old type (arg is a dummy tree, just needs to pass typechecking) | 2519 | val itype = glb(List(pt, arg.tpe)) |
2523 | arg.tpe = oldArgType | 2520 | arg.tpe = pt // restore type (arg is a dummy tree, just needs to pass typechecking) |
2524 | UnApply(fun1, args1) setPos tree.pos setType itype | 2521 | UnApply(fun1, args1) setPos tree.pos setType itype |
2525 | } else { | 2522 | } |
2523 | else { | ||
2526 | errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun)) | 2524 | errorTree(tree, "wrong number of arguments for "+treeSymTypeMsg(fun)) |
2527 | } | 2525 | } |
2528 | } | 2526 | } |
... | ... | ||
3890 | case UnApply(fun, args) => | 3888 | case UnApply(fun, args) => |
3891 | val fun1 = typed(fun) | 3889 | val fun1 = typed(fun) |
3892 | val tpes = formalTypes(unapplyTypeList(fun.symbol, fun1.tpe), args.length) | 3890 | val tpes = formalTypes(unapplyTypeList(fun.symbol, fun1.tpe), args.length) |
3893 | val args1 = (args, tpes).zipped map (typedPattern(_, _)) | 3891 | val args1 = (args, tpes).zipped map typedPattern |
3894 | treeCopy.UnApply(tree, fun1, args1) setType pt | 3892 | treeCopy.UnApply(tree, fun1, args1) setType pt |
3895 | 3893 | ||
3896 | case ArrayValue(elemtpt, elems) => | 3894 | case ArrayValue(elemtpt, elems) => |