Skip to content

Commit e043fdd

Browse files
committed
documenting SR for path-dependent types
1 parent 5118628 commit e043fdd

File tree

1 file changed

+29
-1
lines changed

1 file changed

+29
-1
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,35 @@ trait PatternTypeConstrainer { self: TypeComparer =>
197197
}
198198
}
199199

200-
/** Reconstruct subtype constraints for type members of the scrutinee and the pattern. */
200+
/** Reconstruct subtype constraints for type members of the scrutinee and the pattern.
201+
*
202+
* To inference SR constraints for the type members from the scrutinee `p` and the pattern `q`,
203+
* we first find all the abstract type members of `p`: A₁, A₂, ⋯, Aₖ.
204+
*
205+
* Then, for each Aᵢ, if `q` also has a type member labaled `Aᵢ`, we inference SR constraints by calling
206+
* TypeComparer on the relation `p.Aᵢ <:< q.Aᵢ`.
207+
* We derive SR constraints for type members of the pattern path `q` similarly.
208+
*
209+
* Specially, if for some `Aᵢ`, `p.Aᵢ` is abstract while `q.Aᵢ` is not, we will extract constraints
210+
* for both directions of the subtype relations (i.e. both `p.Aᵢ <:< q.Aᵢ` and `q.Aᵢ <:< p.Aᵢ`).
211+
*
212+
* How we find out and handle the path (`TermRef`) of the scrutinee and pattern.
213+
*
214+
* - The path of scrutinee is not directly available in `constrainPatternType`, since the scrutinee type
215+
* passed to this function is widened.
216+
* To make the path available during GADT reasoning, we save the scrutinee path in `Typer.typedCase`. The scrutinee path will be saved in `ctx.gadt.scrutineePath`.
217+
* Note that we have to clear the saved scrutinee path after using by calling `ctx.gadt.resetScrutineePath()`.
218+
* This is because `constrainPatternType` may be called multiple times for one nested pattern. For example:
219+
*
220+
* e match
221+
* case A(B(a), C(b)) => // ...
222+
*
223+
* We have to reset the scrutinee path after constraining `e` against the top level pattern `A(...)`.
224+
*
225+
* - The path of pattern is not available when calling the function, and the symbol of the pattern will only be created after GADT reasoning.
226+
* Therefore, we will create `SkolemType` acting as a placeholder for the pattern path, and substitute it with the real pattern path
227+
* when it is available later in the typer. We call `ctx.gadt.supplyPatternPath` to do the substitution.
228+
*/
201229
def constrainTypeMembers = trace(i"constrainTypeMembers(${scrutRepr(scrut)}, $pat)", gadts, res => s"$res\ngadt = ${ctx.gadt.debugBoundsDescription}") {
202230
import NameKinds.DepParamName
203231
val realScrutineePath = ctx.gadt.scrutineePath

0 commit comments

Comments
 (0)