Skip to content

Commit 6b30e81

Browse files
committed
Implement SE-0155
1 parent b7ee2ba commit 6b30e81

15 files changed

+360
-94
lines changed

include/swift/AST/ASTMangler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ class ASTMangler : public Mangler {
9090
std::string mangleGlobalGetterEntity(const ValueDecl *decl,
9191
SymbolKind SKind = SymbolKind::Default);
9292

93-
std::string mangleDefaultArgumentEntity(const DeclContext *func,
93+
std::string mangleDefaultArgumentEntity(const ValueDecl *decl,
9494
unsigned index,
9595
SymbolKind SKind);
9696

include/swift/AST/DiagnosticsSema.def

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3223,6 +3223,12 @@ ERROR(type_pattern_missing_is,none,
32233223
ERROR(pattern_type_mismatch_context,none,
32243224
"type annotation does not match contextual type %0", (Type))
32253225

3226+
ERROR(paren_pattern_in_tuple_context,none,
3227+
"parenthesized pattern cannot match value of tuple type %0", (Type))
3228+
WARNING(paren_pattern_in_tuple_context_warn_swift3,none,
3229+
"parenthesized pattern matches value of tuple type %0; this may be "
3230+
"unintended and will be removed in a future version of Swift", (Type))
3231+
32263232
ERROR(tuple_pattern_in_non_tuple_context,none,
32273233
"tuple pattern cannot match values of the non-tuple type %0", (Type))
32283234
ERROR(closure_argument_list_tuple,none,
@@ -3250,10 +3256,18 @@ ERROR(enum_element_pattern_assoc_values_mismatch,none,
32503256
(Identifier))
32513257
NOTE(enum_element_pattern_assoc_values_remove,none,
32523258
"remove associated values to make the pattern match", ())
3259+
32533260
ERROR(tuple_pattern_length_mismatch,none,
32543261
"tuple pattern has the wrong length for tuple type %0", (Type))
32553262
ERROR(tuple_pattern_label_mismatch,none,
32563263
"tuple pattern element label %0 must be %1", (Identifier, Identifier))
3264+
ERROR(tuple_pattern_label_missing,none,
3265+
"tuple pattern mentioning element labels must also specify label '%0'",
3266+
(Identifier))
3267+
ERROR(tuple_pattern_label_should_be_elided,none,
3268+
"tuple pattern not mentioning element labels may not specify label %0",
3269+
(Identifier))
3270+
32573271
ERROR(enum_element_pattern_member_not_found,none,
32583272
"enum case '%0' not found in type %1", (StringRef, Type))
32593273
ERROR(optional_element_pattern_not_valid_type,none,
@@ -3284,6 +3298,16 @@ ERROR(isa_collection_downcast_pattern_value_unimplemented,none,
32843298
"collection downcast in cast pattern is not implemented; use an explicit "
32853299
"downcast to %0 instead", (Type))
32863300

3301+
WARNING(swift3_ignore_specialized_enum_element_call,none,
3302+
"cannot specialize enum case; ignoring generic argument, "
3303+
"which will be rejected in future version of Swift", ())
3304+
3305+
ERROR(ambiguous_enum_element_in_pattern,none,
3306+
"enum case %0 is ambiguous without explicit pattern matching "
3307+
"associated values", (Identifier))
3308+
NOTE(ambiguous_enum_element_candidate,none,
3309+
"found potentially matching case %0", (DeclName))
3310+
32873311
//------------------------------------------------------------------------------
32883312
// MARK: Error-handling diagnostics
32893313
//------------------------------------------------------------------------------

lib/AST/ASTMangler.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,11 +159,15 @@ std::string ASTMangler::mangleGlobalGetterEntity(const ValueDecl *decl,
159159
return finalize();
160160
}
161161

162-
std::string ASTMangler::mangleDefaultArgumentEntity(const DeclContext *func,
162+
std::string ASTMangler::mangleDefaultArgumentEntity(const ValueDecl *decl,
163163
unsigned index,
164164
SymbolKind SKind) {
165165
beginMangling();
166-
appendDefaultArgumentEntity(func, index);
166+
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(decl)) {
167+
appendDefaultArgumentEntity(AFD, index);
168+
} else {
169+
appendDefaultArgumentEntity(decl->getDeclContext(), index);
170+
}
167171
appendSymbolKind(SKind);
168172
return finalize();
169173
}

lib/AST/DeclContext.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,9 @@ ResilienceExpansion DeclContext::getResilienceExpansion() const {
285285
// Default argument initializer contexts have their resilience expansion
286286
// set when they're type checked.
287287
if (isa<DefaultArgumentInitializer>(dc)) {
288+
if (auto *ED = dyn_cast<EnumDecl>(dc->getParent())) {
289+
return ED->getResilienceExpansion();
290+
}
288291
return cast<AbstractFunctionDecl>(dc->getParent())
289292
->getDefaultArgumentResilienceExpansion();
290293
}

lib/Parse/ParsePattern.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ static ParserStatus parseDefaultArgument(
9191
case Parser::ParameterContextKind::Function:
9292
case Parser::ParameterContextKind::Operator:
9393
case Parser::ParameterContextKind::Initializer:
94+
case Parser::ParameterContextKind::EnumElement:
9495
break;
9596
case Parser::ParameterContextKind::Closure:
9697
diagID = diag::no_default_arg_closure;
@@ -101,9 +102,6 @@ static ParserStatus parseDefaultArgument(
101102
case Parser::ParameterContextKind::Curried:
102103
diagID = diag::no_default_arg_curried;
103104
break;
104-
case Parser::ParameterContextKind::EnumElement:
105-
diagID = diag::no_default_arg_enum_elt;
106-
break;
107105
}
108106

109107
assert((diagID.ID != DiagID()) == !defaultArgs &&
@@ -409,7 +407,7 @@ validateParameterWithSpecifier(Parser &parser,
409407
if (parsingEnumElt) {
410408
return new (parser.Context) T(type, loc);
411409
}
412-
410+
413411
if (isa<SpecifierTypeRepr>(type)) {
414412
parser.diagnose(loc, diag::parameter_specifier_repeated).fixItRemove(loc);
415413
} else {

lib/SIL/SILDeclRef.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,14 @@ IsSerialized_t SILDeclRef::isSerialized() const {
451451
// Default argument generators are serialized if the function was
452452
// type-checked in Swift 4 mode.
453453
if (kind == SILDeclRef::Kind::DefaultArgGenerator) {
454-
auto *afd = cast<AbstractFunctionDecl>(d);
455-
switch (afd->getDefaultArgumentResilienceExpansion()) {
454+
ResilienceExpansion expansion;
455+
if (auto *EED = dyn_cast<EnumElementDecl>(d)) {
456+
expansion = EED->getDefaultArgumentResilienceExpansion();
457+
} else {
458+
expansion = cast<AbstractFunctionDecl>(d)
459+
->getDefaultArgumentResilienceExpansion();
460+
}
461+
switch (expansion) {
456462
case ResilienceExpansion::Minimal:
457463
return IsSerialized;
458464
case ResilienceExpansion::Maximal:
@@ -708,10 +714,8 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
708714

709715
case SILDeclRef::Kind::DefaultArgGenerator:
710716
assert(!isCurried);
711-
return mangler.mangleDefaultArgumentEntity(
712-
cast<AbstractFunctionDecl>(getDecl()),
713-
defaultArgIndex,
714-
SKind);
717+
return mangler.mangleDefaultArgumentEntity(getDecl(), defaultArgIndex,
718+
SKind);
715719

716720
case SILDeclRef::Kind::StoredPropertyInitializer:
717721
assert(!isCurried);

lib/SIL/SILVerifier.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,31 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
509509
llvm::dbgs() << " " << type1 << "\n " << type2 << '\n';
510510
});
511511
}
512+
513+
/// Assert that two payload types are equal.
514+
void requireSamePayloadType(SILType type1, SILType type2,
515+
const Twine &complaint) {
516+
if (auto tuple1 = dyn_cast<TupleType>(type1.getSwiftRValueType())) {
517+
require(type2.is<TupleType>(),
518+
"Second payload type does not match first tuple type payload!");
519+
520+
auto tuple2 = type2.castTo<TupleType>();
521+
522+
require(tuple1->getElements().size() == tuple2->getNumElements(),
523+
"Payload tuple element count mismatch!");
524+
525+
for (size_t i = 0, size = tuple1->getElements().size(); i < size; ++i) {
526+
_require(tuple1.getElementType(i) == tuple2.getElementType(i),
527+
complaint, [&] {
528+
llvm::dbgs() << " " << type1 << "\n " << type2 << '\n';
529+
});
530+
}
531+
} else {
532+
_require(type1 == type2, complaint, [&] {
533+
llvm::dbgs() << " " << type1 << "\n " << type2 << '\n';
534+
});
535+
}
536+
}
512537

513538
/// Require two function types to be ABI-compatible.
514539
void requireABICompatibleFunctionTypes(CanSILFunctionType type1,
@@ -2090,7 +2115,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
20902115
SILType caseTy = UI->getType().getEnumElementType(UI->getElement(),
20912116
F.getModule());
20922117
if (UI->getModule().getStage() != SILStage::Lowered) {
2093-
require(caseTy == UI->getOperand()->getType(),
2118+
requireSamePayloadType(caseTy, UI->getOperand()->getType(),
20942119
"EnumInst operand type does not match type of case");
20952120
}
20962121
}
@@ -3922,7 +3947,7 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
39223947
if (F.getModule().getStage() != SILStage::Lowered) {
39233948
// During the lowered stage, a function type might have different
39243949
// signature
3925-
require(eltArgTy == bbArgTy,
3950+
requireSamePayloadType(eltArgTy, bbArgTy,
39263951
"switch_enum destination bbarg must match case arg type");
39273952
}
39283953
require(!dest->getArguments()[0]->getType().isAddress(),

lib/SILGen/SILGen.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,9 @@ void SILGenModule::emitConstructor(ConstructorDecl *decl) {
832832
void SILGenModule::emitEnumConstructor(EnumElementDecl *decl) {
833833
// Enum element constructors are always emitted by need, so don't need
834834
// delayed emission.
835+
if (auto params = decl->getParameterList())
836+
emitDefaultArgGenerators(decl, params);
837+
835838
SILDeclRef constant(decl);
836839
SILFunction *f = getFunction(constant, ForDefinition);
837840
preEmitFunction(constant, decl, f, decl);

lib/SILGen/SILGenApply.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -580,13 +580,13 @@ class Callee {
580580
assert(Substitutions.empty());
581581
return IndirectValue;
582582

583+
case Kind::EnumElement:
584+
LLVM_FALLTHROUGH;
583585
case Kind::StandaloneFunction: {
584586
auto constantInfo = SGF.getConstantInfo(*constant);
585587
SILValue ref = SGF.emitGlobalFunctionRef(Loc, *constant, constantInfo);
586588
return ManagedValue::forUnmanaged(ref);
587589
}
588-
case Kind::EnumElement:
589-
llvm_unreachable("Should have been curried");
590590
case Kind::ClassMethod: {
591591
auto methodTy = SGF.SGM.Types.getConstantOverrideType(*constant);
592592

@@ -683,8 +683,11 @@ class Callee {
683683
auto constantInfo = SGF.getConstantInfo(*constant);
684684
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
685685
}
686-
case Kind::EnumElement:
687-
llvm_unreachable("Should have been curried");
686+
case Kind::EnumElement: {
687+
// Emit a direct call to the element constructor thunk.
688+
auto constantInfo = SGF.getConstantInfo(*constant);
689+
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());
690+
}
688691
case Kind::ClassMethod: {
689692
auto constantInfo = SGF.SGM.Types.getConstantOverrideInfo(*constant);
690693
return createCalleeTypeInfo(SGF, constant, constantInfo.getSILType());

lib/SILGen/SILGenFunction.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ DeclName SILGenModule::getMagicFunctionName(SILDeclRef ref) {
115115
case SILDeclRef::Kind::GlobalAccessor:
116116
return getMagicFunctionName(cast<VarDecl>(ref.getDecl())->getDeclContext());
117117
case SILDeclRef::Kind::DefaultArgGenerator:
118+
if (auto *ED = dyn_cast<EnumElementDecl>(ref.getDecl())) {
119+
return ED->getFullName();
120+
}
118121
return getMagicFunctionName(cast<AbstractFunctionDecl>(ref.getDecl()));
119122
case SILDeclRef::Kind::StoredPropertyInitializer:
120123
return getMagicFunctionName(cast<VarDecl>(ref.getDecl())->getDeclContext());

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4954,7 +4954,14 @@ getCallerDefaultArg(ConstraintSystem &cs, DeclContext *dc,
49544954
unsigned index) {
49554955
auto &tc = cs.getTypeChecker();
49564956

4957-
auto defArg = getDefaultArgumentInfo(cast<ValueDecl>(owner.getDecl()), index);
4957+
std::pair<DefaultArgumentKind, Type> defArg;
4958+
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(owner.getDecl())) {
4959+
defArg = getDefaultArgumentInfo(AFD->getParameters(), index);
4960+
} else {
4961+
defArg = getDefaultArgumentInfo(
4962+
cast<EnumElementDecl>(owner.getDecl())->getParameterList(),
4963+
index);
4964+
}
49584965
Expr *init = nullptr;
49594966
switch (defArg.first) {
49604967
case DefaultArgumentKind::None:

lib/Sema/CSRanking.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -373,15 +373,14 @@ static bool paramIsIUO(Decl *decl, int paramNum) {
373373
auto *paramList = fn->getParameters();
374374
auto *param = paramList->get(paramNum);
375375
return param->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
376+
} else if (auto *subscript = dyn_cast<SubscriptDecl>(decl)) {
377+
auto *index = subscript->getIndices()->get(paramNum);
378+
return index->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
379+
} else {
380+
auto *enumElt = cast<EnumElementDecl>(decl);
381+
auto *index = enumElt->getParameterList()->get(paramNum);
382+
return index->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
376383
}
377-
if (auto *ee = dyn_cast<EnumElementDecl>(decl)) {
378-
auto *param = ee->getParameterList()->get(paramNum);
379-
return param->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
380-
}
381-
382-
auto *subscript = cast<SubscriptDecl>(decl);
383-
auto *index = subscript->getIndices()->get(paramNum);
384-
return index->getAttrs().hasAttribute<ImplicitlyUnwrappedOptionalAttr>();
385384
}
386385

387386
/// \brief Determine whether the first declaration is as "specialized" as
@@ -632,6 +631,21 @@ static bool isDeclAsSpecializedAs(TypeChecker &tc, DeclContext *dc,
632631
break;
633632

634633
case CheckInput: {
634+
if (auto *ED1 = dyn_cast<EnumElementDecl>(decl1)) {
635+
if (auto *ED2 = dyn_cast<EnumElementDecl>(decl2)) {
636+
assert(ED1->hasAssociatedValues() || ED2->hasAssociatedValues());
637+
638+
// If the first function has fewer effective parameters than the
639+
// second, it is more specialized.
640+
if (!ED1->hasAssociatedValues() && ED2->hasAssociatedValues())
641+
return true;
642+
if (ED1->hasAssociatedValues() && !ED2->hasAssociatedValues())
643+
return false;
644+
645+
// Else, fall through to compare function type specialization.
646+
}
647+
}
648+
635649
// Check whether the first function type's input is a subtype of the
636650
// second type's inputs, i.e., can we forward the arguments?
637651
auto funcTy1 = openedType1->castTo<FunctionType>();

0 commit comments

Comments
 (0)