summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Namers.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2006-10-04 16:15:04 +0000
committerMartin Odersky <odersky@gmail.com>2006-10-04 16:15:04 +0000
commit7233c24d3c54cdc4b68b39fb0a270a771d4449f5 (patch)
tree1164bbe016c84e459194f3b530333f243b67ea4e /src/compiler/scala/tools/nsc/typechecker/Namers.scala
parent93275f2d34ec534049baf529493dc6f2836a85ea (diff)
downloadscala-7233c24d3c54cdc4b68b39fb0a270a771d4449f5.tar.gz
scala-7233c24d3c54cdc4b68b39fb0a270a771d4449f5.tar.bz2
scala-7233c24d3c54cdc4b68b39fb0a270a771d4449f5.zip
Improved type inference for method signatures.
Added code for lifted expressions (but it is disabled)
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Namers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala77
1 files changed, 62 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 25b30c9c35..3210b3982f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -407,24 +407,71 @@ trait Namers requires Analyzer {
private def methodSig(tparams: List[AbsTypeDef], vparamss: List[List[ValDef]],
tpt: Tree, rhs: Tree): Type = {
val meth = context.owner
+
val tparamSyms = typer.reenterTypeParams(tparams)
val vparamSymss = enterValueParams(meth, vparamss)
- val restype =
- if (tpt.isEmpty) {
- tpt.tpe = if (meth.name == nme.CONSTRUCTOR) context.enclClass.owner.tpe
- else deconstIfNotFinal(meth, typer.computeType(rhs));
- tpt.tpe
- } else typer.typedType(tpt).tpe;
- def mkMethodType(vparams: List[Symbol], restpe: Type) = {
- val formals = vparams map (.tpe);
- if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT)) ImplicitMethodType(formals, restpe)
- else MethodType(formals, restpe);
+ if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) tpt.tpe = context.enclClass.owner.tpe
+
+ def makeMethodType(vparams: List[Symbol], restpe: Type) = {
+ val formals = vparams map (.tpe);
+ if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT)) ImplicitMethodType(formals, restpe)
+ else MethodType(formals, restpe);
}
- makePolyType(
- tparamSyms,
- if (vparamSymss.isEmpty) PolyType(List(), restype)
- else (vparamSymss :\ restype)(mkMethodType))
- }
+
+ def thisMethodType(restype: Type) =
+ makePolyType(
+ tparamSyms,
+ if (vparamSymss.isEmpty) PolyType(List(), restype)
+ else (vparamSymss :\ restype)(makeMethodType))
+
+ if (meth.owner.isClass && (tpt.isEmpty || vparamss.exists(.exists(.tpt.isEmpty)))) {
+ // try to complete from matching definition in base type
+ for (val vparams <- vparamss; val vparam <- vparams)
+ if (vparam.tpt.isEmpty) vparam.symbol setInfo WildcardType
+ val schema = thisMethodType(if (tpt.isEmpty) WildcardType else typer.typedType(tpt).tpe)
+ val site = meth.owner.thisType
+ val overridden = intersectionType(meth.owner.info.parents).member(meth.name).filter(sym =>
+ sym != NoSymbol && (site.memberType(sym) matches schema))
+ if (overridden != NoSymbol && !(overridden hasFlag OVERLOADED)) {
+ var pt = site.memberType(overridden) match {
+ case PolyType(tparams, rt) => rt.substSym(tparamSyms, tparams)
+ case mt => mt
+ }
+ for (val vparams <- vparamss) {
+ var pfs = pt.paramTypes
+ for (val vparam <- vparams) {
+ if (vparam.tpt.isEmpty) {
+ vparam.tpt.tpe = pfs.head
+ vparam.symbol setInfo pfs.head
+ }
+ pfs = pfs.tail
+ }
+ pt = pt.resultType
+ }
+ if (tpt.isEmpty) {
+ // provisionally assign `meth' a method type with inherited result type
+ // that way, we can leave out the result type even if method is recursive.
+ meth setInfo thisMethodType(
+ pt match {
+ case PolyType(List(), rtpe) => rtpe
+ case MethodType(List(), rtpe) => rtpe
+ case _ => pt
+ })
+ }
+ }
+ }
+
+ for (val vparams <- vparamss; val vparam <- vparams; vparam.tpt.isEmpty) {
+ context.error(vparam.pos, "missing parameter type")
+ vparam.tpt.tpe = ErrorType
+ }
+
+ thisMethodType(
+ if (tpt.isEmpty) {
+ tpt.tpe = deconstIfNotFinal(meth, typer.computeType(rhs));
+ tpt.tpe
+ } else typer.typedType(tpt).tpe)
+ }
/** If `sym' is an implicit value, check that its type signature `tp' is contractive.
* This means: The type of every implicit parameter is properly contained