Skip to content

(More) Declaration checker support for tuple conformances #68282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -5178,21 +5178,19 @@ class ProtocolDecl final : public NominalTypeDecl {
/// and conformances for tuple types.
///
/// - The declared interface type is the special TheTupleType singleton.
/// - The generic parameter list has one pack generic parameter, <Elements...>
/// - The generic signature has no requirements, <Elements...>
/// - The generic parameter list has one pack generic parameter, <each Element>
/// - The generic signature has no requirements, <each Element>
/// - The self interface type is the tuple type containing a single pack
/// expansion, (Elements...).
/// expansion, (repeat each Element).
class BuiltinTupleDecl final : public NominalTypeDecl {
TupleType *TupleSelfType = nullptr;

public:
BuiltinTupleDecl(Identifier Name, DeclContext *Parent);

SourceRange getSourceRange() const {
return SourceRange();
}

TupleType *getTupleSelfType() const;
TupleType *getTupleSelfType(const ExtensionDecl *owner) const;

// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
Expand Down
58 changes: 50 additions & 8 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -2353,6 +2353,18 @@ ERROR(extension_access_with_conformances,none,
ERROR(experimental_tuple_extension,none,
"tuple extensions are experimental",
())
ERROR(tuple_extension_wrong_type,none,
"tuple extension must be written as extension of %0", (Type))
ERROR(tuple_extension_one_conformance,none,
"tuple extension must declare conformance to exactly one protocol", ())
ERROR(tuple_extension_extra_requirement,none,
"tuple extension cannot require that %0 "
"%select{conforms to|subclasses|is the same type as|%error|%error}1 %2",
(Type, unsigned, Type))
ERROR(tuple_extension_missing_requirement,none,
"tuple extension must require that %0 conforms to %1", (Type, Type))
ERROR(tuple_extension_nested_type,none,
"type %0 cannot be nested in tuple extension", (const NominalTypeDecl *))
ERROR(extension_metatype,none,
"cannot extend a metatype %0", (Type))
ERROR(extension_placeholder,none,
Expand Down Expand Up @@ -2721,10 +2733,23 @@ NOTE(ambiguous_witnesses_wrong_name,none,
NOTE(no_witnesses_type,none,
"protocol requires nested type %0; add nested type %0 for conformance",
(const AssociatedTypeDecl *))
NOTE(default_associated_type_req_fail,none,
NOTE(no_witnesses_type_tuple,none,
"protocol requires nested type %0; add type alias %0 with underlying type %1 "
"for conformance",
(const AssociatedTypeDecl *, Type))
NOTE(default_associated_type_unsatisfied_conformance,none,
"default type %0 for associated type %1 (from protocol %2) "
"does not conform to %3",
(Type, const AssociatedTypeDecl *, Type, Type))
NOTE(default_associated_type_unsatisfied_superclass,none,
"default type %0 for associated type %1 (from protocol %2) "
"does not inherit from %3",
(Type, const AssociatedTypeDecl *, Type, Type))
NOTE(default_associated_type_tuple,none,
"default type %0 for associated type %1 (from protocol %2) "
"does not %select{inherit from|conform to}4 %3",
(Type, const AssociatedTypeDecl *, Type, Type, bool))
"is unsuitable for tuple conformance; the associated type requirement "
"must be fulfilled by a type alias with underlying type %3",
(Type, const AssociatedTypeDecl *, Type, Type))
ERROR(associated_type_access,none,
"associated type in "
"%select{a private|a fileprivate|an internal|a package|a public|%error}0 protocol "
Expand Down Expand Up @@ -2752,10 +2777,19 @@ WARNING(associated_type_not_usable_from_inline_warn,none,
NOTE(bad_associated_type_deduction,none,
"unable to infer associated type %0 for protocol %1",
(const AssociatedTypeDecl *, const ProtocolDecl *))
NOTE(associated_type_deduction_witness_failed,none,
NOTE(associated_type_deduction_unsatisfied_conformance,none,
"candidate would match and infer %0 = %1 if %1 "
"conformed to %2",
(const AssociatedTypeDecl *, Type, Type))
NOTE(associated_type_deduction_unsatisfied_superclass,none,
"candidate would match and infer %0 = %1 if %1 "
"%select{inherited from|conformed to}3 %2",
(const AssociatedTypeDecl *, Type, Type, bool))
"inherited from %2",
(const AssociatedTypeDecl *, Type, Type))
NOTE(associated_type_deduction_tuple,none,
"cannot infer %0 = %1 in tuple conformance because "
"the associated type requirement must be fulfilled by a type alias with "
"underlying type %2",
(const AssociatedTypeDecl *, Type, Type))
NOTE(associated_type_witness_conform_impossible,none,
"candidate can not infer %0 = %1 because %1 "
"is not a nominal type and so can't conform to %2",
Expand Down Expand Up @@ -2846,9 +2880,17 @@ NOTE(protocol_witness_enum_case_payload, none,

NOTE(protocol_witness_type,none,
"possibly intended match", ())
NOTE(protocol_witness_nonconform_type,none,
NOTE(protocol_type_witness_unsatisfied_conformance,none,
"possibly intended match %0 does not "
"%select{inherit from|conform to}2 %1", (Type, Type, bool))
"conform to %1", (Type, Type))
NOTE(protocol_type_witness_unsatisfied_superclass,none,
"possibly intended match %0 does not "
"inherit from %1", (Type, Type))
NOTE(protocol_type_witness_tuple,none,
"possibly intended match %0 is unsuitable for tuple conformance; "
"the associated type requirement must be fulfilled by a type alias "
"with underlying type %1",
(Type, Type))

NOTE(protocol_witness_circularity,none,
"candidate references itself", ())
Expand Down
31 changes: 17 additions & 14 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7861,27 +7861,30 @@ Type DeclContext::getSelfTypeInContext() const {
return mapTypeIntoContext(getSelfInterfaceType());
}

TupleType *BuiltinTupleDecl::getTupleSelfType() const {
if (TupleSelfType)
return TupleSelfType;

TupleType *BuiltinTupleDecl::getTupleSelfType(const ExtensionDecl *owner) const {
auto &ctx = getASTContext();

// Get the generic parameter type 'Elements'.
auto paramType = getGenericParams()->getParams()[0]
->getDeclaredInterfaceType();
// Get the generic parameter type 'each T'.
GenericParamList *genericParams;
if (owner != nullptr) {
genericParams = owner->getGenericParams();
} else {
genericParams = getGenericParams();
}

// Build the pack expansion type 'Elements...'.
assert(genericParams != nullptr);
assert(genericParams->getParams().size() == 1);
assert(genericParams->getOuterParameters() == nullptr);
auto paramType = genericParams->getParams()[0]->getDeclaredInterfaceType();

// Build the pack expansion type 'repeat each T'.
Type packExpansionType = PackExpansionType::get(paramType, paramType);

// Build the one-element tuple type '(Elements...)'.
// Build the one-element tuple type '(repeat each T)'.
SmallVector<TupleTypeElt, 1> elts;
elts.push_back(packExpansionType);

const_cast<BuiltinTupleDecl *>(this)->TupleSelfType =
TupleType::get(elts, ctx);

return TupleSelfType;
return TupleType::get(elts, ctx);
}

/// Retrieve the interface type of 'self' for the given context.
Expand All @@ -7890,7 +7893,7 @@ Type DeclContext::getSelfInterfaceType() const {

if (auto *nominalDecl = getSelfNominalTypeDecl()) {
if (auto *builtinTupleDecl = dyn_cast<BuiltinTupleDecl>(nominalDecl))
return builtinTupleDecl->getTupleSelfType();
return builtinTupleDecl->getTupleSelfType(dyn_cast<ExtensionDecl>(this));

if (isa<ProtocolDecl>(nominalDecl)) {
auto *genericParams = nominalDecl->getGenericParams();
Expand Down
Loading