Skip to content

Commit 715610e

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 227f0de commit 715610e

File tree

11 files changed

+80
-37
lines changed

11 files changed

+80
-37
lines changed

include/swift/AST/Types.h

Lines changed: 24 additions & 3 deletions
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

Lines changed: 3 additions & 2 deletions
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

Lines changed: 9 additions & 4 deletions
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

Lines changed: 5 additions & 7 deletions
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

Lines changed: 7 additions & 2 deletions
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

Lines changed: 2 additions & 3 deletions
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

Lines changed: 4 additions & 4 deletions
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

Lines changed: 19 additions & 6 deletions
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.
@@ -6984,9 +6988,18 @@ ConstraintSystem::simplifyConstructionConstraint(
69846988
}
69856989
}
69866990

6991+
auto args = fnType->getParams();
6992+
assert(llvm::all_of(args, [](auto arg) {
6993+
// We should only have '_const' as a parameter flag, as these parameters
6994+
// are for the arguments of the tuple construction. If any future
6995+
// parameter flags are added for arguments, it should be verified that
6996+
// they may be used with tuple construction.
6997+
return arg.getParameterFlags().withCompileTimeConst(false).isNone();
6998+
}));
6999+
69877000
// Tuple construction is simply tuple conversion.
6988-
Type argType = AnyFunctionType::composeTuple(getASTContext(),
6989-
fnType->getParams());
7001+
Type argType = AnyFunctionType::composeTuple(
7002+
getASTContext(), args, ParameterFlagHandling::IgnoreNonEmpty);
69907003
Type resultType = fnType->getResult();
69917004

69927005
ConstraintLocatorBuilder builder(locator);
@@ -7972,7 +7985,7 @@ ConstraintSystem::simplifyBindTupleOfFunctionParamsConstraint(
79727985

79737986
auto tupleTy =
79747987
AnyFunctionType::composeTuple(getASTContext(), funcTy->getParams(),
7975-
/*wantParamFlags*/ false);
7988+
ParameterFlagHandling::IgnoreNonEmpty);
79767989

79777990
addConstraint(ConstraintKind::Bind, tupleTy, second,
79787991
locator.withPathElement(ConstraintLocator::FunctionArgument));

lib/Sema/TypeCheckDeclOverride.cpp

Lines changed: 2 additions & 1 deletion
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

Lines changed: 4 additions & 4 deletions
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();

test/Constraints/diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ func r22263468(_ a : String?) {
573573
// TODO(diagnostics): This is a regression from diagnosing missing optional unwrap for `a`, we have to
574574
// re-think the way errors in tuple elements are detected because it's currently impossible to detect
575575
// exactly what went wrong here and aggregate fixes for different elements at the same time.
576-
_ = MyTuple(42, a) // expected-error {{tuple type '(_const Int, String?)' is not convertible to tuple type 'MyTuple' (aka '(Int, String)')}}
576+
_ = MyTuple(42, a) // expected-error {{tuple type '(Int, String?)' is not convertible to tuple type 'MyTuple' (aka '(Int, String)')}}
577577
}
578578

579579
// rdar://71829040 - "ambiguous without more context" error for tuple type mismatch.

0 commit comments

Comments
 (0)