Skip to content

Commit 1a7d44a

Browse files
committed
Diagnose attempts to reabstract variadic function types in unimplementable ways.
1 parent 4d72501 commit 1a7d44a

19 files changed

+180
-28
lines changed

include/swift/AST/Attr.def.gyb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ TYPE_ATTR(objc_metatype)
8686
TYPE_ATTR(opened)
8787
TYPE_ATTR(pack_element)
8888
TYPE_ATTR(pseudogeneric)
89+
TYPE_ATTR(unimplementable)
8990
TYPE_ATTR(yields)
9091
TYPE_ATTR(yield_once)
9192
TYPE_ATTR(yield_many)

include/swift/AST/CASTBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ typedef enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedTypeAttrKind : long {
190190
BridgedTypeAttrKind_opened,
191191
BridgedTypeAttrKind_pack_element,
192192
BridgedTypeAttrKind_pseudogeneric,
193+
BridgedTypeAttrKind_unimplementable,
193194
BridgedTypeAttrKind_yields,
194195
BridgedTypeAttrKind_yield_once,
195196
BridgedTypeAttrKind_yield_many,

include/swift/AST/DiagnosticsSIL.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ ERROR(c_function_pointer_from_function_with_context,none,
115115
ERROR(objc_selector_malformed,none,"the type ObjectiveC.Selector is malformed",
116116
())
117117

118+
ERROR(unsupported_variadic_function_abstraction,none,
119+
"cannot fully abstract a value of variadic function type %0 because "
120+
"different contexts will not be able to reliably agree on a calling "
121+
"convention; try wrapping it in a struct",
122+
(Type))
123+
118124
// Capture before declaration diagnostics.
119125
ERROR(capture_before_declaration,none,
120126
"closure captures %0 before it is declared", (Identifier))

include/swift/AST/ExtInfo.h

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -651,8 +651,10 @@ class SILExtInfoBuilder {
651651
// If bits are added or removed, then TypeBase::SILFunctionTypeBits
652652
// and NumMaskBits must be updated, and they must match.
653653

654-
// |representation|pseudogeneric| noescape | concurrent | async |differentiability|
655-
// | 0 .. 3 | 4 | 5 | 6 | 7 | 8 .. 10 |
654+
// |representation|pseudogeneric| noescape | concurrent | async
655+
// | 0 .. 3 | 4 | 5 | 6 | 7
656+
// |differentiability|unimplementable|
657+
// | 8 .. 10 | 11 |
656658
//
657659
enum : unsigned {
658660
RepresentationMask = 0xF << 0,
@@ -662,7 +664,8 @@ class SILExtInfoBuilder {
662664
AsyncMask = 1 << 7,
663665
DifferentiabilityMaskOffset = 8,
664666
DifferentiabilityMask = 0x7 << DifferentiabilityMaskOffset,
665-
NumMaskBits = 11
667+
UnimplementableMask = 1 << 11,
668+
NumMaskBits = 12
666669
};
667670

668671
unsigned bits; // Naturally sized for speed.
@@ -677,12 +680,13 @@ class SILExtInfoBuilder {
677680

678681
static constexpr unsigned makeBits(Representation rep, bool isPseudogeneric,
679682
bool isNoEscape, bool isSendable,
680-
bool isAsync,
683+
bool isAsync, bool isUnimplementable,
681684
DifferentiabilityKind diffKind) {
682685
return ((unsigned)rep) | (isPseudogeneric ? PseudogenericMask : 0) |
683686
(isNoEscape ? NoEscapeMask : 0) |
684687
(isSendable ? SendableMask : 0) |
685688
(isAsync ? AsyncMask : 0) |
689+
(isUnimplementable ? UnimplementableMask : 0) |
686690
(((unsigned)diffKind << DifferentiabilityMaskOffset) &
687691
DifferentiabilityMask);
688692
}
@@ -692,22 +696,23 @@ class SILExtInfoBuilder {
692696
/// non-pseudogeneric, non-differentiable.
693697
SILExtInfoBuilder()
694698
: SILExtInfoBuilder(makeBits(SILFunctionTypeRepresentation::Thick, false,
695-
false, false, false,
699+
false, false, false, false,
696700
DifferentiabilityKind::NonDifferentiable),
697701
ClangTypeInfo(nullptr)) {}
698702

699703
SILExtInfoBuilder(Representation rep, bool isPseudogeneric, bool isNoEscape,
700-
bool isSendable, bool isAsync,
704+
bool isSendable, bool isAsync, bool isUnimplementable,
701705
DifferentiabilityKind diffKind, const clang::Type *type)
702706
: SILExtInfoBuilder(makeBits(rep, isPseudogeneric, isNoEscape,
703-
isSendable, isAsync, diffKind),
707+
isSendable, isAsync, isUnimplementable,
708+
diffKind),
704709
ClangTypeInfo(type)) {}
705710

706711
// Constructor for polymorphic type.
707712
SILExtInfoBuilder(ASTExtInfoBuilder info, bool isPseudogeneric)
708713
: SILExtInfoBuilder(makeBits(info.getSILRepresentation(), isPseudogeneric,
709714
info.isNoEscape(), info.isSendable(),
710-
info.isAsync(),
715+
info.isAsync(), /*unimplementable*/ false,
711716
info.getDifferentiabilityKind()),
712717
info.getClangTypeInfo()) {}
713718

@@ -746,6 +751,10 @@ class SILExtInfoBuilder {
746751
DifferentiabilityKind::NonDifferentiable;
747752
}
748753

754+
constexpr bool isUnimplementable() const {
755+
return bits & UnimplementableMask;
756+
}
757+
749758
/// Get the underlying ClangTypeInfo value.
750759
ClangTypeInfo getClangTypeInfo() const { return clangTypeInfo; }
751760

@@ -816,6 +825,12 @@ class SILExtInfoBuilder {
816825
clangTypeInfo);
817826
}
818827
[[nodiscard]]
828+
SILExtInfoBuilder withUnimplementable(bool isUnimplementable = true) const {
829+
return SILExtInfoBuilder(isUnimplementable ? (bits | UnimplementableMask)
830+
: (bits & ~UnimplementableMask),
831+
clangTypeInfo);
832+
}
833+
[[nodiscard]]
819834
SILExtInfoBuilder
820835
withDifferentiabilityKind(DifferentiabilityKind differentiability) const {
821836
return SILExtInfoBuilder(
@@ -828,6 +843,7 @@ class SILExtInfoBuilder {
828843
return SILExtInfoBuilder(bits, ClangTypeInfo(type).getCanonical());
829844
}
830845

846+
831847
bool isEqualTo(SILExtInfoBuilder other, bool useClangTypes) const {
832848
return bits == other.bits &&
833849
(useClangTypes ? (clangTypeInfo == other.clangTypeInfo) : true);
@@ -873,7 +889,7 @@ class SILExtInfo {
873889
/// A default ExtInfo but with a Thin convention.
874890
static SILExtInfo getThin() {
875891
return SILExtInfoBuilder(SILExtInfoBuilder::Representation::Thin, false,
876-
false, false, false,
892+
false, false, false, false,
877893
DifferentiabilityKind::NonDifferentiable, nullptr)
878894
.build();
879895
}
@@ -901,6 +917,10 @@ class SILExtInfo {
901917

902918
constexpr bool isAsync() const { return builder.isAsync(); }
903919

920+
constexpr bool isUnimplementable() const {
921+
return builder.isUnimplementable();
922+
}
923+
904924
constexpr DifferentiabilityKind getDifferentiabilityKind() const {
905925
return builder.getDifferentiabilityKind();
906926
}
@@ -935,6 +955,10 @@ class SILExtInfo {
935955
return builder.withAsync(isAsync).build();
936956
}
937957

958+
SILExtInfo withUnimplementable(bool isUnimplementable = true) const {
959+
return builder.withUnimplementable(isUnimplementable).build();
960+
}
961+
938962
bool isEqualTo(SILExtInfo other, bool useClangTypes) const {
939963
return builder.isEqualTo(other.builder, useClangTypes);
940964
}

include/swift/AST/Types.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ class alignas(1 << TypeAlignInBits) TypeBase
375375

376376
protected:
377377
enum { NumAFTExtInfoBits = 11 };
378-
enum { NumSILExtInfoBits = 11 };
378+
enum { NumSILExtInfoBits = 12 };
379379

380380
// clang-format off
381381
union { uint64_t OpaqueBits;
@@ -3561,6 +3561,10 @@ class AnyFunctionType : public TypeBase {
35613561
/// replaced.
35623562
AnyFunctionType *withExtInfo(ExtInfo info) const;
35633563

3564+
bool containsPackExpansionParam() const {
3565+
return containsPackExpansionType(getParams());
3566+
}
3567+
35643568
static bool containsPackExpansionType(ArrayRef<Param> params);
35653569

35663570
static void printParams(ArrayRef<Param> Params, raw_ostream &OS,
@@ -4621,6 +4625,7 @@ class SILFunctionType final
46214625
}
46224626

46234627
bool isSendable() const { return getExtInfo().isSendable(); }
4628+
bool isUnimplementable() const { return getExtInfo().isUnimplementable(); }
46244629
bool isAsync() const { return getExtInfo().isAsync(); }
46254630

46264631
/// Return the array of all the yields.

include/swift/SIL/AbstractionPattern.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1625,7 +1625,8 @@ class AbstractionPattern {
16251625
getSubstFunctionTypePattern(CanAnyFunctionType substType,
16261626
TypeConverter &TC,
16271627
AbstractionPattern coroutineYieldOrigType,
1628-
CanType coroutineYieldSubstType) const;
1628+
CanType coroutineYieldSubstType,
1629+
bool &unimplementable) const;
16291630

16301631
void dump() const LLVM_ATTRIBUTE_USED;
16311632
void print(raw_ostream &OS) const;

include/swift/SIL/AbstractionPatternGenerators.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,18 @@ class FunctionParamGenerator {
136136
return origParamIsExpansion;
137137
}
138138

139+
/// Return whether the current substituted parameter is a pack
140+
/// expansion but the orig function type is opaque. This is
141+
/// unimplementable in our ABI because the calling convention for
142+
/// function types in the most-general abstraction pattern still
143+
/// assumes a fixed arity.
144+
bool isUnimplementablePackExpansion() const {
145+
assert(!isFinished());
146+
return (origFunctionTypeIsOpaque &&
147+
isa<PackExpansionType>(
148+
allSubstParams[substParamIndex].getParameterType()));
149+
}
150+
139151
/// Return the substituted parameters corresponding to the current
140152
/// orig parameter type. If the current orig parameter is not a
141153
/// pack expansion, this will have exactly one element.

lib/AST/ASTDemangler.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,10 @@ Type ASTBuilder::createImplFunctionType(
574574
#undef SIMPLE_CASE
575575
}
576576

577+
// There's no representation of this in the mangling because it can't
578+
// occur in well-formed programs.
579+
bool unimplementable = false;
580+
577581
llvm::SmallVector<SILParameterInfo, 8> funcParams;
578582
llvm::SmallVector<SILYieldInfo, 8> funcYields;
579583
llvm::SmallVector<SILResultInfo, 8> funcResults;
@@ -610,7 +614,8 @@ Type ASTBuilder::createImplFunctionType(
610614
}
611615
auto einfo = SILFunctionType::ExtInfoBuilder(
612616
representation, flags.isPseudogeneric(), !flags.isEscaping(),
613-
flags.isSendable(), flags.isAsync(), diffKind, clangFnType)
617+
flags.isSendable(), flags.isAsync(),
618+
unimplementable, diffKind, clangFnType)
614619
.build();
615620

616621
return SILFunctionType::get(genericSig, einfo, funcCoroutineKind,

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6523,6 +6523,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
65236523
Printer << " ";
65246524
}
65256525

6526+
if (info.isUnimplementable()) {
6527+
Printer.printSimpleAttr("@unimplementable") << " ";
6528+
}
65266529
if (info.isPseudogeneric()) {
65276530
Printer.printSimpleAttr("@pseudogeneric") << " ";
65286531
}

lib/ASTGen/Sources/ASTGen/Types.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,8 @@ extension ASTGenVisitor {
222222
case .autoclosure, .escaping, .noescape, .noDerivative, .async,
223223
.sendable, .unchecked, ._local, ._noMetadata, .pack_owned,
224224
.pack_guaranteed, .pack_inout, .pack_out, .pseudogeneric,
225-
.yields, .yield_once, .yield_many, .thin, .thick, .count:
225+
.yields, .yield_once, .yield_many, .thin, .thick, .count,
226+
.unimplementable:
226227
TypeAttributes_addSimpleAttr(typeAttributes, typeAttrKind, atLoc, attrLoc)
227228

228229
case .opened, .pack_element, .differentiable, .convention,

0 commit comments

Comments
 (0)