Skip to content

Commit 3437526

Browse files
oderskyKordyjan
authored andcommitted
Make some context bound evidence params tracked
Make context bound evidence params tracked if they have types with abstract type members. [Cherry-picked 4d62692]
1 parent 555f67c commit 3437526

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)