From 78d917393ea03ef94f892549f87cbc2cabba8ac6 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Thu, 23 Feb 2017 15:44:37 -0800 Subject: SI-10206 tighten fix for SI-6889 There are more supertypes of `AnyRef` than you might think: `?{def clone: ?}` is one example... --- test/files/neg/t6889.check | 7 +++++-- test/files/neg/t6889.scala | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/files/neg/t6889.check b/test/files/neg/t6889.check index a77e8a010c..c14c3b09c0 100644 --- a/test/files/neg/t6889.check +++ b/test/files/neg/t6889.check @@ -1,7 +1,10 @@ t6889.scala:16: error: the result type of an implicit conversion must be more specific than AnyRef def f(x: Dingo): AnyRef = x // fail - no conversion to AnyRef ^ -t6889.scala:17: error: an expression of type Null is ineligible for implicit conversion +t6889.scala:17: error: the result type of an implicit conversion must be more specific than Object + def f2(x: Dingo): Object = x // fail - no conversion to Object + ^ +t6889.scala:18: error: an expression of type Null is ineligible for implicit conversion var x: Int = null // fail - no conversion from Null ^ -two errors found +three errors found diff --git a/test/files/neg/t6889.scala b/test/files/neg/t6889.scala index ef1963669c..3fc235bf7e 100644 --- a/test/files/neg/t6889.scala +++ b/test/files/neg/t6889.scala @@ -14,5 +14,6 @@ object Test { trait Dingo extends Any with bippy.Bippy[foo.unrelated.Unrelated] def f(x: Dingo): AnyRef = x // fail - no conversion to AnyRef + def f2(x: Dingo): Object = x // fail - no conversion to Object var x: Int = null // fail - no conversion from Null } -- cgit v1.2.3 From 849d09b9e10d025df7f91494315f927f68bc9dd6 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 24 Feb 2017 09:37:20 +1000 Subject: Test case for SI-10206 Implicit search implements a restriction that the target type for an implicit view should be more specific that AnyRef or AnyVal. scala> def foo(s: String): AnyVal = s :12: error: the result type of an implicit conversion must be more specific than AnyVal def foo(s: String): AnyVal = s ^ Without this, an implicit value classes over `String` would be applied, which is unlikely to be what was intended. Implicit views are implemented as an implicit search for a function type with a structural type as its result. This structural type is created with: scala> val schema = analyzer.HasMethodMatching.apply(TermName("clone"), Nil, WildcardType) schema: $r.intp.global.analyzer.global.Type = ?{def clone(): ?} The quirk arises when, as above, we're seeking a member with the same name as a member of AnyRef. AnyRef is seen to be a subtype of the result type: scala> AnyRefClass.tpe <:< schema res23: Boolean = true Which leads to the implicit in the test case being disqualified. The typer opts to report the error about the inapplicability of the inherited clone method, so we don't even know why the implicit was discarded. --- test/files/pos/t10206.scala | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/files/pos/t10206.scala (limited to 'test') diff --git a/test/files/pos/t10206.scala b/test/files/pos/t10206.scala new file mode 100644 index 0000000000..3ddd1ea2fd --- /dev/null +++ b/test/files/pos/t10206.scala @@ -0,0 +1,15 @@ +class Foo(val bar: String) + +object Foo { + implicit class Enrich(foo: Foo) { + def clone(x: Int, y: Int): Int = x + y + } +} + +object Main extends App { + val foo = new Foo("hello") + println(foo.clone(1, 2)) // <- does not compile + // the implicit view was being disqualified because a new check in the compiler + // that implicit views must not target Any or AnyRef considered an implicit search + // for `foo.type => ?{def clone: ?}` to targeted AnyRef. +} -- cgit v1.2.3