Skip to content

Commit 5816057

Browse files
committed
Make explicit arguments for context bounds an error from 3.5
1 parent bde6bf3 commit 5816057

File tree

5 files changed

+105
-24
lines changed

5 files changed

+105
-24
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,8 @@ object desugar {
674674
val nu = vparamss.foldLeft(makeNew(classTypeRef)) { (nu, vparams) =>
675675
val app = Apply(nu, vparams.map(refOfDef))
676676
vparams match {
677-
case vparam :: _ if vparam.mods.is(Given) => app.setApplyKind(ApplyKind.Using)
677+
case vparam :: _ if vparam.mods.is(Given) || vparam.name.is(ContextBoundParamName) =>
678+
app.setApplyKind(ApplyKind.Using)
678679
case _ => app
679680
}
680681
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package dotty.tools
2+
package dotc
3+
package typer
4+
5+
import core.*
6+
import ast.*
7+
import Contexts.*
8+
import Types.*
9+
import Flags.*
10+
import Names.*
11+
import StdNames.*
12+
import Symbols.*
13+
import Trees.*
14+
import ProtoTypes.*
15+
import Decorators.*
16+
import config.MigrationVersion
17+
import config.Feature.{sourceVersion, migrateTo3}
18+
import config.SourceVersion.*
19+
import reporting.*
20+
import NameKinds.ContextBoundParamName
21+
import rewrites.Rewrites.patch
22+
import util.Spans.Span
23+
24+
/** A utility module containing source-dependent deprecation messages
25+
* and migrations
26+
*/
27+
object Migrations:
28+
29+
import tpd.*
30+
31+
/** Flag & migrate `?` used as a higher-kinded type parameter
32+
* Warning in 3.0-migration, error from 3.0
33+
*/
34+
def migrateKindProjectorQMark(tree: untpd.TypeDef, sym: Symbol)(using Context): Unit =
35+
if tree.name eq tpnme.? then
36+
val addendum = if sym.owner.is(TypeParam)
37+
then ", use `_` to denote a higher-kinded type parameter"
38+
else ""
39+
val namePos = tree.sourcePos.withSpan(tree.nameSpan)
40+
report.errorOrMigrationWarning(
41+
em"`?` is not a valid type name$addendum", namePos, MigrationVersion.Scala2to3)
42+
43+
/** Flag & migrate explicit normal arguments to parameters coming from context bounds
44+
* Warning in 3.4, error in 3.5, rewrite in 3.5-migration.
45+
*/
46+
def migrateContextBoundParams(tree: Tree, tp: Type, pt: FunProto)(using Context): Unit =
47+
def isContextBoundParams = tp.stripPoly match
48+
case MethodType(ContextBoundParamName(_) :: _) => true
49+
case _ => false
50+
if sourceVersion.isAtLeast(`3.4`)
51+
&& isContextBoundParams
52+
&& pt.applyKind != ApplyKind.Using
53+
then
54+
def rewriteMsg = Message.rewriteNotice("This code", `3.5-migration`)
55+
report.errorOrMigrationWarning(
56+
em"""Context bounds will map to context parameters.
57+
|A `using` clause is needed to pass explicit arguments to them.$rewriteMsg""",
58+
tree.srcPos, MigrationVersion(`3.4`, `3.5`))
59+
if sourceVersion.isAtLeast(`3.5-migration`) then
60+
patch(Span(pt.args.head.span.start), "using ")
61+
end migrateContextBoundParams

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

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import NullOpsDecorator.*
5151
import cc.CheckCaptures
5252
import config.Config
5353
import config.MigrationVersion
54+
import Migrations.*
5455

5556
import scala.annotation.constructorOnly
5657
import dotty.tools.dotc.rewrites.Rewrites
@@ -3137,13 +3138,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
31373138
case tree: untpd.TypeDef =>
31383139
// separate method to keep dispatching method `typedNamed` short which might help the JIT
31393140
def typedTypeOrClassDef: Tree =
3140-
if tree.name eq tpnme.? then
3141-
val addendum = if sym.owner.is(TypeParam)
3142-
then ", use `_` to denote a higher-kinded type parameter"
3143-
else ""
3144-
val namePos = tree.sourcePos.withSpan(tree.nameSpan)
3145-
report.errorOrMigrationWarning(
3146-
em"`?` is not a valid type name$addendum", namePos, MigrationVersion.Scala2to3)
3141+
migrateKindProjectorQMark(tree, sym)
31473142
if tree.isClassDef then
31483143
typedClassDef(tree, sym.asClass)(using ctx.localContext(tree, sym))
31493144
else
@@ -3818,24 +3813,12 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
38183813
def adaptToArgs(wtp: Type, pt: FunProto): Tree = wtp match {
38193814
case wtp: MethodOrPoly =>
38203815
def methodStr = methPart(tree).symbol.showLocated
3821-
if (matchingApply(wtp, pt))
3816+
if matchingApply(wtp, pt) then
3817+
migrateContextBoundParams(tree, wtp, pt)
38223818
if needsTupledDual(wtp, pt) then adapt(tree, pt.tupledDual, locked)
38233819
else tree
38243820
else if wtp.isContextualMethod then
3825-
def isContextBoundParams = wtp.stripPoly match
3826-
case MethodType(ContextBoundParamName(_) :: _) => true
3827-
case _ => false
3828-
if sourceVersion == `future-migration` && isContextBoundParams && pt.args.nonEmpty
3829-
then // Under future-migration, don't infer implicit arguments yet for parameters
3830-
// coming from context bounds. Issue a warning instead and offer a patch.
3831-
def rewriteMsg = Message.rewriteNotice("This code", `future-migration`)
3832-
report.migrationWarning(
3833-
em"""Context bounds will map to context parameters.
3834-
|A `using` clause is needed to pass explicit arguments to them.$rewriteMsg""", tree.srcPos)
3835-
patch(Span(pt.args.head.span.start), "using ")
3836-
tree
3837-
else
3838-
adaptNoArgs(wtp) // insert arguments implicitly
3821+
adaptNoArgs(wtp) // insert arguments implicitly
38393822
else if (tree.symbol.isPrimaryConstructor && tree.symbol.info.firstParamTypes.isEmpty)
38403823
readapt(tree.appliedToNone) // insert () to primary constructors
38413824
else
@@ -4441,7 +4424,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
44414424
protected def matchingApply(methType: MethodOrPoly, pt: FunProto)(using Context): Boolean =
44424425
val isUsingApply = pt.applyKind == ApplyKind.Using
44434426
methType.isContextualMethod == isUsingApply
4444-
|| methType.isImplicitMethod && isUsingApply // for a transition allow `with` arguments for regular implicit parameters
4427+
|| methType.isImplicitMethod && isUsingApply // for a transition allow `using` arguments for regular implicit parameters
44454428

44464429
/** Check that `tree == x: pt` is typeable. Used when checking a pattern
44474430
* against a selector of type `pt`. This implementation accounts for
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//> using options -Xfatal-warnings
2+
3+
class C[T]
4+
def foo[X: C] = ()
5+
6+
given [T]: C[T] = C[T]()
7+
8+
def Test =
9+
foo(C[Int]()) // error
10+
foo(using C[Int]()) // ok

tests/neg/hidden-type-errors.check

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
-- Warning: tests/neg/hidden-type-errors/Test.scala:8:24 ---------------------------------------------------------------
2+
8 | val x = X.doSomething("XXX") // error
3+
| ^^^^^^^^^^^^^^^^^^^^
4+
| Context bounds will map to context parameters.
5+
| A `using` clause is needed to pass explicit arguments to them.
6+
| This code can be rewritten automatically under -rewrite -source 3.5-migration.
7+
|--------------------------------------------------------------------------------------------------------------------
8+
|Inline stack trace
9+
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
10+
|This location contains code that was inlined from Macro.scala:15
11+
15 | doSomethingImpl('x)
12+
| ^^^^^^^^^^^^^^^^^^^
13+
--------------------------------------------------------------------------------------------------------------------
114
-- [E007] Type Mismatch Error: tests/neg/hidden-type-errors/Test.scala:8:24 --------------------------------------------
215
8 | val x = X.doSomething("XXX") // error
316
| ^^^^^^^^^^^^^^^^^^^^
@@ -18,3 +31,16 @@
1831
|
1932
| The tests were made under the empty constraint
2033
---------------------------------------------------------------------------------------------------------------------
34+
-- Warning: tests/neg/hidden-type-errors/Test.scala:8:24 ---------------------------------------------------------------
35+
8 | val x = X.doSomething("XXX") // error
36+
| ^^^^^^^^^^^^^^^^^^^^
37+
| Context bounds will map to context parameters.
38+
| A `using` clause is needed to pass explicit arguments to them.
39+
| This code can be rewritten automatically under -rewrite -source 3.5-migration.
40+
|--------------------------------------------------------------------------------------------------------------------
41+
|Inline stack trace
42+
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
43+
|This location contains code that was inlined from Macro.scala:15
44+
15 | doSomethingImpl('x)
45+
| ^^^^^^^^^^^^^^^^^^^
46+
--------------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)