Skip to content

Commit 4d62692

Browse files
committed
Make some context bound evidence params tracked
Make context bound evidence params tracked if they have types with abstract type members.
1 parent d923cac commit 4d62692

File tree

6 files changed

+47
-21
lines changed

6 files changed

+47
-21
lines changed

compiler/src/dotty/tools/dotc/core/Symbols.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,6 @@ object Symbols extends SymUtils {
312312
* With the given setup, all such calls will give implicit-not found errors
313313
*/
314314
final def symbol(implicit ev: DontUseSymbolOnSymbol): Nothing = unsupported("symbol")
315-
type DontUseSymbolOnSymbol
316315

317316
final def source(using Context): SourceFile = {
318317
def valid(src: SourceFile): SourceFile =
@@ -402,13 +401,12 @@ object Symbols extends SymUtils {
402401
flags: FlagSet = this.flags,
403402
info: Type = this.info,
404403
privateWithin: Symbol = this.privateWithin,
405-
coord: Coord = NoCoord, // Can be `= owner.coord` once we bootstrap
406-
compUnitInfo: CompilationUnitInfo | Null = null // Can be `= owner.associatedFile` once we bootstrap
404+
coord: Coord = NoCoord, // Can be `= owner.coord` once we have new default args
405+
compUnitInfo: CompilationUnitInfo | Null = null // Can be `= owner.compilationUnitInfo` once we have new default args
407406
): Symbol = {
408407
val coord1 = if (coord == NoCoord) owner.coord else coord
409408
val compilationUnitInfo1 = if (compilationUnitInfo == null) owner.compilationUnitInfo else compilationUnitInfo
410409

411-
412410
if isClass then
413411
newClassSymbol(owner, name.asTypeName, flags, _ => info, privateWithin, coord1, compilationUnitInfo1)
414412
else
@@ -936,6 +934,8 @@ object Symbols extends SymUtils {
936934
case (x: Symbol) :: _ if x.isType => Some(xs.asInstanceOf[List[TypeSymbol]])
937935
case _ => None
938936

937+
type DontUseSymbolOnSymbol
938+
939939
// ----- Locating predefined symbols ----------------------------------------
940940

941941
def requiredPackage(path: PreName)(using Context): TermSymbol = {

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

+30
Original file line numberDiff line numberDiff line change
@@ -1885,6 +1885,28 @@ class Namer { typer: Typer =>
18851885
ddef.trailingParamss.foreach(completeParams)
18861886
val paramSymss = normalizeIfConstructor(ddef.paramss.nestedMap(symbolOfTree), isConstructor)
18871887
sym.setParamss(paramSymss)
1888+
1889+
/** We add `tracked` to context bound witnesses that have abstract type members */
1890+
def needsTracked(sym: Symbol, param: ValDef)(using Context) =
1891+
!sym.is(Tracked)
1892+
&& param.hasAttachment(ContextBoundParam)
1893+
&& sym.info.memberNames(abstractTypeNameFilter).nonEmpty
1894+
1895+
/** Set every context bound evidence parameter of a class to be tracked,
1896+
* provided it has a type that has an abstract type member. Reset private and local flags
1897+
* so that the parameter becomes a `val`.
1898+
*/
1899+
def setTracked(param: ValDef): Unit =
1900+
val sym = symbolOfTree(param)
1901+
sym.maybeOwner.maybeOwner.infoOrCompleter match
1902+
case info: TempClassInfo if needsTracked(sym, param) =>
1903+
typr.println(i"set tracked $param, $sym: ${sym.info} containing ${sym.info.memberNames(abstractTypeNameFilter).toList}")
1904+
for acc <- info.decls.lookupAll(sym.name) if acc.is(ParamAccessor) do
1905+
acc.resetFlag(PrivateLocal)
1906+
acc.setFlag(Tracked)
1907+
sym.setFlag(Tracked)
1908+
case _ =>
1909+
18881910
def wrapMethType(restpe: Type): Type =
18891911
instantiateDependent(restpe, paramSymss)
18901912
methodType(paramSymss, restpe, ddef.mods.is(JavaDefined))
@@ -1893,10 +1915,18 @@ class Namer { typer: Typer =>
18931915
wrapMethType(addParamRefinements(restpe, paramSymss))
18941916

18951917
if isConstructor then
1918+
if sym.isPrimaryConstructor && Feature.enabled(modularity) then
1919+
ddef.termParamss.foreach(_.foreach(setTracked))
18961920
// set result type tree to unit, but take the current class as result type of the symbol
18971921
typedAheadType(ddef.tpt, defn.UnitType)
18981922
wrapMethType(effectiveResultType(sym, paramSymss))
18991923
else if sym.isAllOf(Given | Method) && Feature.enabled(modularity) then
1924+
// set every context bound evidence parameter of a given companion method
1925+
// to be tracked, provided it has a type that has an abstract type member.
1926+
// Add refinements for all tracked parameters to the result type.
1927+
for params <- ddef.termParamss; param <- params do
1928+
val psym = symbolOfTree(param)
1929+
if needsTracked(psym, param) then psym.setFlag(Tracked)
19001930
valOrDefDefSig(ddef, sym, paramSymss, wrapRefinedMethType)
19011931
else
19021932
valOrDefDefSig(ddef, sym, paramSymss, wrapMethType)

tests/pos/hylolib-cb/AnyCollection.scala

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ final class AnyCollection[Element] private (
1414
object AnyCollection {
1515

1616
/** Creates an instance forwarding its operations to `base`. */
17-
def apply[Base](using b: Collection[Base])(base: Base): AnyCollection[b.Element] =
17+
def apply[Base: Collection as b](base: Base): AnyCollection[b.Element] =
1818
// NOTE: This evidence is redefined so the compiler won't report ambiguity between `intIsValue`
1919
// and `anyValueIsValue` when the method is called on a collection of `Int`s. None of these
2020
// choices is even correct! Note also that the ambiguity is suppressed if the constructor of
@@ -42,7 +42,7 @@ object AnyCollection {
4242

4343
}
4444

45-
given anyCollectionIsCollection[T](using tIsValue: Value[T]): Collection[AnyCollection[T]] with {
45+
given anyCollectionIsCollection[T: Value]: Collection[AnyCollection[T]] with {
4646

4747
type Element = T
4848
type Position = AnyValue

tests/pos/hylolib-cb/Collection.scala

+4-5
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ trait Collection[Self] {
8989

9090
}
9191

92-
extension [Self](self: Self)(using s: Collection[Self]) {
92+
extension [Self: Collection as s](self: Self) {
9393

9494
/** Returns the first element of `self` along with a slice containing the suffix after this
9595
* element, or `None` if `self` is empty.
@@ -148,7 +148,7 @@ extension [Self](self: Self)(using s: Collection[Self]) {
148148
* @complexity
149149
* O(n) where n is the number of elements in `self`.
150150
*/
151-
def map[T](using Value[T])(transform: (s.Element) => T): HyArray[T] =
151+
def map[T: Value](transform: (s.Element) => T): HyArray[T] =
152152
self.reduce(
153153
HyArray[T](),
154154
(r, e) => r.append(transform(e), assumeUniqueness = true)
@@ -257,9 +257,8 @@ extension [Self](self: Self)(using s: Collection[Self]) {
257257

258258
}
259259

260-
extension [Self](self: Self)(using
261-
s: Collection[Self],
262-
e: Value[s.Element]
260+
extension [Self: Collection as s](self: Self)(using
261+
Value[s.Element]
263262
) {
264263

265264
/** Returns `true` if `self` contains the same elements as `other`, in the same order. */

tests/pos/hylolib-cb/HyArray.scala

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1+
//> using options -language:experimental.modularity -source future
12
package hylo
23

34
import java.util.Arrays
45
import scala.collection.mutable
56

67
/** An ordered, random-access collection. */
7-
final class HyArray[Element] private (using
8-
elementIsValue: Value[Element]
9-
)(
8+
final class HyArray[Element: Value as elementIsCValue](
109
private var _storage: scala.Array[AnyRef | Null] | Null,
1110
private var _count: Int // NOTE: where do I document private fields
1211
) {
@@ -155,14 +154,14 @@ final class HyArray[Element] private (using
155154
object HyArray {
156155

157156
/** Creates an array with the given `elements`. */
158-
def apply[T](using t: Value[T])(elements: T*): HyArray[T] =
157+
def apply[T: Value](elements: T*): HyArray[T] =
159158
var a = new HyArray[T](null, 0)
160159
for (e <- elements) a = a.append(e, assumeUniqueness = true)
161160
a
162161

163162
}
164163

165-
given hyArrayIsValue[T](using tIsValue: Value[T]): Value[HyArray[T]] with {
164+
given [T: Value] => Value[HyArray[T]] with {
166165

167166
extension (self: HyArray[T]) {
168167

@@ -179,7 +178,7 @@ given hyArrayIsValue[T](using tIsValue: Value[T]): Value[HyArray[T]] with {
179178

180179
}
181180

182-
given hyArrayIsCollection[T](using tIsValue: Value[T]): Collection[HyArray[T]] with {
181+
given [T: Value] => Collection[HyArray[T]] with {
183182

184183
type Element = T
185184
type Position = Int

tests/pos/hylolib-cb/Slice.scala

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package hylo
22

33
/** A view into a collection. */
4-
final class Slice[Base](using
5-
val b: Collection[Base]
6-
)(
4+
final class Slice[Base: Collection as b](
75
val base: Base,
86
val bounds: Range[b.Position]
97
) {
@@ -26,7 +24,7 @@ final class Slice[Base](using
2624

2725
}
2826

29-
given sliceIsCollection[T](using c: Collection[T]): Collection[Slice[T]] with {
27+
given sliceIsCollection[T: Collection as c]: Collection[Slice[T]] with {
3028

3129
type Element = c.Element
3230
type Position = c.Position

0 commit comments

Comments
 (0)