From 66532955a172313b18900ae2257db8ae7ff6e243 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 11 Feb 2019 19:11:41 +0100 Subject: [PATCH] Fix #5888: Disallow SAM type creation of final and sealed classes --- compiler/src/dotty/tools/dotc/core/Flags.scala | 3 +++ compiler/src/dotty/tools/dotc/typer/Typer.scala | 6 +++++- tests/neg/i5888.scala | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i5888.scala diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 3d1152784fc5..6baa7f6f65ad 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -638,6 +638,9 @@ object Flags { /** value that's final or inline */ final val FinalOrInline: FlagSet = Final | Inline + /** class that's final or sealed */ + final val FinalOrSealed: FlagSet = Final | Sealed + /** A covariant type parameter instance */ final val LocalCovariant: FlagConjunction = allOf(Local, Covariant) diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 327c9756bc44..fd6df929d16f 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -985,7 +985,11 @@ class Typer extends Namer case SAMType(sam) if !defn.isFunctionType(pt) && mt <:< sam => if (!isFullyDefined(pt, ForceDegree.all)) - ctx.error(ex"result type of closure is an underspecified SAM type $pt", tree.sourcePos) + ctx.error(ex"result type of lambda is an underspecified SAM type $pt", tree.sourcePos) + else if (pt.classSymbol.is(FinalOrSealed)) { + val offendingFlag = pt.classSymbol.flags & FinalOrSealed + ctx.error(ex"lambda cannot implement $offendingFlag ${pt.classSymbol}", tree.sourcePos) + } TypeTree(pt) case _ => if (mt.isParamDependent) { diff --git a/tests/neg/i5888.scala b/tests/neg/i5888.scala new file mode 100644 index 000000000000..c43d36cb2626 --- /dev/null +++ b/tests/neg/i5888.scala @@ -0,0 +1,8 @@ +val x: String <:< Int = _.toInt // error + +abstract final class Foo { def f(x: Int): Int } + +val foo: Foo = x => x // error + +val foo2: Foo = Predef.identity // error +