Skip to content

Commit 8ac889f

Browse files
committed
Handle byname parameters
1 parent b62635f commit 8ac889f

File tree

5 files changed

+59
-18
lines changed

5 files changed

+59
-18
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,14 @@ class Compiler {
7979
new RefChecks, // Various checks mostly related to abstract members and overriding
8080
new TryCatchPatterns, // Compile cases in try/catch
8181
new PatternMatcher) :: // Compile pattern matches
82+
List(new PreRecheck) :: // Preparations for check captures phase, enabled under -Ycc
83+
List(new CheckCaptures) :: // Check captures, enabled under -Ycc
8284
List(new ElimOpaque, // Turn opaque into normal aliases
8385
new sjs.ExplicitJSClasses, // Make all JS classes explicit (Scala.js only)
8486
new ExplicitOuter, // Add accessors to outer classes from nested ones.
8587
new ExplicitSelf, // Make references to non-trivial self types explicit as casts
8688
new ElimByName, // Expand by-name parameter references
8789
new StringInterpolatorOpt) :: // Optimizes raw and s string interpolators by rewriting them to string concatenations
88-
List(new PreRecheck) :: // Preparations for check captures phase, enabled under -Ycc
89-
List(new CheckCaptures) :: // Check captures, enabled under -Ycc
9090
List(new PruneErasedDefs, // Drop erased definitions from scopes and simplify erased expressions
9191
new UninitializedDefs, // Replaces `compiletime.uninitialized` by `_`
9292
new InlinePatterns, // Remove placeholders of inlined patterns

compiler/src/dotty/tools/dotc/transform/Recheck.scala

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
199199
if !tree.rhs.isEmpty then recheck(tree.rhs, sym.info)
200200

201201
def recheckDefDef(tree: DefDef, sym: Symbol)(using Context): Unit =
202-
val rhsCtx = linkConstructorParams(sym)
202+
val rhsCtx = linkConstructorParams(sym).withOwner(sym)
203203
if !tree.rhs.isEmpty && !sym.isInlineMethod && !sym.isEffectivelyErased then
204204
inContext(rhsCtx) { recheck(tree.rhs, recheck(tree.tpt)) }
205205

@@ -354,7 +354,7 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
354354
* @param tree the original tree
355355
* @param pt the expected result type
356356
*/
357-
def recheck(tree: Tree, pt: Type = WildcardType)(using Context): Type = trace(i"rechecking $tree with pt = $pt", recheckr, show = true) {
357+
def recheckStart(tree: Tree, pt: Type = WildcardType)(using Context): Type =
358358

359359
def recheckNamed(tree: NameTree, pt: Type)(using Context): Type =
360360
val sym = tree.symbol
@@ -397,18 +397,23 @@ abstract class Recheck extends Phase, IdentityDenotTransformer:
397397
case tree: PackageDef => recheckPackageDef(tree)
398398
case tree: Thicket => defn.NothingType
399399

400-
try
401-
val result = tree match
402-
case tree: NameTree => recheckNamed(tree, pt)
403-
case tree => recheckUnnamed(tree, pt)
404-
checkConforms(result, pt, tree)
405-
if keepTypes then result.rememberFor(tree)
406-
result
407-
catch case ex: Exception =>
408-
println(i"error while rechecking $tree")
409-
throw ex
410-
}
411-
end recheck
400+
tree match
401+
case tree: NameTree => recheckNamed(tree, pt)
402+
case tree => recheckUnnamed(tree, pt)
403+
end recheckStart
404+
405+
def recheckFinish(tpe: Type, tree: Tree, pt: Type)(using Context): Type =
406+
checkConforms(tpe, pt, tree)
407+
if keepTypes then tpe.rememberFor(tree)
408+
tpe
409+
410+
def recheck(tree: Tree, pt: Type = WildcardType)(using Context): Type =
411+
trace(i"rechecking $tree with pt = $pt", recheckr, show = true) {
412+
try recheckFinish(recheckStart(tree, pt), tree, pt)
413+
catch case ex: Exception =>
414+
println(i"error while rechecking $tree")
415+
throw ex
416+
}
412417

413418
private val debugSuccesses = false
414419

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

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,25 @@ class CheckCaptures extends Recheck:
364364
.showing(i"constr type $mt with $argTypes%, % in $cls = $result", capt)
365365
else ownType
366366

367+
def recheckByNameArg(tree: Tree, pt: Type)(using Context): Type =
368+
val closureDef(mdef) = tree
369+
val arg = mdef.rhs
370+
val localSet = CaptureSet.Var()
371+
curEnv = Env(mdef.symbol, localSet, isBoxed = false, curEnv)
372+
val result =
373+
try
374+
inContext(ctx.withOwner(mdef.symbol)) {
375+
recheckStart(arg, pt).capturing(localSet)
376+
}
377+
finally curEnv = curEnv.outer
378+
recheckFinish(result, arg, pt)
379+
367380
override def recheckApply(tree: Apply, pt: Type)(using Context): Type =
368-
includeCallCaptures(tree.symbol, tree.srcPos)
369-
super.recheckApply(tree, pt)
381+
if tree.symbol == defn.cbnArg then
382+
recheckByNameArg(tree.args(0), pt)
383+
else
384+
includeCallCaptures(tree.symbol, tree.srcPos)
385+
super.recheckApply(tree, pt)
370386

371387
override def recheck(tree: Tree, pt: Type = WildcardType)(using Context): Type =
372388
val res = super.recheck(tree, pt)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class CC
2+
type Cap = {*} CC
3+
4+
def test(cap1: Cap, cap2: Cap) =
5+
def f() = if cap1 == cap1 then g else g
6+
def g(x: Int) = if cap2 == cap2 then 1 else x
7+
def h(ff: => {cap2} Int => Int) = ff
8+
h(f()) // error
9+
10+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class CC
2+
type Cap = {*} CC
3+
4+
class I
5+
6+
def test(cap1: Cap, cap2: Cap): {cap1} I =
7+
def f() = if cap1 == cap1 then I() else I()
8+
def h(x: => {cap1} I) = x
9+
h(f())
10+

0 commit comments

Comments
 (0)