Skip to content
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

[4.0] [GSB] Improve handling of concrete types, type aliases, recursion #10565

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
05bc0ef
[GSB] Eliminate PotentialArchetype::NestedTypeUpdate.
DougGregor Jun 2, 2017
830da21
[GSB] Separate out a "structurally derived" requirement source kind.
DougGregor Jun 6, 2017
50a7ad5
[GSB] Improve handling of conformances resolved by concrete types.
DougGregor Jun 6, 2017
7c68366
[GSB] Remove unused form of addSameTypeRequirementDirect()
DougGregor Jun 7, 2017
2167a3f
[GSB] Break recursion based on the “root” type we’re creating require…
DougGregor Jun 7, 2017
398b99a
[GSB] Avoid recursively growing increasingly-nested potential archety…
DougGregor Jun 23, 2017
075a4c3
[GSB] Clean up the meaning of ArchetypeResolutionKind::(Complete)Well…
DougGregor Jun 2, 2017
6c4e4fd
[GSB] Centralize diagnosis of concrete types and conformance requirem…
DougGregor Jun 6, 2017
8295561
[GSB] Concretize nested types when merging two potential archetypes.
DougGregor Jun 7, 2017
9d681fa
[GSB] Diagnose all same-type-to-concrete conflicts consistently.
DougGregor Jun 5, 2017
e01e302
[GSB] Cope with typealiases within protocol hierarchies.
DougGregor Jun 8, 2017
9fdd79f
[GSB] When retrieving the archetype anchor, allow partial results.
DougGregor Jun 13, 2017
efe8fde
Add formerly-crashing test case for SR-4786 / rdar://problem/31955862.
DougGregor Jun 24, 2017
e1395ea
[GSB] Don't add invalid concrete requirements.
DougGregor Jun 24, 2017
3b8b73b
Add recently-fixed test case from SR-4737 / rdar://problem/31905232.
DougGregor Jun 24, 2017
f72fec0
[GSB] Ensure that we have superclass constraints from merged equiv cl…
DougGregor Jun 26, 2017
19f4ee7
[GSB] Don't crash when substitution fails to produce a type.
DougGregor Jun 26, 2017
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
9 changes: 6 additions & 3 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -1682,16 +1682,16 @@ ERROR(requires_generic_param_same_type_does_not_conform,none,
(Type, Identifier))
ERROR(requires_same_concrete_type,none,
"generic signature requires types %0 and %1 to be the same", (Type, Type))
ERROR(protocol_typealias_conflict, none,
"type alias %0 requires types %1 and %2 to be the same",
(Identifier, Type, Type))
WARNING(redundant_conformance_constraint,none,
"redundant conformance constraint %0: %1", (Type, ProtocolDecl *))
NOTE(redundant_conformance_here,none,
"conformance constraint %1: %2 %select{written here|implied here|"
"inferred from type here}0",
(unsigned, Type, ProtocolDecl *))

ERROR(same_type_conflict,none,
"%select{generic parameter |protocol |}0%1 cannot be equal to both "
"%2 and %3", (unsigned, Type, Type, Type))
WARNING(redundant_same_type_to_concrete,none,
"redundant same-type constraint %0 == %1", (Type, Type))
NOTE(same_type_redundancy_here,none,
Expand Down Expand Up @@ -1732,6 +1732,9 @@ WARNING(inherited_associated_type_redecl,none,
WARNING(typealias_override_associated_type,none,
"typealias overriding associated type %0 from protocol %1 is better "
"expressed as same-type constraint on the protocol", (DeclName, Type))
WARNING(associated_type_override_typealias,none,
"associated type %0 is redundant with type %0 declared in inherited "
"%1 %2", (DeclName, DescriptiveDeclKind, Type))

ERROR(generic_param_access,none,
"%0 %select{must be declared %select{"
Expand Down
94 changes: 56 additions & 38 deletions include/swift/AST/GenericSignatureBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "swift/AST/Decl.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/Identifier.h"
#include "swift/AST/ProtocolConformanceRef.h"
#include "swift/AST/Types.h"
#include "swift/AST/TypeLoc.h"
#include "swift/AST/TypeRepr.h"
Expand Down Expand Up @@ -74,6 +75,11 @@ enum class ArchetypeResolutionKind {
/// Only create a new potential archetype to describe this dependent type
/// if it is already known.
AlreadyKnown,

/// Only create a potential archetype when it is well-formed (i.e., we know
/// that there is a nested type with that name), but (unlike \c AlreadyKnown)
/// allow the creation of a new potential archetype.
WellFormed,
};

/// \brief Collects a set of requirements of generic parameters, both explicitly
Expand Down Expand Up @@ -176,6 +182,9 @@ class GenericSignatureBuilder {
/// the concrete type.
unsigned recursiveConcreteType : 1;

/// Whether we have an invalid concrete type.
unsigned invalidConcreteType : 1;

/// Whether we have detected recursion during the substitution of
/// the superclass type.
unsigned recursiveSuperclassType : 1;
Expand Down Expand Up @@ -281,16 +290,24 @@ class GenericSignatureBuilder {
FloatingRequirementSource source,
UnresolvedHandlingKind unresolvedHandling);

/// Resolve the conformance of the given potential archetype to
/// the given protocol when the potential archetype is known to be equivalent
/// to a concrete type.
///
/// \returns the requirement source for the resolved conformance, or nullptr
/// if the conformance could not be resolved.
const RequirementSource *resolveConcreteConformance(PotentialArchetype *pa,
ProtocolDecl *proto);

/// Retrieve the constraint source conformance for the superclass constraint
/// of the given potential archetype (if present) to the given protocol.
///
/// \param pa The potential archetype whose superclass constraint is being
/// queried.
///
/// \param proto The protocol to which we are establishing conformance.
const RequirementSource *resolveSuperConformance(
GenericSignatureBuilder::PotentialArchetype *pa,
ProtocolDecl *proto);
const RequirementSource *resolveSuperConformance(PotentialArchetype *pa,
ProtocolDecl *proto);

/// \brief Add a new conformance requirement specifying that the given
/// potential archetype conforms to the given protocol.
Expand All @@ -316,15 +333,6 @@ class GenericSignatureBuilder {
FloatingRequirementSource Source,
llvm::function_ref<void(Type, Type)> diagnoseMismatch);

/// \brief Add a new same-type requirement between two fully resolved types
/// (output of GenericSignatureBuilder::resolve).
///
/// The two types must not be incompatible concrete types.
ConstraintResult addSameTypeRequirementDirect(
ResolvedType paOrT1,
ResolvedType paOrT2,
FloatingRequirementSource Source);

/// \brief Add a new same-type requirement between two unresolved types.
///
/// The types are resolved with \c GenericSignatureBuilder::resolve, and must
Expand Down Expand Up @@ -770,7 +778,7 @@ class GenericSignatureBuilder::RequirementSource final

/// A requirement that was resolved via a superclass requirement.
///
/// This stores the \c ProtocolConformance* used to resolve the
/// This stores the \c ProtocolConformanceRef used to resolve the
/// requirement.
Superclass,

Expand All @@ -784,6 +792,10 @@ class GenericSignatureBuilder::RequirementSource final
/// This stores the \c ProtocolConformance* used to resolve the
/// requirement.
Concrete,

/// A requirement that was resolved based on structural derivation from
/// another requirement.
Derived,
};

/// The kind of requirement source.
Expand All @@ -792,6 +804,7 @@ class GenericSignatureBuilder::RequirementSource final
private:
/// The kind of storage we have.
enum class StorageKind : uint8_t {
None,
RootArchetype,
StoredType,
ProtocolConformance,
Expand All @@ -816,7 +829,7 @@ class GenericSignatureBuilder::RequirementSource final
TypeBase *type;

/// A protocol conformance used to satisfy the requirement.
ProtocolConformance *conformance;
void *conformance;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't this just be a ProtocolConfomanceRef? You're including the header above

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sigh. Non-POD types are really annoying to work with in unions.


/// An associated type to which a requirement is being applied.
AssociatedTypeDecl *assocType;
Expand All @@ -839,6 +852,7 @@ class GenericSignatureBuilder::RequirementSource final
case Superclass:
case Parent:
case Concrete:
case Derived:
return 0;
}

Expand Down Expand Up @@ -882,6 +896,7 @@ class GenericSignatureBuilder::RequirementSource final
case Superclass:
case Parent:
case Concrete:
case Derived:
return false;
}

Expand Down Expand Up @@ -931,7 +946,7 @@ class GenericSignatureBuilder::RequirementSource final
}

RequirementSource(Kind kind, const RequirementSource *parent,
ProtocolConformance *conformance)
ProtocolConformanceRef conformance)
: kind(kind), storageKind(StorageKind::ProtocolConformance),
hasTrailingWrittenRequirementLoc(false),
usesRequirementSignature(false), parent(parent) {
Expand All @@ -940,7 +955,7 @@ class GenericSignatureBuilder::RequirementSource final
assert(isAcceptableStorageKind(kind, storageKind) &&
"RequirementSource kind/storageKind mismatch");

storage.conformance = conformance;
storage.conformance = conformance.getOpaqueValue();
}

RequirementSource(Kind kind, const RequirementSource *parent,
Expand All @@ -956,6 +971,16 @@ class GenericSignatureBuilder::RequirementSource final
storage.assocType = assocType;
}

RequirementSource(Kind kind, const RequirementSource *parent)
: kind(kind), storageKind(StorageKind::None),
hasTrailingWrittenRequirementLoc(false),
usesRequirementSignature(false), parent(parent) {
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
"Root RequirementSource should not have parent (or vice versa)");
assert(isAcceptableStorageKind(kind, storageKind) &&
"RequirementSource kind/storageKind mismatch");
}

public:
/// Retrieve an abstract requirement source.
static const RequirementSource *forAbstract(PotentialArchetype *root);
Expand Down Expand Up @@ -997,13 +1022,14 @@ class GenericSignatureBuilder::RequirementSource final
/// A requirement source that describes that a requirement that is resolved
/// via a superclass requirement.
const RequirementSource *viaSuperclass(
GenericSignatureBuilder &builder,
ProtocolConformance *conformance) const;
GenericSignatureBuilder &builder,
ProtocolConformanceRef conformance) const;

/// A requirement source that describes that a requirement that is resolved
/// via a same-type-to-concrete requirement.
const RequirementSource *viaConcrete(GenericSignatureBuilder &builder,
ProtocolConformance *conformance) const;
const RequirementSource *viaConcrete(
GenericSignatureBuilder &builder,
ProtocolConformanceRef conformance) const;

/// A constraint source that describes that a constraint that is resolved
/// for a nested type via a constraint on its parent.
Expand All @@ -1012,6 +1038,10 @@ class GenericSignatureBuilder::RequirementSource final
const RequirementSource *viaParent(GenericSignatureBuilder &builder,
AssociatedTypeDecl *assocType) const;

/// A constraint source that describes a constraint that is structurally
/// derived from another constraint but does not require further information.
const RequirementSource *viaDerived(GenericSignatureBuilder &builder) const;

/// Retrieve the root requirement source.
const RequirementSource *getRoot() const;

Expand Down Expand Up @@ -1100,9 +1130,9 @@ class GenericSignatureBuilder::RequirementSource final
ProtocolDecl *getProtocolDecl() const;

/// Retrieve the protocol conformance for this requirement, if there is one.
ProtocolConformance *getProtocolConformance() const {
if (storageKind != StorageKind::ProtocolConformance) return nullptr;
return storage.conformance;
ProtocolConformanceRef getProtocolConformance() const {
assert(storageKind == StorageKind::ProtocolConformance);
return ProtocolConformanceRef::getFromOpaqueValue(storage.conformance);
}

/// Retrieve the associated type declaration for this requirement, if there
Expand Down Expand Up @@ -1577,18 +1607,6 @@ class GenericSignatureBuilder::PotentialArchetype {
PotentialArchetype *getNestedType(TypeDecl *concreteDecl,
GenericSignatureBuilder &builder);

/// Describes the kind of update that is performed.
enum class NestedTypeUpdate {
/// Resolve an existing potential archetype, but don't create a new
/// one if not present.
ResolveExisting,
/// If this potential archetype is missing, create it.
AddIfMissing,
/// If this potential archetype is missing and would be a better anchor,
/// create it.
AddIfBetterAnchor,
};

/// \brief Retrieve (or create) a nested type that is the current best
/// nested archetype anchor (locally) with the given name.
///
Expand All @@ -1597,7 +1615,7 @@ class GenericSignatureBuilder::PotentialArchetype {
PotentialArchetype *getNestedArchetypeAnchor(
Identifier name,
GenericSignatureBuilder &builder,
NestedTypeUpdate kind = NestedTypeUpdate::AddIfMissing);
ArchetypeResolutionKind kind);

/// Update the named nested type when we know this type conforms to the given
/// protocol.
Expand All @@ -1607,7 +1625,7 @@ class GenericSignatureBuilder::PotentialArchetype {
/// a potential archetype should not be created if it's missing.
PotentialArchetype *updateNestedTypeForConformance(
PointerUnion<AssociatedTypeDecl *, TypeDecl *> type,
NestedTypeUpdate kind);
ArchetypeResolutionKind kind);

/// Update the named nested type when we know this type conforms to the given
/// protocol.
Expand All @@ -1618,7 +1636,7 @@ class GenericSignatureBuilder::PotentialArchetype {
PotentialArchetype *updateNestedTypeForConformance(
Identifier name,
ProtocolDecl *protocol,
NestedTypeUpdate kind);
ArchetypeResolutionKind kind);

/// \brief Retrieve (or build) the type corresponding to the potential
/// archetype within the given generic environment.
Expand Down
2 changes: 1 addition & 1 deletion lib/AST/GenericSignature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,7 @@ ConformanceAccessPath GenericSignature::getConformanceAccessPath(
auto pa =
reqSigBuilder.resolveArchetype(
storedType,
ArchetypeResolutionKind::CompleteWellFormed);
ArchetypeResolutionKind::AlwaysPartial);
auto equivClass = pa->getOrCreateEquivalenceClass();

// Find the conformance of this potential archetype to the protocol in
Expand Down
Loading