Skip to content

Commit e60aa9e

Browse files
committed
Turn given loop prevention on for -source future
Drop the experimental language import. I believe everybody agrees that this is a desirable improvement, and type inference and implicit search have traditionally been in the realm of the compiler implementers. Experimental language imports have to live forever (albeit as deprecated once the feature is accepted as standard). So they are rather heavyweight and it is unergonomic to require them for smallish improvements to type inference. The new road map is as follows: - In 3.4: warning if behavior would change in the future. - In 3.5: error if behavior would change in the future - In 3.future (at the earliest 3.6): new behavior.
1 parent 708e640 commit e60aa9e

File tree

9 files changed

+43
-50
lines changed

9 files changed

+43
-50
lines changed

compiler/src/dotty/tools/dotc/config/Feature.scala

-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ object Feature:
3333
val pureFunctions = experimental("pureFunctions")
3434
val captureChecking = experimental("captureChecking")
3535
val into = experimental("into")
36-
val givenLoopPrevention = experimental("givenLoopPrevention")
3736

3837
val globalOnlyImports: Set[TermName] = Set(pureFunctions, captureChecking)
3938

compiler/src/dotty/tools/dotc/typer/Implicits.scala

+3-2
Original file line numberDiff line numberDiff line change
@@ -1595,7 +1595,7 @@ trait Implicits:
15951595

15961596
def checkResolutionChange(result: SearchResult) =
15971597
if (eligible ne preEligible)
1598-
&& !Feature.enabled(Feature.givenLoopPrevention)
1598+
&& !sourceVersion.isAtLeast(SourceVersion.future)
15991599
then
16001600
val prevResult = searchImplicit(preEligible, contextual)
16011601
prevResult match
@@ -1621,7 +1621,8 @@ trait Implicits:
16211621
|Current result ${showResult(prevResult)} will be no longer eligible
16221622
| because it is not defined before the search position.
16231623
|Result with new rules: ${showResult(result)}.
1624-
|To opt into the new rules, use the `experimental.givenLoopPrevention` language import.
1624+
|To opt into the new rules, compile with `-source future` or use
1625+
|the `scala.language.future` language import.
16251626
|
16261627
|To fix the problem without the language import, you could try one of the following:
16271628
| - use a `given ... with` clause as the enclosing given,

library/src/scala/runtime/stdLibPatches/language.scala

-9
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,6 @@ object language:
9191
@compileTimeOnly("`into` can only be used at compile time in import statements")
9292
object into
9393

94-
/** Experimental support for new given resolution rules that avoid looping
95-
* givens. By the new rules, a given may not implicitly use itself or givens
96-
* defined after it.
97-
*
98-
* @see [[https://dotty.epfl.ch/docs/reference/experimental/given-loop-prevention]]
99-
*/
100-
@compileTimeOnly("`givenLoopPrevention` can only be used at compile time in import statements")
101-
object givenLoopPrevention
102-
10394
/** Was needed to add support for relaxed imports of extension methods.
10495
* The language import is no longer needed as this is now a standard feature since SIP was accepted.
10596
* @see [[http://dotty.epfl.ch/docs/reference/contextual/extension-methods]]

tests/neg/i15474.check

+23-21
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,31 @@
11
-- Error: tests/neg/i15474.scala:6:39 ----------------------------------------------------------------------------------
22
6 | given c: Conversion[ String, Int ] = _.toInt // error
33
| ^
4-
| Result of implicit search for ?{ toInt: ? } will change.
5-
| Current result Test2.c will be no longer eligible
6-
| because it is not defined before the search position.
7-
| Result with new rules: augmentString.
8-
| To opt into the new rules, use the `experimental.givenLoopPrevention` language import.
4+
| Result of implicit search for ?{ toInt: ? } will change.
5+
| Current result Test2.c will be no longer eligible
6+
| because it is not defined before the search position.
7+
| Result with new rules: augmentString.
8+
| To opt into the new rules, compile with `-source future` or use
9+
| the `scala.language.future` language import.
910
|
10-
| To fix the problem without the language import, you could try one of the following:
11-
| - use a `given ... with` clause as the enclosing given,
12-
| - rearrange definitions so that Test2.c comes earlier,
13-
| - use an explicit conversion,
14-
| - use an import to get extension method into scope.
15-
| This will be an error in Scala 3.5 and later.
11+
| To fix the problem without the language import, you could try one of the following:
12+
| - use a `given ... with` clause as the enclosing given,
13+
| - rearrange definitions so that Test2.c comes earlier,
14+
| - use an explicit conversion,
15+
| - use an import to get extension method into scope.
16+
| This will be an error in Scala 3.5 and later.
1617
-- Error: tests/neg/i15474.scala:12:56 ---------------------------------------------------------------------------------
1718
12 | given Ordering[Price] = summon[Ordering[BigDecimal]] // error
1819
| ^
19-
| Result of implicit search for Ordering[BigDecimal] will change.
20-
| Current result Prices.Price.given_Ordering_Price will be no longer eligible
21-
| because it is not defined before the search position.
22-
| Result with new rules: scala.math.Ordering.BigDecimal.
23-
| To opt into the new rules, use the `experimental.givenLoopPrevention` language import.
20+
| Result of implicit search for Ordering[BigDecimal] will change.
21+
| Current result Prices.Price.given_Ordering_Price will be no longer eligible
22+
| because it is not defined before the search position.
23+
| Result with new rules: scala.math.Ordering.BigDecimal.
24+
| To opt into the new rules, compile with `-source future` or use
25+
| the `scala.language.future` language import.
2426
|
25-
| To fix the problem without the language import, you could try one of the following:
26-
| - use a `given ... with` clause as the enclosing given,
27-
| - rearrange definitions so that Prices.Price.given_Ordering_Price comes earlier,
28-
| - use an explicit argument.
29-
| This will be an error in Scala 3.5 and later.
27+
| To fix the problem without the language import, you could try one of the following:
28+
| - use a `given ... with` clause as the enclosing given,
29+
| - rearrange definitions so that Prices.Price.given_Ordering_Price comes earlier,
30+
| - use an explicit argument.
31+
| This will be an error in Scala 3.5 and later.

tests/neg/i6716.check

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
-- Error: tests/neg/i6716.scala:12:39 ----------------------------------------------------------------------------------
22
12 | given Monad[Bar] = summon[Monad[Foo]] // error
33
| ^
4-
| Result of implicit search for Monad[Foo] will change.
5-
| Current result Bar.given_Monad_Bar will be no longer eligible
6-
| because it is not defined before the search position.
7-
| Result with new rules: Foo.given_Monad_Foo.
8-
| To opt into the new rules, use the `experimental.givenLoopPrevention` language import.
4+
| Result of implicit search for Monad[Foo] will change.
5+
| Current result Bar.given_Monad_Bar will be no longer eligible
6+
| because it is not defined before the search position.
7+
| Result with new rules: Foo.given_Monad_Foo.
8+
| To opt into the new rules, compile with `-source future` or use
9+
| the `scala.language.future` language import.
910
|
10-
| To fix the problem without the language import, you could try one of the following:
11-
| - use a `given ... with` clause as the enclosing given,
12-
| - rearrange definitions so that Bar.given_Monad_Bar comes earlier,
13-
| - use an explicit argument.
14-
| This will be an error in Scala 3.5 and later.
11+
| To fix the problem without the language import, you could try one of the following:
12+
| - use a `given ... with` clause as the enclosing given,
13+
| - rearrange definitions so that Bar.given_Monad_Bar comes earlier,
14+
| - use an explicit argument.
15+
| This will be an error in Scala 3.5 and later.

tests/neg/i7294-a.check

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
| Current result foo.Test.f will be no longer eligible
1515
| because it is not defined before the search position.
1616
| Result with new rules: No Matching Implicit.
17-
| To opt into the new rules, use the `experimental.givenLoopPrevention` language import.
17+
| To opt into the new rules, compile with `-source future` or use
18+
| the `scala.language.future` language import.
1819
|
1920
| To fix the problem without the language import, you could try one of the following:
2021
| - use a `given ... with` clause as the enclosing given,

tests/pos/i15474.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//> using options -Xfatal-warnings
22
import scala.language.implicitConversions
3-
import scala.language.experimental.givenLoopPrevention
3+
import scala.language.future
44

55
object Test2:
66
given c: Conversion[ String, Int ] = _.toInt // now avoided, was loop not detected, could be used as a fallback to avoid the warning.

tests/pos/looping-givens.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import language.experimental.givenLoopPrevention
1+
import language.future
22

33
class A
44
class B

tests/run/i6716.scala

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
//> using options -Xfatal-warnings
2-
3-
import scala.language.experimental.givenLoopPrevention
1+
//> using options -Xfatal-warnings -source future
42

53
trait Monad[T]:
64
def id: String
@@ -11,7 +9,7 @@ object Foo {
119

1210
opaque type Bar = Foo
1311
object Bar {
14-
given Monad[Bar] = summon[Monad[Foo]] // was error, fixed by givenLoopPrevention
12+
given Monad[Bar] = summon[Monad[Foo]] // was error, fixed by given loop prevention
1513
}
1614

1715
object Test extends App {

0 commit comments

Comments
 (0)