aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala13
-rw-r--r--src/dotty/tools/dotc/typer/Applications.scala10
-rw-r--r--src/dotty/tools/dotc/typer/ProtoTypes.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala7
-rw-r--r--tests/pos/i1378.scala3
5 files changed, 33 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index c1efd0b0b..55eb21687 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -278,7 +278,18 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
}
trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] =>
- // todo: fill with methods from TreeInfo that only apply to untpd.Tree's
+ import TreeInfo._
+
+ def isFunctionWithImplicitParamType(tree: Tree) = tree match {
+ case untpd.Function(args, _) =>
+ args.exists {
+ case ValDef(_, tpt, _) => tpt.isEmpty
+ case _ => false
+ }
+ case _ => false
+ }
+
+ // todo: fill with other methods from TreeInfo that only apply to untpd.Tree's
}
trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
diff --git a/src/dotty/tools/dotc/typer/Applications.scala b/src/dotty/tools/dotc/typer/Applications.scala
index 6e78a570d..7a742112b 100644
--- a/src/dotty/tools/dotc/typer/Applications.scala
+++ b/src/dotty/tools/dotc/typer/Applications.scala
@@ -553,6 +553,16 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
// a modified tree but this would be more convoluted and less efficient.
if (proto.isTupled) proto = proto.tupled
+ // If some of the application's arguments are function literals without explicitly declared
+ // parameter types, and the expected type is a value type, relate the
+ // normalized result type of the application with the expected type through `<:<`.
+ // This can add more constraints which help sharpen the inferred parameter
+ // types for the argument function literal(s).
+ // This tweak is needed to make i1348 compile.
+ if (tree.args.exists(untpd.isFunctionWithImplicitParamType(_)))
+ if (!constrainResult(fun1.tpe.widen, proto.derivedFunProto(resultType = pt)))
+ typr.println(i"result failure for $tree with type ${fun1.tpe.widen}, expected = $pt")
+
fun1.tpe match {
case ErrorType => tree.withType(ErrorType)
case TryDynamicCallType =>
diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala
index a430d5f75..767ccbe7d 100644
--- a/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -175,7 +175,7 @@ object ProtoTypes {
def isMatchedBy(tp: Type)(implicit ctx: Context) =
typer.isApplicable(tp, Nil, typedArgs, resultType)
- def derivedFunProto(args: List[untpd.Tree], resultType: Type, typer: Typer) =
+ def derivedFunProto(args: List[untpd.Tree] = this.args, resultType: Type, typer: Typer = this.typer) =
if ((args eq this.args) && (resultType eq this.resultType) && (typer eq this.typer)) this
else new FunProto(args, resultType, typer)
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 11a7b6753..13b6167b1 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -597,6 +597,13 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
untpd.TypeTree(defn.FunctionClass(args.length).typeRef), args :+ body), pt)
else {
val params = args.asInstanceOf[List[untpd.ValDef]]
+
+ pt match {
+ case pt: TypeVar if untpd.isFunctionWithImplicitParamType(tree) =>
+ isFullyDefined(pt, ForceDegree.noBottom)
+ case _ =>
+ }
+
val (protoFormals, protoResult) = decomposeProtoFunction(pt, params.length)
def refersTo(arg: untpd.Tree, param: untpd.ValDef): Boolean = arg match {
diff --git a/tests/pos/i1378.scala b/tests/pos/i1378.scala
new file mode 100644
index 000000000..31475daf2
--- /dev/null
+++ b/tests/pos/i1378.scala
@@ -0,0 +1,3 @@
+object Test {
+ (1, x => 2): (Int, Int => Int)
+}