Skip to content

Commit 6e51841

Browse files
committed
[AST] Enforce that composeTuple drops parameter flags
Callers may either assert that the parameter flags are empty, or ask for them to be dropped.
1 parent 1bf954c commit 6e51841

10 files changed

+73
-36
lines changed

include/swift/AST/Types.h

+24-3
Original file line numberDiff line numberDiff line change
@@ -2123,6 +2123,28 @@ class ParameterTypeFlags {
21232123
uint16_t toRaw() const { return value.toRaw(); }
21242124
};
21252125

2126+
/// A type that indicates how parameter flags should be handled in an operation
2127+
/// that requires the conversion into a type that doesn't support them, such as
2128+
/// tuples.
2129+
enum class ParameterFlagHandling {
2130+
/// Ignores any parameter flags that may be present, dropping them from the
2131+
/// result. This should only be used in specific cases, including e.g:
2132+
///
2133+
/// - The flags have already been handled, and unsuitable flags have been
2134+
/// rejected or asserted to not be present.
2135+
/// - The flags aren't relevant for the particular conversion (e.g for type
2136+
/// printing or compatibility logic).
2137+
/// - The conversion is only interested in the 'internal argument' of a
2138+
/// parameter, in which case only the type and label are relevant.
2139+
///
2140+
/// In all other cases, you ought to verify that unsuitable flags are not
2141+
/// present, or add assertions to that effect.
2142+
IgnoreNonEmpty,
2143+
2144+
/// Asserts that no parameter flags are present.
2145+
AssertEmpty
2146+
};
2147+
21262148
class YieldTypeFlags {
21272149
enum YieldFlags : uint8_t {
21282150
None = 0,
@@ -3127,10 +3149,9 @@ class AnyFunctionType : public TypeBase {
31273149
public:
31283150
/// Take an array of parameters and turn it into a tuple or paren type.
31293151
///
3130-
/// \param wantParamFlags Whether to preserve the parameter flags from the
3131-
/// given set of parameters.
3152+
/// \param paramFlagHandling How to handle the parameter flags.
31323153
static Type composeTuple(ASTContext &ctx, ArrayRef<Param> params,
3133-
bool wantParamFlags = true);
3154+
ParameterFlagHandling paramFlagHandling);
31343155

31353156
/// Given two arrays of parameters determine if they are equal in their
31363157
/// canonicalized form. Internal labels and type sugar is *not* taken into

lib/APIDigester/ModuleAnalyzerNodes.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -1601,8 +1601,9 @@ SwiftDeclCollector::constructTypeNode(Type T, TypeInitInfo Info) {
16011601
// Still, return type first
16021602
Root->addChild(constructTypeNode(Fun->getResult()));
16031603

1604-
auto Input = AnyFunctionType::composeTuple(Fun->getASTContext(),
1605-
Fun->getParams());
1604+
auto Input =
1605+
AnyFunctionType::composeTuple(Fun->getASTContext(), Fun->getParams(),
1606+
ParameterFlagHandling::IgnoreNonEmpty);
16061607
Root->addChild(constructTypeNode(Input));
16071608
return Root;
16081609
}

lib/AST/ASTContext.cpp

+9-4
Original file line numberDiff line numberDiff line change
@@ -3623,12 +3623,17 @@ Type AnyFunctionType::Param::getParameterType(bool forCanonical,
36233623
}
36243624

36253625
Type AnyFunctionType::composeTuple(ASTContext &ctx, ArrayRef<Param> params,
3626-
bool wantParamFlags) {
3626+
ParameterFlagHandling paramFlagHandling) {
36273627
SmallVector<TupleTypeElt, 4> elements;
36283628
for (const auto &param : params) {
3629-
auto flags = wantParamFlags ? param.getParameterFlags()
3630-
: ParameterTypeFlags();
3631-
elements.emplace_back(param.getParameterType(), param.getLabel(), flags);
3629+
switch (paramFlagHandling) {
3630+
case ParameterFlagHandling::IgnoreNonEmpty:
3631+
break;
3632+
case ParameterFlagHandling::AssertEmpty:
3633+
assert(param.getParameterFlags().isNone());
3634+
break;
3635+
}
3636+
elements.emplace_back(param.getParameterType(), param.getLabel());
36323637
}
36333638
return TupleType::get(elements, ctx);
36343639
}

lib/AST/Decl.cpp

+5-7
Original file line numberDiff line numberDiff line change
@@ -8813,13 +8813,11 @@ Type EnumElementDecl::getArgumentInterfaceType() const {
88138813
auto funcTy = interfaceType->castTo<AnyFunctionType>();
88148814
funcTy = funcTy->getResult()->castTo<FunctionType>();
88158815

8816-
auto &ctx = getASTContext();
8817-
SmallVector<TupleTypeElt, 4> elements;
8818-
for (const auto &param : funcTy->getParams()) {
8819-
Type eltType = param.getParameterType(/*canonicalVararg=*/false, &ctx);
8820-
elements.emplace_back(eltType, param.getLabel());
8821-
}
8822-
return TupleType::get(elements, ctx);
8816+
// The payload type of an enum is an imploded tuple of the internal arguments
8817+
// of the case constructor. As such, compose a tuple type with the parameter
8818+
// flags dropped.
8819+
return AnyFunctionType::composeTuple(getASTContext(), funcTy->getParams(),
8820+
ParameterFlagHandling::IgnoreNonEmpty);
88238821
}
88248822

88258823
void EnumElementDecl::setParameterList(ParameterList *params) {

lib/SILGen/SILGenApply.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -4186,8 +4186,13 @@ RValue CallEmission::applyEnumElementConstructor(SGFContext C) {
41864186
resultFnType, argVals,
41874187
std::move(*callSite).forward());
41884188

4189-
auto payloadTy = AnyFunctionType::composeTuple(SGF.getASTContext(),
4190-
resultFnType->getParams());
4189+
// We need to implode a tuple rvalue for enum construction. This is
4190+
// essentially an implosion of the internal arguments of a pseudo case
4191+
// constructor, so we can drop the parameter flags.
4192+
auto payloadTy = AnyFunctionType::composeTuple(
4193+
SGF.getASTContext(), resultFnType->getParams(),
4194+
ParameterFlagHandling::IgnoreNonEmpty);
4195+
41914196
auto arg = RValue(SGF, argVals, payloadTy->getCanonicalType());
41924197
payload = ArgumentSource(uncurriedLoc, std::move(arg));
41934198
formalResultType = cast<FunctionType>(formalResultType).getResult();

lib/SILGen/SILGenExpr.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -2765,9 +2765,8 @@ loadIndexValuesForKeyPathComponent(SILGenFunction &SGF, SILLocation loc,
27652765
return indexValues;
27662766
}
27672767

2768-
auto indexLoweredTy =
2769-
SGF.getLoweredType(
2770-
AnyFunctionType::composeTuple(SGF.getASTContext(), indexParams));
2768+
auto indexLoweredTy = SGF.getLoweredType(AnyFunctionType::composeTuple(
2769+
SGF.getASTContext(), indexParams, ParameterFlagHandling::AssertEmpty));
27712770

27722771
auto addr = SGF.B.createPointerToAddress(loc, pointer,
27732772
indexLoweredTy.getAddressType(),

lib/Sema/CSRanking.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -847,10 +847,10 @@ getConstructorParamsAsTuples(ASTContext &ctx, Type boundTy1, Type boundTy2) {
847847
return bindings;
848848
}
849849

850-
auto tuple1 = AnyFunctionType::composeTuple(ctx, initParams1,
851-
/*wantParamFlags*/ false);
852-
auto tuple2 = AnyFunctionType::composeTuple(ctx, initParams2,
853-
/*wantParamFlags*/ false);
850+
auto tuple1 = AnyFunctionType::composeTuple(
851+
ctx, initParams1, ParameterFlagHandling::IgnoreNonEmpty);
852+
auto tuple2 = AnyFunctionType::composeTuple(
853+
ctx, initParams2, ParameterFlagHandling::IgnoreNonEmpty);
854854
return TypeBindingsToCompare(tuple1, tuple2);
855855
}
856856

lib/Sema/CSSimplify.cpp

+13-6
Original file line numberDiff line numberDiff line change
@@ -2650,8 +2650,12 @@ static bool fixMissingArguments(ConstraintSystem &cs, ASTNode anchor,
26502650
// If the argument was a single "tuple", let's bind newly
26512651
// synthesized arguments to it.
26522652
if (argumentTuple) {
2653+
// We can ignore parameter flags here as we're imploding a tuple for a
2654+
// simulated ((X, Y, Z)) -> R to (X, Y, Z) -> R conversion. As such, this is
2655+
// similar to e.g { x, y, z in fn((x, y, z)) }.
26532656
cs.addConstraint(ConstraintKind::Bind, *argumentTuple,
2654-
FunctionType::composeTuple(ctx, args),
2657+
FunctionType::composeTuple(
2658+
ctx, args, ParameterFlagHandling::IgnoreNonEmpty),
26552659
cs.getConstraintLocator(anchor));
26562660
}
26572661

@@ -2884,8 +2888,8 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
28842888
// Form an imploded tuple type, dropping the parameter flags as although
28852889
// canImplodeParams makes sure we're not dealing with vargs, inout, etc,
28862890
// we may still have e.g ownership flags left over, which we can drop.
2887-
auto input = AnyFunctionType::composeTuple(getASTContext(), params,
2888-
/*wantParamFlags*/ false);
2891+
auto input = AnyFunctionType::composeTuple(
2892+
getASTContext(), params, ParameterFlagHandling::IgnoreNonEmpty);
28892893
params.clear();
28902894
// If fixes are disabled let's do an easy thing and implode
28912895
// tuple directly into parameters list.
@@ -7008,8 +7012,11 @@ ConstraintSystem::simplifyConstructionConstraint(
70087012
args.push_back(arg.withFlags(flags));
70097013
}
70107014

7011-
// Tuple construction is simply tuple conversion.
7012-
Type argType = AnyFunctionType::composeTuple(getASTContext(), args);
7015+
// Tuple construction is simply tuple conversion. We should have already
7016+
// handled the parameter flags. If any future parameter flags are added,
7017+
// they should also be verified above.
7018+
Type argType = AnyFunctionType::composeTuple(
7019+
getASTContext(), args, ParameterFlagHandling::AssertEmpty);
70137020
Type resultType = fnType->getResult();
70147021

70157022
ConstraintLocatorBuilder builder(locator);
@@ -7995,7 +8002,7 @@ ConstraintSystem::simplifyBindTupleOfFunctionParamsConstraint(
79958002

79968003
auto tupleTy =
79978004
AnyFunctionType::composeTuple(getASTContext(), funcTy->getParams(),
7998-
/*wantParamFlags*/ false);
8005+
ParameterFlagHandling::IgnoreNonEmpty);
79998006

80008007
addConstraint(ConstraintKind::Bind, tupleTy, second,
80018008
locator.withPathElement(ConstraintLocator::FunctionArgument));

lib/Sema/TypeCheckDeclOverride.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,8 @@ static bool noteFixableMismatchedTypes(ValueDecl *decl, const ValueDecl *base) {
490490
auto *fnType = baseTy->getAs<AnyFunctionType>();
491491
baseTy = fnType->getResult();
492492
Type argTy = FunctionType::composeTuple(
493-
ctx, baseTy->getAs<AnyFunctionType>()->getParams());
493+
ctx, baseTy->getAs<AnyFunctionType>()->getParams(),
494+
ParameterFlagHandling::IgnoreNonEmpty);
494495
auto diagKind = diag::override_type_mismatch_with_fixits_init;
495496
unsigned numArgs = baseInit->getParameters()->size();
496497
return computeFixitsForOverriddenDeclaration(

lib/Sema/TypeCheckProtocol.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -2267,10 +2267,10 @@ static void addAssocTypeDeductionString(llvm::SmallString<128> &str,
22672267
static Type getTypeForDisplay(ModuleDecl *module, ValueDecl *decl) {
22682268
// For a constructor, we only care about the parameter types.
22692269
if (auto ctor = dyn_cast<ConstructorDecl>(decl)) {
2270-
return AnyFunctionType::composeTuple(module->getASTContext(),
2271-
ctor->getMethodInterfaceType()
2272-
->castTo<FunctionType>()
2273-
->getParams());
2270+
return AnyFunctionType::composeTuple(
2271+
module->getASTContext(),
2272+
ctor->getMethodInterfaceType()->castTo<FunctionType>()->getParams(),
2273+
ParameterFlagHandling::IgnoreNonEmpty);
22742274
}
22752275

22762276
Type type = decl->getInterfaceType();

0 commit comments

Comments
 (0)