Skip to content

Use WildcardType in place of a type variable in pretypeArgs #3974

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Applications.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1459,7 +1459,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
fn.get.isInstanceOf[untpd.Match] &&
formalsForArg.exists(_.isRef(defn.PartialFunctionClass))
val commonFormal =
if (isPartial) defn.PartialFunctionOf(commonParamTypes.head, newTypeVar(TypeBounds.empty))
if (isPartial) defn.PartialFunctionOf(commonParamTypes.head, WildcardType)
else defn.FunctionOf(commonParamTypes, WildcardType)
overload.println(i"pretype arg $arg with expected type $commonFormal")
pt.typedArg(arg, commonFormal)(ctx.addMode(Mode.ImplicitsEnabled))
Expand Down
18 changes: 18 additions & 0 deletions tests/pos/overloaded.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,40 @@ object overloaded {
val r2 = map(x => x.toInt)
val t2: Seq[Int] = r2

val rp1 = map { case x => x.toUpper }
val tp1: String = rp1
val rp2 = map { case x => x.toInt }
val tp2: Seq[Int] = rp2

def flatMap(f: Char => String): String = ???
def flatMap[U](f: Char => Seq[U]): Seq[U] = ???
val r3 = flatMap(x => x.toString)
val t3: String = r3
val r4 = flatMap(x => List(x))
val t4: Seq[Char] = r4

val rp3 = flatMap { case x => x.toString }
val tp3: String = rp3
val rp4 = flatMap { case x => List(x) }
val tp4: Seq[Char] = rp4

def bar(f: (Char, Char) => Unit): Unit = ???
def bar(f: Char => Unit) = ???
bar((x, y) => ())
bar (x => ())
// bar { case (x, y) => () } // error: cannot test if value types are references
bar { case x => () }

def combine(f: (Char, Int) => Int): Int = ???
def combine(f: (String, Int) => String): String = ???
val r5 = combine((x: Char, y) => x + y)
val t5: Int = r5
val r6 = combine((x: String, y) => x ++ y.toString)
val t6: String = r6

// Errors: The argument types of an anonymous function must be fully known
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@odersky Is this intended? Should I open an issue for it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine; we don't look inside tuples here. What does scalac say?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on Scala 2.13.0-M2:

[error] constructor cannot be instantiated to expected type;
[error]  found   : (T1, T2)
[error]  required: Char
[error]   bar { case (x, y) => () }
[error]              ^

[warn] match may not be exhaustive.
[warn] It would fail on the following input: (_, _)
[warn]   val rp5 = combine { case (x: Char, y) => x + y }
[warn]                     ^

[warn] match may not be exhaustive.
[warn] It would fail on the following input: (_, _)
[warn]   val rp6 = combine { case (x: String, y) => x ++ y.toString }
[warn]                     ^
[warn] two warnings found

In two out of tree of the cases scalac is able to find the correct overload. It emits a spurious exhaustivity warning though

// val rp5 = combine { case (x: Char, y) => x + y }
// val tp5: Int = rp5
// val rp6 = combine { case (x: String, y) => x ++ y.toString }
// val tp6: String = rp6
}