Skip to content

Commit

Permalink
Merge pull request #77491 from slavapestov/fix-rdar139237671
Browse files Browse the repository at this point in the history
Sema: Allow closure parameter lists to reference opaque parameter declarations
  • Loading branch information
slavapestov authored Nov 9, 2024
2 parents c174b86 + e9ff8ad commit b5af518
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 30 deletions.
62 changes: 32 additions & 30 deletions lib/Sema/TypeCheckDeclPrimary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4280,48 +4280,50 @@ void TypeChecker::checkParameterList(ParameterList *params,
}

// Opaque types cannot occur in parameter position.
Type interfaceType = param->getInterfaceType();
if (interfaceType->hasTypeParameter()) {
interfaceType.findIf([&](Type type) {
if (auto fnType = type->getAs<FunctionType>()) {
for (auto innerParam : fnType->getParams()) {
auto paramType = innerParam.getPlainType();
if (!paramType->hasTypeParameter())
continue;

bool hadError = paramType.findIf([&](Type innerType) {
auto genericParam = innerType->getAs<GenericTypeParamType>();
if (!genericParam)
return false;

auto genericParamDecl = genericParam->getOpaqueDecl();
if (!genericParamDecl)
return false;

param->diagnose(
diag::opaque_type_in_parameter, true, interfaceType);
return true;
});
if (!isa<ClosureExpr>(owner)) {
Type interfaceType = param->getInterfaceType();
if (interfaceType->hasTypeParameter()) {
interfaceType.findIf([&](Type type) {
if (auto fnType = type->getAs<FunctionType>()) {
for (auto innerParam : fnType->getParams()) {
auto paramType = innerParam.getPlainType();
if (!paramType->hasTypeParameter())
continue;

bool hadError = paramType.findIf([&](Type innerType) {
auto genericParam = innerType->getAs<GenericTypeParamType>();
if (!genericParam)
return false;

auto genericParamDecl = genericParam->getOpaqueDecl();
if (!genericParamDecl)
return false;

param->diagnose(
diag::opaque_type_in_parameter, true, interfaceType);
return true;
});

if (hadError)
return true;
}

if (hadError)
return true;
return false;
}

return false;
}

return false;
});
});
}
}

if (param->hasAttachedPropertyWrapper())
(void) param->getPropertyWrapperInitializerInfo();

auto *SF = param->getDeclContext()->getParentSourceFile();
if (!param->isInvalid()) {
auto *SF = owner->getParentSourceFile();
param->visitAuxiliaryDecls([&](VarDecl *auxiliaryDecl) {
if (!isa<ParamDecl>(auxiliaryDecl))
DeclChecker(param->getASTContext(), SF).visitBoundVariable(auxiliaryDecl);
DeclChecker(SF->getASTContext(), SF).visitBoundVariable(auxiliaryDecl);
});
}

Expand Down
15 changes: 15 additions & 0 deletions test/type/opaque_parameters.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,18 @@ struct I61387_1 {
}
}
}

// However, it's fine if the inferred type of a closure refers to opaque parameters from the outer scope.
public func combinator<T>(_: T, _: ((T) -> ()) -> ()) {}

public func closureWithOpaqueParameterInConsumingPosition(p: some Any) {
// Single-expression
combinator(p) { $0(p) }

// Multi-expression
combinator(p) { fn in
let result: () = fn(p)
return result
}
}

0 comments on commit b5af518

Please sign in to comment.