-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Bug fixes to make collection strawman compile #2331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 12 commits
1f75d92
bc81563
b454936
22455d1
60e6278
b783424
a6ced04
d92f456
ef6922c
6c21f08
609e40e
f0c05cf
1ebff50
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -321,72 +321,11 @@ trait TypeOps { this: Context => // TODO: Make standalone object. | |
} | ||
} | ||
|
||
/** If we have member definitions | ||
* | ||
* type argSym v= from | ||
* type from v= to | ||
* | ||
* where the variances of both alias are the same, then enter a new definition | ||
* | ||
* type argSym v= to | ||
* | ||
* unless a definition for `argSym` already exists in the current scope. | ||
*/ | ||
def forwardRef(argSym: Symbol, from: Symbol, to: TypeBounds, cls: ClassSymbol, decls: Scope) = | ||
argSym.info match { | ||
case info @ TypeBounds(lo2 @ TypeRef(_: ThisType, name), hi2) => | ||
if (name == from.name && | ||
(lo2 eq hi2) && | ||
info.variance == to.variance && | ||
!decls.lookup(argSym.name).exists) { | ||
// println(s"short-circuit ${argSym.name} was: ${argSym.info}, now: $to") | ||
enterArgBinding(argSym, to, cls, decls) | ||
} | ||
case _ => | ||
} | ||
|
||
|
||
/** Normalize a list of parent types of class `cls` that may contain refinements | ||
* to a list of typerefs referring to classes, by converting all refinements to member | ||
* definitions in scope `decls`. Can add members to `decls` as a side-effect. | ||
*/ | ||
def normalizeToClassRefs(parents: List[Type], cls: ClassSymbol, decls: Scope): List[TypeRef] = { | ||
|
||
/** If we just entered the type argument binding | ||
* | ||
* type From = To | ||
* | ||
* and there is a type argument binding in a parent in `prefs` of the form | ||
* | ||
* type X = From | ||
* | ||
* then also add the binding | ||
* | ||
* type X = To | ||
* | ||
* to the current scope, provided (1) variances of both aliases are the same, and | ||
* (2) X is not yet defined in current scope. This "short-circuiting" prevents | ||
* long chains of aliases which would have to be traversed in type comparers. | ||
* | ||
* Note: Test i1401.scala shows that `forwardRefs` is also necessary | ||
* for typechecking in the case where self types refer to type parameters | ||
* that are upper-bounded by subclass instances. | ||
*/ | ||
def forwardRefs(from: Symbol, to: Type, prefs: List[TypeRef]) = to match { | ||
case to @ TypeBounds(lo1, hi1) if lo1 eq hi1 => | ||
for (pref <- prefs) { | ||
def forward()(implicit ctx: Context): Unit = | ||
for (argSym <- pref.decls) | ||
if (argSym is BaseTypeArg) | ||
forwardRef(argSym, from, to, cls, decls) | ||
pref.info match { | ||
case info: TempClassInfo => info.addSuspension(implicit ctx => forward()) | ||
case _ => forward() | ||
} | ||
} | ||
case _ => | ||
} | ||
|
||
// println(s"normalizing $parents of $cls in ${cls.owner}") // !!! DEBUG | ||
|
||
// A map consolidating all refinements arising from parent type parameters | ||
|
@@ -429,16 +368,70 @@ trait TypeOps { this: Context => // TODO: Make standalone object. | |
s"redefinition of ${decls.lookup(name).debugString} in ${cls.showLocated}") | ||
enterArgBinding(formals(name), refinedInfo, cls, decls) | ||
} | ||
// Forward definitions in super classes that have one of the refined parameters | ||
// as aliases directly to the refined info. | ||
// Note that this cannot be fused with the previous loop because we now | ||
// assume that all arguments have been entered in `decls`. | ||
refinements foreachBinding { (name, refinedInfo) => | ||
forwardRefs(formals(name), refinedInfo, parentRefs) | ||
} | ||
|
||
if (!ctx.settings.YsuppressParamForwarding.value) | ||
forwardParamBindings(parentRefs, refinements, cls, decls) | ||
|
||
parentRefs | ||
} | ||
|
||
/** Forward parameter bindings in baseclasses to argument types of | ||
* class `cls` if possible. | ||
* If there have member definitions | ||
* | ||
* type param v= middle | ||
* type middle v= to | ||
* | ||
* where the variances of both alias are the same, then enter a new definition | ||
* | ||
* type param v= to | ||
* | ||
* If multiple forwarders would be generated, join their `to` types with an `&`. | ||
* | ||
* @param cls The class for which parameter bindings should be forwarded | ||
* @param decls Its scope | ||
* @param parentRefs The parent type references of `cls` | ||
* @param paramBindings The type parameter bindings generated for `cls` | ||
* | ||
*/ | ||
def forwardParamBindings(parentRefs: List[TypeRef], | ||
paramBindings: SimpleMap[TypeName, Type], | ||
cls: ClassSymbol, decls: Scope)(implicit ctx: Context) = { | ||
|
||
def forwardRef(argSym: Symbol, from: TypeName, to: TypeAlias) = argSym.info match { | ||
case info @ TypeAlias(TypeRef(_: ThisType, `from`)) if info.variance == to.variance => | ||
val existing = decls.lookup(argSym.name) | ||
if (existing.exists) existing.info = existing.info & to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems we get away with it. I have a tendency to wait for an actual CyclicReference popping up before we take that measure. |
||
else enterArgBinding(argSym, to, cls, decls) | ||
case _ => | ||
} | ||
|
||
def forwardRefs(from: TypeName, to: Type) = to match { | ||
case to: TypeAlias => | ||
for (pref <- parentRefs) { | ||
def forward()(implicit ctx: Context): Unit = | ||
for (argSym <- pref.decls) | ||
if (argSym is BaseTypeArg) forwardRef(argSym, from, to) | ||
pref.info match { | ||
case info: TempClassInfo => info.addSuspension(implicit ctx => forward()) | ||
case _ => forward() | ||
} | ||
} | ||
case _ => | ||
} | ||
|
||
paramBindings.foreachBinding(forwardRefs) | ||
} | ||
|
||
/** Used only for debugging: All BaseTypeArg definitions in | ||
* `cls` and all its base classes. | ||
*/ | ||
def allBaseTypeArgs(cls: ClassSymbol)(implicit ctx: Context) = | ||
for { bc <- cls.baseClasses | ||
sym <- bc.info.decls.toList | ||
if sym.is(BaseTypeArg) | ||
} yield sym | ||
|
||
/** An argument bounds violation is a triple consisting of | ||
* - the argument tree | ||
* - a string "upper" or "lower" indicating which bound is violated | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The params are not in the same order in the doc than in the declaration.