Skip to content

Commit 4994fef

Browse files
committed
Add integration tests
1 parent f5dc508 commit 4994fef

40 files changed

+302
-167
lines changed

include/swift/AST/Decl.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5758,7 +5758,7 @@ class EnumElementDecl : public ValueDecl {
57585758
{
57595759
Bits.EnumElementDecl.Recursiveness =
57605760
static_cast<unsigned>(ElementRecursiveness::NotRecursive);
5761-
EnumElementDeclBits.DefaultArgumentResilienceExpansion =
5761+
Bits.EnumElementDecl.DefaultArgumentResilienceExpansion =
57625762
static_cast<unsigned>(ResilienceExpansion::Maximal);
57635763
}
57645764

@@ -5811,18 +5811,18 @@ class EnumElementDecl : public ValueDecl {
58115811
Bits.EnumElementDecl.Recursiveness = static_cast<unsigned>(recursiveness);
58125812
}
58135813

5814-
/// The ResilienceExpansion for default arguments.
5814+
/// The ResilienceExpansion for default arguments.
58155815
///
58165816
/// In Swift 4 mode, default argument expressions are serialized, and must
58175817
/// obey the restrictions imposed upon inlineable function bodies.
58185818
ResilienceExpansion getDefaultArgumentResilienceExpansion() const {
58195819
return ResilienceExpansion(
5820-
EnumElementDeclBits.DefaultArgumentResilienceExpansion);
5820+
Bits.EnumElementDecl.DefaultArgumentResilienceExpansion);
58215821
}
58225822

58235823
/// Set the ResilienceExpansion for default arguments.
58245824
void setDefaultArgumentResilienceExpansion(ResilienceExpansion expansion) {
5825-
EnumElementDeclBits.DefaultArgumentResilienceExpansion =
5825+
Bits.EnumElementDecl.DefaultArgumentResilienceExpansion =
58265826
unsigned(expansion);
58275827
}
58285828

include/swift/AST/DiagnosticsParse.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,7 @@ WARNING(parameter_extraneous_double_up,none,
879879
"extraneous duplicate parameter name; %0 already has an argument "
880880
"label", (Identifier))
881881
ERROR(parameter_operator_keyword_argument,none,
882-
"%select{operator|closure}0 cannot have keyword arguments", (bool))
882+
"%select{operator|closure|enum case}0 cannot have keyword arguments", (unsigned))
883883

884884
ERROR(parameter_unnamed,none,
885885
"unnamed parameters must be written with the empty name '_'", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3025,8 +3025,7 @@ WARNING(swift3_ignore_specialized_enum_element_call,none,
30253025

30263026
ERROR(ambiguous_enum_element_in_pattern,none,
30273027
"enum case %0 is ambiguous without explicit pattern matching "
3028-
"associated values",
3029-
(Identifier))
3028+
"associated values", (Identifier))
30303029
NOTE(ambiguous_enum_element_candidate,none,
30313030
"found potentially matching case %0", (DeclName))
30323031

include/swift/AST/PrintOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ struct PrintOptions {
285285
ArgumentOnly,
286286
MatchSource,
287287
BothAlways,
288+
EnumElement,
288289
};
289290

290291
/// Whether to print the doc-comment from the conformance if a member decl

lib/AST/ASTPrinter.cpp

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2217,6 +2217,13 @@ void PrintAST::printOneParameter(const ParamDecl *param,
22172217
auto ArgName = param->getArgumentName();
22182218
auto BodyName = param->getName();
22192219
switch (Options.ArgAndParamPrinting) {
2220+
case PrintOptions::ArgAndParamPrintingMode::EnumElement:
2221+
if (ArgName.empty() && BodyName.empty() && !param->getDefaultValue()) {
2222+
// Don't print anything, in the style of a tuple element.
2223+
return;
2224+
}
2225+
// Else, print the argument only.
2226+
LLVM_FALLTHROUGH;
22202227
case PrintOptions::ArgAndParamPrintingMode::ArgumentOnly:
22212228
Printer.printName(ArgName, PrintNameContext::FunctionParameterExternal);
22222229

@@ -2560,9 +2567,22 @@ void PrintAST::printEnumElement(EnumElementDecl *elt) {
25602567
Printer.printName(elt->getName());
25612568
});
25622569

2563-
if (auto argTy = elt->getArgumentInterfaceType()) {
2564-
if (!Options.SkipPrivateStdlibDecls || !argTy.isPrivateStdlibType())
2565-
argTy.print(Printer, Options);
2570+
if (auto *PL = elt->getParameterList()) {
2571+
if (PL->size() == 1 && PL->get(0)->hasType()
2572+
&& PL->get(0)->getType()->isVoid()) {
2573+
auto &ctx = elt->getASTContext();
2574+
TupleType::get({ TupleType::getEmpty(ctx) }, ctx).print(Printer, Options);
2575+
} else {
2576+
llvm::SaveAndRestore<PrintOptions::ArgAndParamPrintingMode>
2577+
mode(Options.ArgAndParamPrinting,
2578+
PrintOptions::ArgAndParamPrintingMode::EnumElement);
2579+
printParameterList(PL,
2580+
elt->hasInterfaceType()
2581+
? elt->getArgumentInterfaceType()
2582+
: nullptr,
2583+
/*isCurried=*/false,
2584+
/*isAPINameByDefault*/[]()->bool{return true;});
2585+
}
25662586
}
25672587

25682588
auto *raw = elt->getRawValueExpr();
@@ -4233,6 +4253,13 @@ void swift::printEnumElementsAsCases(
42334253
// If the enum element has no payloads, return.
42344254
if (!PL)
42354255
return;
4256+
4257+
// Print an empty-but-non-NULL parameter list as '(Void)'
4258+
if (PL->size() == 0) {
4259+
OS << "(Void)";
4260+
return;
4261+
}
4262+
42364263
OS << "(";
42374264
// Print each element in the pattern match.
42384265
for (auto i = PL->begin(); i != PL->end(); ++i) {

lib/AST/Decl.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1950,6 +1950,7 @@ void ValueDecl::setInterfaceType(Type type) {
19501950
if (!type.isNull() && isa<ParamDecl>(this)) {
19511951
assert(!type->is<InOutType>() && "caller did not pass a base type");
19521952
}
1953+
19531954
// lldb creates global typealiases with archetypes in them.
19541955
// FIXME: Add an isDebugAlias() flag, like isDebugVar().
19551956
//
@@ -5295,7 +5296,14 @@ bool EnumElementDecl::computeType() {
52955296

52965297
// The type of the enum element is either (T) -> T or (T) -> ArgType -> T.
52975298
if (auto *PL = getParameterList()) {
5298-
auto paramTy = PL->getType(getASTContext());
5299+
// A parameter type of (Void) indicates that the user wants an empty
5300+
// payload.
5301+
Type paramTy;
5302+
if (PL->size() == 1 && PL->get(0)->getType()->isVoid()) {
5303+
paramTy = TupleType::getEmpty(getASTContext());
5304+
} else {
5305+
paramTy = PL->getType(getASTContext());
5306+
}
52995307
resultTy = FunctionType::get(paramTy->mapTypeOutOfContext(), resultTy);
53005308
}
53015309

lib/IDE/CodeCompletion.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2785,8 +2785,11 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
27852785
setClangDeclKeywords(EED, Pairs, Builder);
27862786
addLeadingDot(Builder);
27872787
Builder.addTextChunk(EED->getName().str());
2788-
if (auto *params = EED->getParameterList())
2788+
if (auto *params = EED->getParameterList()) {
2789+
Builder.addLeftParen();
27892790
addParameters(Builder, params);
2791+
Builder.addRightParen();
2792+
}
27902793

27912794
// Enum element is of function type such as EnumName.type -> Int ->
27922795
// EnumName; however we should show Int -> EnumName as the type

lib/IDE/Refactoring.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,14 @@ class Renamer {
152152
// add an empty range for the local name, or for the decl argument label if
153153
// IsCollapsible is false.
154154
StringRef Content = Range.str();
155+
if (Content.empty()) {
156+
// We can have nothing in the original range if we're trying to rename
157+
// a previously nameless enum argument. This rename behaves like a
158+
// rename for a call argument in that case.
159+
doRenameLabel(Range, RefactoringRangeKind::CallArgumentCombined, NameIndex);
160+
return;
161+
}
162+
155163
size_t ExternalNameEnd = Content.find_first_of(" \t\n\v\f\r/");
156164

157165
if (ExternalNameEnd == StringRef::npos) { // foo([a]: Int)

lib/IDE/SwiftSourceDocInfo.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,14 @@ static std::vector<CharSourceRange> getLabelRanges(const ParameterList* List, co
316316
if (NameLoc.isValid()) {
317317
LabelRanges.push_back(Lexer::getCharSourceRangeFromSourceRange(SM,
318318
SourceRange(NameLoc, ParamLoc)));
319-
} else {
319+
} else if (ParamLoc.isValid()) {
320320
NameLoc = ParamLoc;
321321
NameLength = Param->getNameStr().size();
322322
LabelRanges.push_back(CharSourceRange(NameLoc, NameLength));
323+
} else {
324+
NameLoc = Param->getTypeLoc().getLoc();
325+
NameLength = 0;
326+
LabelRanges.push_back(CharSourceRange(NameLoc, NameLength));
323327
}
324328
}
325329
return LabelRanges;
@@ -375,7 +379,7 @@ bool NameMatcher::walkToDeclPre(Decl *D) {
375379
} else if (EnumElementDecl *EED = dyn_cast<EnumElementDecl>(D)) {
376380
if (auto *ParamList = EED->getParameterList()) {
377381
auto LabelRanges = getLabelRanges(ParamList, getSourceMgr());
378-
tryResolve(ASTWalker::ParentTy(D), D->getLoc(), LabelRangeType::CallArg,
382+
tryResolve(ASTWalker::ParentTy(D), D->getLoc(), LabelRangeType::Param,
379383
LabelRanges);
380384
} else {
381385
tryResolve(ASTWalker::ParentTy(D), D->getLoc());

lib/Parse/ParsePattern.cpp

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,10 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
173173
// Diagnose and insert 'Void' where appropriate.
174174
if (paramContext == ParameterContextKind::EnumElement) {
175175
decltype(diag::enum_element_empty_arglist) diagnostic;
176-
if (Context.isSwiftVersion3()) {
177-
diagnostic = diag::enum_element_empty_arglist_swift3;
178-
} else {
176+
if (Context.isSwiftVersionAtLeast(5)) {
179177
diagnostic = diag::enum_element_empty_arglist;
178+
} else {
179+
diagnostic = diag::enum_element_empty_arglist_swift3;
180180
}
181181

182182
diagnose(leftParenLoc, diagnostic)
@@ -276,8 +276,27 @@ Parser::parseParameterClause(SourceLoc &leftParenLoc,
276276
paramContext == ParameterContextKind::EnumElement) &&
277277
!param.FirstName.empty() &&
278278
param.SecondNameLoc.isValid()) {
279+
enum KeywordArgumentDiagnosticContextKind {
280+
Operator = 0,
281+
Closure = 1,
282+
EnumElement = 2,
283+
} diagContextKind;
284+
285+
switch (paramContext) {
286+
case ParameterContextKind::Operator:
287+
diagContextKind = Operator;
288+
break;
289+
case ParameterContextKind::Closure:
290+
diagContextKind = Closure;
291+
break;
292+
case ParameterContextKind::EnumElement:
293+
diagContextKind = EnumElement;
294+
break;
295+
default:
296+
llvm_unreachable("Unhandled parameter context kind!");
297+
}
279298
diagnose(param.FirstNameLoc, diag::parameter_operator_keyword_argument,
280-
isClosure)
299+
unsigned(diagContextKind))
281300
.fixItRemoveChars(param.FirstNameLoc, param.SecondNameLoc);
282301
param.FirstName = param.SecondName;
283302
param.FirstNameLoc = param.SecondNameLoc;
@@ -426,8 +445,11 @@ mapParsedParameters(Parser &parser,
426445
paramInfo.SpecifierLoc,
427446
argNameLoc, argName,
428447
paramNameLoc, paramName, Type(),
429-
parser.CurDeclContext);
430-
if (argNameLoc.isInvalid() && paramNameLoc.isInvalid())
448+
parser.CurDeclContext);
449+
// If we're not parsing an enum case, lack of a SourceLoc for both
450+
// names indicates the parameter is synthetic.
451+
if (paramContext != Parser::ParameterContextKind::EnumElement &&
452+
argNameLoc.isInvalid() && paramNameLoc.isInvalid())
431453
param->setImplicit();
432454

433455
// If we diagnosed this parameter as a parse error, propagate to the decl.
@@ -436,16 +458,21 @@ mapParsedParameters(Parser &parser,
436458

437459
// If a type was provided, create the type for the parameter.
438460
if (auto type = paramInfo.Type) {
439-
// If 'inout' was specified, turn the type into an in-out type.
440-
if (paramInfo.SpecifierKind == VarDecl::Specifier::InOut) {
441-
type = validateParameterWithSpecifier<InOutTypeRepr>(parser, paramInfo,
442-
"inout");
443-
} else if (paramInfo.SpecifierKind == VarDecl::Specifier::Shared) {
444-
type = validateParameterWithSpecifier<SharedTypeRepr>(parser, paramInfo,
445-
"__shared");
446-
} else if (paramInfo.SpecifierKind == VarDecl::Specifier::Owned) {
447-
type = validateParameterWithSpecifier<OwnedTypeRepr>(parser, paramInfo,
448-
"__owned");
461+
if (paramContext != Parser::ParameterContextKind::EnumElement) {
462+
// If 'inout' was specified, turn the type into an in-out type.
463+
if (paramInfo.SpecifierKind == VarDecl::Specifier::InOut) {
464+
type = validateParameterWithSpecifier<InOutTypeRepr>(parser,
465+
paramInfo,
466+
"inout");
467+
} else if (paramInfo.SpecifierKind == VarDecl::Specifier::Shared) {
468+
type = validateParameterWithSpecifier<SharedTypeRepr>(parser,
469+
paramInfo,
470+
"__shared");
471+
} else if (paramInfo.SpecifierKind == VarDecl::Specifier::Owned) {
472+
type = validateParameterWithSpecifier<OwnedTypeRepr>(parser,
473+
paramInfo,
474+
"__owned");
475+
}
449476
}
450477
param->getTypeLoc() = TypeLoc(type);
451478
} else if (paramContext != Parser::ParameterContextKind::Closure) {

lib/SIL/SILVerifier.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,8 +1968,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
19681968
"EnumInst operand must be an object");
19691969
SILType caseTy = UI->getType().getEnumElementType(UI->getElement(),
19701970
F.getModule());
1971-
if (UI->getModule().getStage() != SILStage::Lowered) {
1972-
require(caseTy == UI->getOperand()->getType(),
1971+
if (UI->getModule().getStage() != SILStage::Lowered
1972+
&& !caseTy.is<SILBoxType>()) {
1973+
requireSameType(caseTy, UI->getOperand()->getType(),
19731974
"EnumInst operand type does not match type of case");
19741975
}
19751976
}

lib/SILGen/ArgumentSource.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,11 @@ class ArgumentSource {
225225
bool isTuple() const & { return StoredKind == Kind::Tuple; }
226226
bool isTupleShuffleExpr() const & {
227227
if (StoredKind == Kind::Expr) {
228-
if (auto *TSE = dyn_cast<TupleShuffleExpr>(asKnownExpr())) {
228+
auto *e = asKnownExpr();
229+
if (auto *TSE = dyn_cast<TupleShuffleExpr>(e)) {
229230
return llvm::any_of(TSE->getElementMapping(), [](const int &i) {
230-
return i == TupleShuffleExpr::DefaultInitialize;
231+
return i == TupleShuffleExpr::DefaultInitialize
232+
|| i == TupleShuffleExpr::CallerDefaultInitialize;
231233
});
232234
}
233235
}

lib/SILGen/SILGenApply.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -544,13 +544,13 @@ class Callee {
544544
assert(Substitutions.empty());
545545
return IndirectValue;
546546

547+
case Kind::EnumElement:
548+
LLVM_FALLTHROUGH;
547549
case Kind::StandaloneFunction: {
548550
auto constantInfo = SGF.getConstantInfo(*constant);
549551
SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
550552
return ManagedValue::forUnmanaged(ref);
551553
}
552-
case Kind::EnumElement:
553-
llvm_unreachable("Should have been curried");
554554
case Kind::ClassMethod: {
555555
auto methodTy = SGF.SGM.Types.getConstantOverrideType(*constant);
556556

@@ -3639,9 +3639,8 @@ CallEmission::applyFirstLevelCallee(SGFContext C) {
36393639
return applyPartiallyAppliedSuperMethod(C);
36403640
}
36413641

3642-
3643-
if (isEnumElementConstructor() && llvm::all_of(uncurriedSites, [](const CallSite &s){
3644-
return !s.isArgTupleShuffle();
3642+
if (isEnumElementConstructor() && !llvm::any_of(uncurriedSites, [](const CallSite &s){
3643+
return s.isArgTupleShuffle();
36453644
})) {
36463645
return applyEnumElementConstructor(C);
36473646
}

lib/Sema/DerivedConformanceEquatableHashable.cpp

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,15 @@ bool allAssociatedValuesConformToProtocol(TypeChecker &tc, EnumDecl *theEnum,
4242
auto declContext = theEnum->getDeclContext();
4343

4444
for (auto elt : theEnum->getAllElements()) {
45-
if (!elt->getArgumentTypeLoc().getType())
45+
if (!elt->hasInterfaceType())
4646
tc.validateDecl(elt);
4747

48-
auto argumentType = elt->getArgumentTypeLoc().getType();
49-
if (!argumentType)
48+
auto PL = elt->getParameterList();
49+
if (!PL)
5050
continue;
5151

52-
if (auto tupleType = argumentType->getAs<TupleType>()) {
53-
// One associated value with a label or multiple associated values
54-
// (labeled or unlabeled) are tuple types.
55-
for (auto tupleElementType : tupleType->getElementTypes()) {
56-
if (!tc.conformsToProtocol(tupleElementType, protocol, declContext,
57-
ConformanceCheckFlags::Used)) {
58-
return false;
59-
}
60-
}
61-
} else {
62-
// One associated value with no label is represented as a paren type.
63-
auto actualType = argumentType->getWithoutParens();
64-
if (!tc.conformsToProtocol(actualType, protocol, declContext,
52+
for (auto param : *PL) {
53+
if (!tc.conformsToProtocol(param->getType(), protocol, declContext,
6554
ConformanceCheckFlags::Used)) {
6655
return false;
6756
}
@@ -154,12 +143,11 @@ enumElementPayloadSubpattern(EnumElementDecl *enumElementDecl,
154143
auto parentDC = enumElementDecl->getDeclContext();
155144
ASTContext &C = parentDC->getASTContext();
156145

157-
auto argumentTypeLoc = enumElementDecl->getArgumentTypeLoc();
158-
if (argumentTypeLoc.isNull())
159-
// No arguments, so no subpattern to match.
146+
// No arguments, so no subpattern to match.
147+
if (!enumElementDecl->hasAssociatedValues())
160148
return nullptr;
161149

162-
auto argumentType = argumentTypeLoc.getType();
150+
auto argumentType = enumElementDecl->getArgumentInterfaceType();
163151
if (auto tupleType = argumentType->getAs<TupleType>()) {
164152
// Either multiple (labeled or unlabeled) arguments, or one labeled
165153
// argument. Return a tuple pattern that matches the enum element in arity,

lib/Sema/TypeCheckCaptures.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,11 +429,12 @@ class FindCapturedVars : public ASTWalker {
429429

430430
// Can default parameter initializers capture state? That seems like
431431
// a really bad idea.
432-
for (auto *paramList : AFD->getParameterLists())
432+
for (auto *paramList : AFD->getParameterLists()) {
433433
for (auto param : *paramList) {
434434
if (auto E = param->getDefaultValue())
435435
E->walk(*this);
436436
}
437+
}
437438
return false;
438439
}
439440

0 commit comments

Comments
 (0)