Skip to content

Commit 0f85940

Browse files
cypressiousSpace Team
authored andcommitted
[FIR] Fix collection of DSL markers from function types
When we're checking a context parameter, we only should collect the DSL markers from the respective context parameter type of the function type, and especially we shouldn't collect the DSL markers from the receiver type. #KT-77301 Fixed
1 parent 726a9d7 commit 0f85940

File tree

2 files changed

+22
-11
lines changed

2 files changed

+22
-11
lines changed

compiler/fir/analysis-tests/testData/resolve/contextParameters/declarationAndUsages/dslMarkerKt77301.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN_PIPELINE_TILL: FRONTEND
1+
// RUN_PIPELINE_TILL: BACKEND
22
// ISSUE: KT-77301
33
// LANGUAGE: +ContextParameters
44
@DslMarker
@@ -17,6 +17,6 @@ val pageContext: PageContext
1717

1818
fun test() {
1919
postprocess {
20-
<!DSL_SCOPE_VIOLATION!>pageContext<!>
20+
pageContext
2121
}
2222
}

compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/stages/ResolutionStages.kt

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -497,22 +497,33 @@ object CheckDslScopeViolation : ResolutionStage() {
497497
context: ResolutionContext,
498498
): Set<ClassId> {
499499
return buildSet {
500-
(boundSymbol.containingDeclarationIfParameter() as? FirAnonymousFunctionSymbol)?.fir?.matchingParameterFunctionType?.let {
501-
// collect annotations in the function type at declaration site. For example, the `@A` and `@B` in the following code.
500+
(boundSymbol.containingDeclarationIfParameter() as? FirAnonymousFunctionSymbol)?.let { anonymousFunctionSymbol ->
501+
val matchingParameterFunctionType = anonymousFunctionSymbol.fir.matchingParameterFunctionType ?: return@let
502+
503+
// Collect annotations in the function type at declaration site. For example, the `@A`, `@B` and `@C in the following code.
502504
// ```
503-
// fun <T> body(block: @A ((@B T).() -> Unit)) { ... }
505+
// fun <T, R> body(block: @A (context(@B T) (@C R).() -> Unit)) { ... }
504506
// ```
507+
// @A should be collected unconditionally.
508+
// @B should only be collected if `boundSymbol` resolves to the respective context parameter of the anonymous function.
509+
// @C should only be collected if `boundSymbol` resolves to the receiver parameter of the anonymous function.
505510

506511
// Collect the annotation on the function type, or `@A` in the example above.
507-
collectDslMarkerAnnotations(context, it.customAnnotations)
512+
collectDslMarkerAnnotations(context, matchingParameterFunctionType.customAnnotations)
508513

509-
// Collect the annotation on the extension receiver, or `@B` in the example above.
510-
it.receiverType(context.session)?.let { receiverType ->
511-
collectDslMarkerAnnotations(context, receiverType)
514+
// Collect the annotation on the context parameter, or `@B` in the example above.
515+
if (boundSymbol is FirValueParameterSymbol) {
516+
val index = anonymousFunctionSymbol.contextParameterSymbols.indexOf(boundSymbol)
517+
matchingParameterFunctionType.contextParameterTypes(context.session).elementAtOrNull(index)?.let { contextType ->
518+
collectDslMarkerAnnotations(context, contextType)
519+
}
512520
}
513521

514-
it.contextParameterTypes(context.session).forEach { contextType ->
515-
collectDslMarkerAnnotations(context, contextType)
522+
// Collect the annotation on the extension receiver, or `@C` in the example above.
523+
if (boundSymbol is FirReceiverParameterSymbol) {
524+
matchingParameterFunctionType.receiverType(context.session)?.let { receiverType ->
525+
collectDslMarkerAnnotations(context, receiverType)
526+
}
516527
}
517528
}
518529

0 commit comments

Comments
 (0)