Skip to content

Fix #8012: Disallow conversion to underspecified SAM type #8013

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 3 commits into from
Jan 17, 2020
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
22 changes: 13 additions & 9 deletions compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1099,16 +1099,20 @@ class Typer extends Namer
pt match {
case SAMType(sam)
if !defn.isFunctionType(pt) && mt <:< sam =>
// SAMs of the form C[?] where C is a class cannot be conversion targets.
// The resulting class `class $anon extends C[?] {...}` would be illegal,
// since type arguments to `C`'s super constructor cannot be constructed.
def isWildcardClassSAM =
!pt.classSymbol.is(Trait) && pt.argInfos.exists(_.isInstanceOf[TypeBounds])
val targetTpe =
if (!isFullyDefined(pt, ForceDegree.all))
if (pt.isRef(defn.PartialFunctionClass))
// Replace the underspecified expected type by one based on the closure method type
defn.PartialFunctionOf(mt.firstParamTypes.head, mt.resultType)
else {
ctx.error(ex"result type of lambda is an underspecified SAM type $pt", tree.sourcePos)
pt
}
else pt
if isFullyDefined(pt, ForceDegree.all) && !isWildcardClassSAM then
pt
else if pt.isRef(defn.PartialFunctionClass) then
// Replace the underspecified expected type by one based on the closure method type
defn.PartialFunctionOf(mt.firstParamTypes.head, mt.resultType)
else
ctx.error(ex"result type of lambda is an underspecified SAM type $pt", tree.sourcePos)
pt
if (pt.classSymbol.isOneOf(FinalOrSealed)) {
val offendingFlag = pt.classSymbol.flags & FinalOrSealed
ctx.error(ex"lambda cannot implement $offendingFlag ${pt.classSymbol}", tree.sourcePos)
Expand Down
13 changes: 13 additions & 0 deletions tests/neg/i8012.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@


@FunctionalInterface
abstract class Q[A] {
def apply(a: A): Int
}

class C extends Q[?] // error: Type argument must be fully defined

object O {
def m(i: Int): Int = i
val x: Q[_] = m // error: result type of lambda is an underspecified SAM type Q[?]
}