Skip to content

Commit f6e1c03

Browse files
committed
Bugfix: Fix setup of overriding symbols
- Avoid accidental addition of capture set variables through traverseChildren of exact ValDefs and DefDefs. - Don't require that overriding symbols need explicit types if their capture set is non-empty. This is not needed since an overriding symbol with inferred type will get the type of the overridden symbol.
1 parent f194098 commit f6e1c03

File tree

4 files changed

+21
-24
lines changed

4 files changed

+21
-24
lines changed

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -884,12 +884,11 @@ class CheckCaptures extends Recheck, SymTransformer:
884884
val isLocal =
885885
sym.owner.ownersIterator.exists(_.isTerm)
886886
|| sym.accessBoundary(defn.RootClass).isContainedIn(sym.topLevelClass)
887-
def canUseInferred = // If canUseInferred is false, all capturing types in the type of `sym` need to be given explicitly
888-
sym.is(Private) // private symbols can always have inferred types
889-
|| // non-local symbols cannot have inferred types since external capture types are not inferred
890-
isLocal // local symbols still need an explicit types if
891-
&& !sym.owner.is(Trait) // - they are defined in a trait, since we do OverridingPairs checking before capture inference
892-
&& !sym.allOverriddenSymbols.nonEmpty // - they override some other symbol, since we do override checking before capture inference
887+
def canUseInferred = // If canUseInferred is false, all capturing types in the type of `sym` need to be given explicitly
888+
sym.is(Private) // private symbols can always have inferred types
889+
|| // non-local symbols cannot have inferred types since external capture types are not inferred
890+
isLocal // local symbols still need explicit types if
891+
&& !sym.owner.is(Trait) // they are defined in a trait, since we do OverridingPairs checking before capture inference
893892
def isNotPureThis(ref: CaptureRef) = ref match {
894893
case ref: ThisType => !ref.cls.isPureClass
895894
case _ => true

compiler/src/dotty/tools/dotc/cc/Setup.scala

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -385,20 +385,18 @@ extends tpd.TreeTraverser:
385385
return
386386
tree.tpt match
387387
case tpt: TypeTree if tree.symbol.allOverriddenSymbols.hasNext =>
388+
tree.paramss.foreach(traverse)
388389
transformTT(tpt, boxed = false, exact = true)
390+
traverse(tree.rhs)
389391
//println(i"TYPE of ${tree.symbol.showLocated} = ${tpt.knownType}")
390392
case _ =>
391-
traverseChildren(tree)
393+
traverseChildren(tree)
392394
case tree @ ValDef(_, tpt: TypeTree, _) =>
393-
val isVar = tree.symbol.is(Mutable)
394-
val overrides = tree.symbol.allOverriddenSymbols.hasNext
395-
//if overrides then println(i"transforming overriding ${tree.symbol}")
396-
if isVar || overrides then
397-
transformTT(tpt,
398-
boxed = isVar, // types of mutable variables are boxed
399-
exact = overrides // types of symbols that override a parent don't get a capture set
400-
)
401-
traverseChildren(tree)
395+
transformTT(tpt,
396+
boxed = tree.symbol.is(Mutable), // types of mutable variables are boxed
397+
exact = tree.symbol.allOverriddenSymbols.hasNext // types of symbols that override a parent don't get a capture set
398+
)
399+
traverse(tree.rhs)
402400
case tree @ TypeApply(fn, args) =>
403401
traverse(fn)
404402
for case arg: TypeTree <- args do

tests/neg-custom-args/captures/lazylist.check

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
| method tail of type -> {*} lazylists.LazyList[Nothing] has incompatible type
66
|
77
| longer explanation available when compiling with `-explain`
8+
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazylist.scala:17:15 -------------------------------------
9+
17 | def tail = xs() // error
10+
| ^^^^
11+
| Found: {LazyCons.this.xs} lazylists.LazyList[T]
12+
| Required: lazylists.LazyList[T]
13+
|
14+
| longer explanation available when compiling with `-explain`
815
-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/lazylist.scala:35:29 -------------------------------------
916
35 | val ref1c: LazyList[Int] = ref1 // error
1017
| ^^^^
@@ -33,10 +40,3 @@
3340
| Required: {cap1, ref3, cap3} lazylists.LazyList[Int]
3441
|
3542
| longer explanation available when compiling with `-explain`
36-
-- Error: tests/neg-custom-args/captures/lazylist.scala:17:6 -----------------------------------------------------------
37-
17 | def tail = xs() // error: cannot have an inferred type
38-
| ^^^^^^^^^^^^^^^
39-
| Non-local method tail cannot have an inferred result type
40-
| {LazyCons.this.xs} lazylists.LazyList[? T]
41-
| with non-empty capture set {LazyCons.this.xs}.
42-
| The type needs to be declared explicitly.

tests/neg-custom-args/captures/lazylist.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ abstract class LazyList[+T]:
1414
class LazyCons[+T](val x: T, val xs: () => {*} LazyList[T]) extends LazyList[T]:
1515
def isEmpty = false
1616
def head = x
17-
def tail = xs() // error: cannot have an inferred type
17+
def tail = xs() // error
1818

1919
object LazyNil extends LazyList[Nothing]:
2020
def isEmpty = true

0 commit comments

Comments
 (0)