Skip to content

Commit b5af518

Browse files
authored
Merge pull request #77491 from slavapestov/fix-rdar139237671
Sema: Allow closure parameter lists to reference opaque parameter declarations
2 parents c174b86 + e9ff8ad commit b5af518

File tree

2 files changed

+47
-30
lines changed

2 files changed

+47
-30
lines changed

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4280,48 +4280,50 @@ void TypeChecker::checkParameterList(ParameterList *params,
42804280
}
42814281

42824282
// Opaque types cannot occur in parameter position.
4283-
Type interfaceType = param->getInterfaceType();
4284-
if (interfaceType->hasTypeParameter()) {
4285-
interfaceType.findIf([&](Type type) {
4286-
if (auto fnType = type->getAs<FunctionType>()) {
4287-
for (auto innerParam : fnType->getParams()) {
4288-
auto paramType = innerParam.getPlainType();
4289-
if (!paramType->hasTypeParameter())
4290-
continue;
4291-
4292-
bool hadError = paramType.findIf([&](Type innerType) {
4293-
auto genericParam = innerType->getAs<GenericTypeParamType>();
4294-
if (!genericParam)
4295-
return false;
4296-
4297-
auto genericParamDecl = genericParam->getOpaqueDecl();
4298-
if (!genericParamDecl)
4299-
return false;
4300-
4301-
param->diagnose(
4302-
diag::opaque_type_in_parameter, true, interfaceType);
4303-
return true;
4304-
});
4283+
if (!isa<ClosureExpr>(owner)) {
4284+
Type interfaceType = param->getInterfaceType();
4285+
if (interfaceType->hasTypeParameter()) {
4286+
interfaceType.findIf([&](Type type) {
4287+
if (auto fnType = type->getAs<FunctionType>()) {
4288+
for (auto innerParam : fnType->getParams()) {
4289+
auto paramType = innerParam.getPlainType();
4290+
if (!paramType->hasTypeParameter())
4291+
continue;
4292+
4293+
bool hadError = paramType.findIf([&](Type innerType) {
4294+
auto genericParam = innerType->getAs<GenericTypeParamType>();
4295+
if (!genericParam)
4296+
return false;
4297+
4298+
auto genericParamDecl = genericParam->getOpaqueDecl();
4299+
if (!genericParamDecl)
4300+
return false;
4301+
4302+
param->diagnose(
4303+
diag::opaque_type_in_parameter, true, interfaceType);
4304+
return true;
4305+
});
4306+
4307+
if (hadError)
4308+
return true;
4309+
}
43054310

4306-
if (hadError)
4307-
return true;
4311+
return false;
43084312
}
43094313

43104314
return false;
4311-
}
4312-
4313-
return false;
4314-
});
4315+
});
4316+
}
43154317
}
43164318

43174319
if (param->hasAttachedPropertyWrapper())
43184320
(void) param->getPropertyWrapperInitializerInfo();
43194321

4320-
auto *SF = param->getDeclContext()->getParentSourceFile();
43214322
if (!param->isInvalid()) {
4323+
auto *SF = owner->getParentSourceFile();
43224324
param->visitAuxiliaryDecls([&](VarDecl *auxiliaryDecl) {
43234325
if (!isa<ParamDecl>(auxiliaryDecl))
4324-
DeclChecker(param->getASTContext(), SF).visitBoundVariable(auxiliaryDecl);
4326+
DeclChecker(SF->getASTContext(), SF).visitBoundVariable(auxiliaryDecl);
43254327
});
43264328
}
43274329

test/type/opaque_parameters.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,18 @@ struct I61387_1 {
131131
}
132132
}
133133
}
134+
135+
// However, it's fine if the inferred type of a closure refers to opaque parameters from the outer scope.
136+
public func combinator<T>(_: T, _: ((T) -> ()) -> ()) {}
137+
138+
public func closureWithOpaqueParameterInConsumingPosition(p: some Any) {
139+
// Single-expression
140+
combinator(p) { $0(p) }
141+
142+
// Multi-expression
143+
combinator(p) { fn in
144+
let result: () = fn(p)
145+
return result
146+
}
147+
}
148+

0 commit comments

Comments
 (0)