mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Introduce a new representation of polymorphic function types.
Introduces a new kind of function type, GenericFunctionType, that represents a polymorphic function type with all of its generic parameters and requirements stored in a more readily canonicalizable form. It is meant to eventually replace PolymorphicFunctionType, but for now we build it up in parallel so we can switch over to it pieacemeal. Note: this representation is built and then thrown away. We'll start recording it soon. Swift SVN r8881
This commit is contained in:
@@ -32,7 +32,7 @@ class ArchetypeType;
|
|||||||
class AssociatedTypeDecl;
|
class AssociatedTypeDecl;
|
||||||
class Pattern;
|
class Pattern;
|
||||||
class ProtocolDecl;
|
class ProtocolDecl;
|
||||||
class Requirement;
|
class RequirementRepr;
|
||||||
class SourceLoc;
|
class SourceLoc;
|
||||||
class TranslationUnit;
|
class TranslationUnit;
|
||||||
class Type;
|
class Type;
|
||||||
@@ -104,6 +104,9 @@ public:
|
|||||||
ArchetypeBuilder(ArchetypeBuilder &&);
|
ArchetypeBuilder(ArchetypeBuilder &&);
|
||||||
~ArchetypeBuilder();
|
~ArchetypeBuilder();
|
||||||
|
|
||||||
|
/// Retrieve the translation unit.
|
||||||
|
TranslationUnit &getTranslationUnit() const { return TU; }
|
||||||
|
|
||||||
/// \brief Add a new generic parameter for which there may be requirements.
|
/// \brief Add a new generic parameter for which there may be requirements.
|
||||||
///
|
///
|
||||||
/// \returns true if an error occurred, false otherwise.
|
/// \returns true if an error occurred, false otherwise.
|
||||||
@@ -114,7 +117,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// \returns true if this requirement makes the set of requirements
|
/// \returns true if this requirement makes the set of requirements
|
||||||
/// inconsistent, in which case a diagnostic will have been issued.
|
/// inconsistent, in which case a diagnostic will have been issued.
|
||||||
bool addRequirement(const Requirement &Req);
|
bool addRequirement(const RequirementRepr &Req);
|
||||||
|
|
||||||
/// \brief Add a new, implicit conformance requirement for one of the
|
/// \brief Add a new, implicit conformance requirement for one of the
|
||||||
/// parameters.
|
/// parameters.
|
||||||
@@ -180,7 +183,6 @@ public:
|
|||||||
/// list.
|
/// list.
|
||||||
ArrayRef<ArchetypeType *> getAllArchetypes();
|
ArrayRef<ArchetypeType *> getAllArchetypes();
|
||||||
|
|
||||||
// FIXME: Infer requirements from signatures
|
|
||||||
// FIXME: Compute the set of 'extra' witness tables needed to express this
|
// FIXME: Compute the set of 'extra' witness tables needed to express this
|
||||||
// requirement set.
|
// requirement set.
|
||||||
|
|
||||||
@@ -233,6 +235,10 @@ public:
|
|||||||
/// \brief Retrieve the full display name of this potential archetype.
|
/// \brief Retrieve the full display name of this potential archetype.
|
||||||
std::string getFullName() const;
|
std::string getFullName() const;
|
||||||
|
|
||||||
|
/// Retrieve the parent of this potential archetype, which will be non-null
|
||||||
|
/// when this potential archetype is an associated type.
|
||||||
|
PotentialArchetype *getParent() const { return Parent; }
|
||||||
|
|
||||||
/// Retrieve the set of protocols to which this type conforms.
|
/// Retrieve the set of protocols to which this type conforms.
|
||||||
ArrayRef<ProtocolDecl *> getConformsTo() const {
|
ArrayRef<ProtocolDecl *> getConformsTo() const {
|
||||||
return llvm::makeArrayRef(ConformsTo.begin(), ConformsTo.end());
|
return llvm::makeArrayRef(ConformsTo.begin(), ConformsTo.end());
|
||||||
@@ -241,6 +247,11 @@ public:
|
|||||||
/// Retrieve the superclass of this archetype.
|
/// Retrieve the superclass of this archetype.
|
||||||
Type getSuperclass() const { return Superclass; }
|
Type getSuperclass() const { return Superclass; }
|
||||||
|
|
||||||
|
/// Retrieve the set of nested types.
|
||||||
|
const llvm::DenseMap<Identifier, PotentialArchetype*> &getNestedTypes() const{
|
||||||
|
return NestedTypes;
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Determine the nesting depth of this potential archetype, e.g.,
|
/// \brief Determine the nesting depth of this potential archetype, e.g.,
|
||||||
/// the number of associated type references.
|
/// the number of associated type references.
|
||||||
unsigned getNestingDepth() const;
|
unsigned getNestingDepth() const;
|
||||||
@@ -257,6 +268,9 @@ public:
|
|||||||
ArchetypeType *getArchetype(AssociatedTypeDecl * /*nullable*/ rootAssocTy,
|
ArchetypeType *getArchetype(AssociatedTypeDecl * /*nullable*/ rootAssocTy,
|
||||||
TranslationUnit &tu);
|
TranslationUnit &tu);
|
||||||
|
|
||||||
|
/// Retrieve the associated type declaration for a given nested type.
|
||||||
|
AssociatedTypeDecl *getAssociatedType(TranslationUnit &tu, Identifier name);
|
||||||
|
|
||||||
void dump(llvm::raw_ostream &Out, unsigned Indent);
|
void dump(llvm::raw_ostream &Out, unsigned Indent);
|
||||||
|
|
||||||
friend class ArchetypeBuilder;
|
friend class ArchetypeBuilder;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "swift/AST/DefaultArgumentKind.h"
|
#include "swift/AST/DefaultArgumentKind.h"
|
||||||
#include "swift/AST/KnownProtocols.h"
|
#include "swift/AST/KnownProtocols.h"
|
||||||
#include "swift/AST/Identifier.h"
|
#include "swift/AST/Identifier.h"
|
||||||
|
#include "swift/AST/Requirement.h"
|
||||||
#include "swift/AST/Substitution.h"
|
#include "swift/AST/Substitution.h"
|
||||||
#include "swift/AST/Type.h"
|
#include "swift/AST/Type.h"
|
||||||
#include "swift/AST/TypeLoc.h"
|
#include "swift/AST/TypeLoc.h"
|
||||||
@@ -427,30 +428,19 @@ public:
|
|||||||
void setDeclContext(DeclContext *DC);
|
void setDeclContext(DeclContext *DC);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Describes the kind of a requirement that occurs within a requirements
|
|
||||||
/// clause.
|
|
||||||
enum class RequirementKind : unsigned int {
|
|
||||||
/// \brief A conformance requirement T : P, where T is a type that depends
|
|
||||||
/// on a generic parameter and P is a protocol to which T must conform.
|
|
||||||
Conformance,
|
|
||||||
/// \brief A same-type requirement T == U, where T and U are types that
|
|
||||||
/// shall be equivalent.
|
|
||||||
SameType
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \brief A single requirement in a 'where' clause, which places additional
|
/// \brief A single requirement in a 'where' clause, which places additional
|
||||||
/// restrictions on the generic parameters or associated types of a generic
|
/// restrictions on the generic parameters or associated types of a generic
|
||||||
/// function, type, or protocol.
|
/// function, type, or protocol.
|
||||||
///
|
///
|
||||||
/// This always represents a requirement spelled in the source code. It is
|
/// This always represents a requirement spelled in the source code. It is
|
||||||
/// never generated implicitly.
|
/// never generated implicitly.
|
||||||
class Requirement {
|
class RequirementRepr {
|
||||||
SourceLoc SeparatorLoc;
|
SourceLoc SeparatorLoc;
|
||||||
RequirementKind Kind : 1;
|
RequirementKind Kind : 1;
|
||||||
bool Invalid : 1;
|
bool Invalid : 1;
|
||||||
TypeLoc Types[2];
|
TypeLoc Types[2];
|
||||||
|
|
||||||
Requirement(SourceLoc SeparatorLoc, RequirementKind Kind, TypeLoc FirstType,
|
RequirementRepr(SourceLoc SeparatorLoc, RequirementKind Kind, TypeLoc FirstType,
|
||||||
TypeLoc SecondType)
|
TypeLoc SecondType)
|
||||||
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
|
: SeparatorLoc(SeparatorLoc), Kind(Kind), Invalid(false),
|
||||||
Types{FirstType, SecondType} { }
|
Types{FirstType, SecondType} { }
|
||||||
@@ -464,7 +454,7 @@ public:
|
|||||||
/// this requirement was implied.
|
/// this requirement was implied.
|
||||||
/// \param Constraint The protocol or protocol composition to which the
|
/// \param Constraint The protocol or protocol composition to which the
|
||||||
/// subject must conform, or superclass from which the subject must inherit.
|
/// subject must conform, or superclass from which the subject must inherit.
|
||||||
static Requirement getConformance(TypeLoc Subject,
|
static RequirementRepr getConformance(TypeLoc Subject,
|
||||||
SourceLoc ColonLoc,
|
SourceLoc ColonLoc,
|
||||||
TypeLoc Constraint) {
|
TypeLoc Constraint) {
|
||||||
return { ColonLoc, RequirementKind::Conformance, Subject, Constraint };
|
return { ColonLoc, RequirementKind::Conformance, Subject, Constraint };
|
||||||
@@ -476,7 +466,7 @@ public:
|
|||||||
/// \param EqualLoc The location of the '==' in the same-type constraint, or
|
/// \param EqualLoc The location of the '==' in the same-type constraint, or
|
||||||
/// an invalid location if this requirement was implied.
|
/// an invalid location if this requirement was implied.
|
||||||
/// \param SecondType The second type.
|
/// \param SecondType The second type.
|
||||||
static Requirement getSameType(TypeLoc FirstType,
|
static RequirementRepr getSameType(TypeLoc FirstType,
|
||||||
SourceLoc EqualLoc,
|
SourceLoc EqualLoc,
|
||||||
TypeLoc SecondType) {
|
TypeLoc SecondType) {
|
||||||
return { EqualLoc, RequirementKind::SameType, FirstType, SecondType };
|
return { EqualLoc, RequirementKind::SameType, FirstType, SecondType };
|
||||||
@@ -589,7 +579,7 @@ class GenericParamList {
|
|||||||
SourceRange Brackets;
|
SourceRange Brackets;
|
||||||
unsigned NumParams;
|
unsigned NumParams;
|
||||||
SourceLoc WhereLoc;
|
SourceLoc WhereLoc;
|
||||||
MutableArrayRef<Requirement> Requirements;
|
MutableArrayRef<RequirementRepr> Requirements;
|
||||||
ArrayRef<ArchetypeType *> AllArchetypes;
|
ArrayRef<ArchetypeType *> AllArchetypes;
|
||||||
|
|
||||||
GenericParamList *OuterParameters;
|
GenericParamList *OuterParameters;
|
||||||
@@ -597,7 +587,7 @@ class GenericParamList {
|
|||||||
GenericParamList(SourceLoc LAngleLoc,
|
GenericParamList(SourceLoc LAngleLoc,
|
||||||
ArrayRef<GenericParam> Params,
|
ArrayRef<GenericParam> Params,
|
||||||
SourceLoc WhereLoc,
|
SourceLoc WhereLoc,
|
||||||
MutableArrayRef<Requirement> Requirements,
|
MutableArrayRef<RequirementRepr> Requirements,
|
||||||
SourceLoc RAngleLoc);
|
SourceLoc RAngleLoc);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -630,7 +620,7 @@ public:
|
|||||||
SourceLoc LAngleLoc,
|
SourceLoc LAngleLoc,
|
||||||
ArrayRef<GenericParam> Params,
|
ArrayRef<GenericParam> Params,
|
||||||
SourceLoc WhereLoc,
|
SourceLoc WhereLoc,
|
||||||
MutableArrayRef<Requirement> Requirements,
|
MutableArrayRef<RequirementRepr> Requirements,
|
||||||
SourceLoc RAngleLoc);
|
SourceLoc RAngleLoc);
|
||||||
|
|
||||||
MutableArrayRef<GenericParam> getParams() {
|
MutableArrayRef<GenericParam> getParams() {
|
||||||
@@ -659,7 +649,7 @@ public:
|
|||||||
/// This list may contain both explicitly-written requirements as well as
|
/// This list may contain both explicitly-written requirements as well as
|
||||||
/// implicitly-generated requirements, and may be non-empty even if no
|
/// implicitly-generated requirements, and may be non-empty even if no
|
||||||
/// 'where' keyword is present.
|
/// 'where' keyword is present.
|
||||||
MutableArrayRef<Requirement> getRequirements() { return Requirements; }
|
MutableArrayRef<RequirementRepr> getRequirements() { return Requirements; }
|
||||||
|
|
||||||
/// \brief Retrieve the set of additional requirements placed on these
|
/// \brief Retrieve the set of additional requirements placed on these
|
||||||
/// generic parameters and types derived from them.
|
/// generic parameters and types derived from them.
|
||||||
@@ -667,7 +657,7 @@ public:
|
|||||||
/// This list may contain both explicitly-written requirements as well as
|
/// This list may contain both explicitly-written requirements as well as
|
||||||
/// implicitly-generated requirements, and may be non-empty even if no
|
/// implicitly-generated requirements, and may be non-empty even if no
|
||||||
/// 'where' keyword is present.
|
/// 'where' keyword is present.
|
||||||
ArrayRef<Requirement> getRequirements() const { return Requirements; }
|
ArrayRef<RequirementRepr> getRequirements() const { return Requirements; }
|
||||||
|
|
||||||
/// \brief Override the set of requirements associated with this generic
|
/// \brief Override the set of requirements associated with this generic
|
||||||
/// parameter list.
|
/// parameter list.
|
||||||
@@ -676,7 +666,7 @@ public:
|
|||||||
/// to be a superset of the existing set of requirements (although this
|
/// to be a superset of the existing set of requirements (although this
|
||||||
/// property is not checked here). It is assumed that the array reference
|
/// property is not checked here). It is assumed that the array reference
|
||||||
/// refers to ASTContext-allocated memory.
|
/// refers to ASTContext-allocated memory.
|
||||||
void overrideRequirements(MutableArrayRef<Requirement> NewRequirements) {
|
void overrideRequirements(MutableArrayRef<RequirementRepr> NewRequirements) {
|
||||||
Requirements = NewRequirements;
|
Requirements = NewRequirements;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -887,8 +877,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Note that we have already type-checked the inheritance clause.
|
/// Note that we have already type-checked the inheritance clause.
|
||||||
void setCheckedInheritanceClause() {
|
void setCheckedInheritanceClause(bool checked = true) {
|
||||||
ExtensionDeclBits.CheckedInheritanceClause = true;
|
ExtensionDeclBits.CheckedInheritanceClause = checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieve the set of protocols to which this extension conforms.
|
/// \brief Retrieve the set of protocols to which this extension conforms.
|
||||||
@@ -1158,8 +1148,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Note that we have already type-checked the inheritance clause.
|
/// Note that we have already type-checked the inheritance clause.
|
||||||
void setCheckedInheritanceClause() {
|
void setCheckedInheritanceClause(bool checked = true) {
|
||||||
TypeDeclBits.CheckedInheritanceClause = true;
|
TypeDeclBits.CheckedInheritanceClause = checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieve the set of protocols to which this type conforms.
|
/// \brief Retrieve the set of protocols to which this type conforms.
|
||||||
|
|||||||
63
include/swift/AST/Requirement.h
Normal file
63
include/swift/AST/Requirement.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
//===--- Requirement.h - Swift Requirement ASTs -----------------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// This source file is part of the Swift.org open source project
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
||||||
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||||
|
//
|
||||||
|
// See http://swift.org/LICENSE.txt for license information
|
||||||
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This file defines the Requirement class and subclasses.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef SWIFT_AST_REQUIREMENT_H
|
||||||
|
#define SWIFT_AST_REQUIREMENT_H
|
||||||
|
|
||||||
|
#include "swift/AST/Type.h"
|
||||||
|
#include "llvm/ADT/PointerIntPair.h"
|
||||||
|
|
||||||
|
namespace swift {
|
||||||
|
|
||||||
|
/// \brief Describes the kind of a requirement that occurs within a requirements
|
||||||
|
/// clause.
|
||||||
|
enum class RequirementKind : unsigned int {
|
||||||
|
/// \brief A conformance requirement T : P, where T is a type that depends
|
||||||
|
/// on a generic parameter and P is a protocol to which T must conform.
|
||||||
|
Conformance,
|
||||||
|
/// \brief A same-type requirement T == U, where T and U are types that
|
||||||
|
/// shall be equivalent.
|
||||||
|
SameType
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief A single requirement placed on the type parameters (or associated
|
||||||
|
/// types thereof) of a
|
||||||
|
class Requirement {
|
||||||
|
llvm::PointerIntPair<Type, 1, RequirementKind> FirstTypeAndKind;
|
||||||
|
Type SecondType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Create a conformance or same-type requirement.
|
||||||
|
Requirement(RequirementKind kind, Type first, Type second)
|
||||||
|
: FirstTypeAndKind(first, kind), SecondType(second) { }
|
||||||
|
|
||||||
|
/// \brief Determine the kind of requirement.
|
||||||
|
RequirementKind getKind() const { return FirstTypeAndKind.getInt(); }
|
||||||
|
|
||||||
|
/// \brief Retrieve the first type.
|
||||||
|
Type getFirstType() const {
|
||||||
|
return FirstTypeAndKind.getPointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the second type.
|
||||||
|
Type getSecondType() const {
|
||||||
|
return SecondType;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace swift
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -117,7 +117,8 @@ TYPE(DependentMember, Type)
|
|||||||
ABSTRACT_TYPE(AnyFunction, Type)
|
ABSTRACT_TYPE(AnyFunction, Type)
|
||||||
TYPE(Function, AnyFunctionType)
|
TYPE(Function, AnyFunctionType)
|
||||||
TYPE(PolymorphicFunction, AnyFunctionType)
|
TYPE(PolymorphicFunction, AnyFunctionType)
|
||||||
TYPE_RANGE(AnyFunction, Function, PolymorphicFunction)
|
TYPE(GenericFunction, AnyFunctionType)
|
||||||
|
TYPE_RANGE(AnyFunction, Function, GenericFunction)
|
||||||
TYPE(Array, Type)
|
TYPE(Array, Type)
|
||||||
ABSTRACT_SUGARED_TYPE(SyntaxSugar, Type)
|
ABSTRACT_SUGARED_TYPE(SyntaxSugar, Type)
|
||||||
SUGARED_TYPE(ArraySlice, SyntaxSugarType)
|
SUGARED_TYPE(ArraySlice, SyntaxSugarType)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "swift/AST/DeclContext.h"
|
#include "swift/AST/DeclContext.h"
|
||||||
#include "swift/AST/DefaultArgumentKind.h"
|
#include "swift/AST/DefaultArgumentKind.h"
|
||||||
#include "swift/AST/Ownership.h"
|
#include "swift/AST/Ownership.h"
|
||||||
|
#include "swift/AST/Requirement.h"
|
||||||
#include "swift/AST/Type.h"
|
#include "swift/AST/Type.h"
|
||||||
#include "swift/AST/Identifier.h"
|
#include "swift/AST/Identifier.h"
|
||||||
#include "swift/Basic/ArrayRefView.h"
|
#include "swift/Basic/ArrayRefView.h"
|
||||||
@@ -40,6 +41,7 @@ namespace swift {
|
|||||||
class ClassDecl;
|
class ClassDecl;
|
||||||
class ExprHandle;
|
class ExprHandle;
|
||||||
class GenericTypeParamDecl;
|
class GenericTypeParamDecl;
|
||||||
|
class GenericTypeParamType;
|
||||||
class GenericParam;
|
class GenericParam;
|
||||||
class GenericParamList;
|
class GenericParamList;
|
||||||
class Identifier;
|
class Identifier;
|
||||||
@@ -361,12 +363,12 @@ private:
|
|||||||
// Make vanilla new/delete illegal for Types.
|
// Make vanilla new/delete illegal for Types.
|
||||||
void *operator new(size_t Bytes) throw() = delete;
|
void *operator new(size_t Bytes) throw() = delete;
|
||||||
void operator delete(void *Data) throw() = delete;
|
void operator delete(void *Data) throw() = delete;
|
||||||
void *operator new(size_t Bytes, void *Mem) throw() = delete;
|
|
||||||
public:
|
public:
|
||||||
// Only allow allocation of Types using the allocator in ASTContext
|
// Only allow allocation of Types using the allocator in ASTContext
|
||||||
// or by doing a placement new.
|
// or by doing a placement new.
|
||||||
void *operator new(size_t bytes, const ASTContext &ctx,
|
void *operator new(size_t bytes, const ASTContext &ctx,
|
||||||
AllocationArena arena, unsigned alignment = 8);
|
AllocationArena arena, unsigned alignment = 8);
|
||||||
|
void *operator new(size_t Bytes, void *Mem) throw() { return Mem; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ErrorType - This represents a type that was erroneously constructed. This
|
/// ErrorType - This represents a type that was erroneously constructed. This
|
||||||
@@ -1394,7 +1396,83 @@ private:
|
|||||||
const ASTContext &C);
|
const ASTContext &C);
|
||||||
};
|
};
|
||||||
DEFINE_EMPTY_CAN_TYPE_WRAPPER(PolymorphicFunctionType, AnyFunctionType)
|
DEFINE_EMPTY_CAN_TYPE_WRAPPER(PolymorphicFunctionType, AnyFunctionType)
|
||||||
|
|
||||||
|
/// Describes a generic function type.
|
||||||
|
///
|
||||||
|
/// A generic function type describes a function that is polymorphic with
|
||||||
|
/// respect to some set of generic parameters and the requirements placed
|
||||||
|
/// on those parameters and dependent member types thereof. The input and
|
||||||
|
/// output types of the generic function can be expressed in terms of those
|
||||||
|
/// generic parameters.
|
||||||
|
///
|
||||||
|
/// FIXME: \c GenericFunctionType is meant as a replacement for
|
||||||
|
/// \c PolymorphicFunctionType.
|
||||||
|
class GenericFunctionType : public AnyFunctionType,
|
||||||
|
public llvm::FoldingSetNode {
|
||||||
|
unsigned NumGenericParams;
|
||||||
|
unsigned NumRequirements;
|
||||||
|
|
||||||
|
/// Retrieve a mutable version of the generic parameters.
|
||||||
|
MutableArrayRef<GenericTypeParamType *> getGenericParamsBuffer() {
|
||||||
|
return { reinterpret_cast<GenericTypeParamType **>(this + 1),
|
||||||
|
NumGenericParams };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve a mutable verison of the requirements.
|
||||||
|
MutableArrayRef<Requirement> getRequirementsBuffer() {
|
||||||
|
void *genericParams = getGenericParamsBuffer().end();
|
||||||
|
return { reinterpret_cast<Requirement *>(genericParams),
|
||||||
|
NumRequirements };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a new generic function type.
|
||||||
|
GenericFunctionType(ArrayRef<GenericTypeParamType *> genericParams,
|
||||||
|
ArrayRef<Requirement> requirements,
|
||||||
|
Type input,
|
||||||
|
Type result,
|
||||||
|
const ExtInfo &info,
|
||||||
|
const ASTContext *ctx);
|
||||||
|
public:
|
||||||
|
/// Create a new generic function type.
|
||||||
|
static GenericFunctionType *get(ArrayRef<GenericTypeParamType *> params,
|
||||||
|
ArrayRef<Requirement> requirements,
|
||||||
|
Type input,
|
||||||
|
Type result,
|
||||||
|
const ExtInfo &info,
|
||||||
|
const ASTContext &ctx);
|
||||||
|
|
||||||
|
/// Retrieve the generic parameters of this polymorphic function type.
|
||||||
|
ArrayRef<GenericTypeParamType *> getGenericParams() const {
|
||||||
|
return { reinterpret_cast<GenericTypeParamType * const *>(this + 1),
|
||||||
|
NumGenericParams };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve the requirements of this polymorphic function type.
|
||||||
|
ArrayRef<Requirement> getRequirements() const {
|
||||||
|
const void *genericParams = getGenericParams().end();
|
||||||
|
return { reinterpret_cast<const Requirement *>(genericParams),
|
||||||
|
NumRequirements };
|
||||||
|
}
|
||||||
|
|
||||||
|
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
|
Profile(ID, getGenericParams(), getRequirements(), getInput(), getResult(),
|
||||||
|
getExtInfo());
|
||||||
|
}
|
||||||
|
static void Profile(llvm::FoldingSetNodeID &ID,
|
||||||
|
ArrayRef<GenericTypeParamType *> params,
|
||||||
|
ArrayRef<Requirement> requirements,
|
||||||
|
Type input,
|
||||||
|
Type result,
|
||||||
|
const ExtInfo &info);
|
||||||
|
|
||||||
|
// Implement isa/cast/dyncast/etc.
|
||||||
|
static bool classof(const TypeBase *T) {
|
||||||
|
return T->getKind() == TypeKind::GenericFunction;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DEFINE_EMPTY_CAN_TYPE_WRAPPER(GenericFunctionType, AnyFunctionType)
|
||||||
|
|
||||||
/// ArrayType - An array type has a base type and either an unspecified or a
|
/// ArrayType - An array type has a base type and either an unspecified or a
|
||||||
/// constant size. For example "int[]" and "int[4]". Array types cannot have
|
/// constant size. For example "int[]" and "int[4]". Array types cannot have
|
||||||
/// size = 0.
|
/// size = 0.
|
||||||
@@ -2274,6 +2352,19 @@ case TypeKind::Id:
|
|||||||
function->getResult().findIf(pred);
|
function->getResult().findIf(pred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TypeKind::GenericFunction: {
|
||||||
|
auto function = cast<GenericFunctionType>(base);
|
||||||
|
for (auto param : function->getGenericParams())
|
||||||
|
if (Type(param).findIf(pred))
|
||||||
|
return true;
|
||||||
|
for (const auto &req : function->getRequirements())
|
||||||
|
if (req.getFirstType().findIf(pred) ||
|
||||||
|
req.getSecondType().findIf(pred))
|
||||||
|
return true;
|
||||||
|
return function->getInput().findIf(pred) ||
|
||||||
|
function->getResult().findIf(pred);
|
||||||
|
}
|
||||||
|
|
||||||
case TypeKind::Array:
|
case TypeKind::Array:
|
||||||
return cast<ArrayType>(base)->getBaseType().findIf(pred);
|
return cast<ArrayType>(base)->getBaseType().findIf(pred);
|
||||||
|
|
||||||
@@ -2535,6 +2626,72 @@ case TypeKind::Id:
|
|||||||
ctx);
|
ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TypeKind::GenericFunction: {
|
||||||
|
GenericFunctionType *function = cast<GenericFunctionType>(base);
|
||||||
|
bool anyChanges = false;
|
||||||
|
|
||||||
|
// Transform generic parameters.
|
||||||
|
SmallVector<GenericTypeParamType *, 4> genericParams;
|
||||||
|
for (auto param : function->getGenericParams()) {
|
||||||
|
Type paramTy = Type(param).transform(ctx, fn);
|
||||||
|
if (!paramTy)
|
||||||
|
return Type();
|
||||||
|
|
||||||
|
if (auto newParam = paramTy->getAs<GenericTypeParamType>()) {
|
||||||
|
if (newParam != param)
|
||||||
|
anyChanges = true;
|
||||||
|
|
||||||
|
genericParams.push_back(newParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform requirements.
|
||||||
|
SmallVector<Requirement, 4> requirements;
|
||||||
|
for (const auto &req : function->getRequirements()) {
|
||||||
|
auto firstType = req.getFirstType().transform(ctx, fn);
|
||||||
|
if (!firstType)
|
||||||
|
return Type();
|
||||||
|
|
||||||
|
auto secondType = req.getSecondType().transform(ctx, fn);
|
||||||
|
if (!secondType)
|
||||||
|
return Type();
|
||||||
|
|
||||||
|
if (firstType->isDependentType() || secondType->isDependentType()) {
|
||||||
|
if (firstType.getPointer() != req.getFirstType().getPointer() ||
|
||||||
|
secondType.getPointer() != req.getSecondType().getPointer())
|
||||||
|
anyChanges = true;
|
||||||
|
|
||||||
|
requirements.push_back(Requirement(req.getKind(), firstType,
|
||||||
|
secondType));
|
||||||
|
} else
|
||||||
|
anyChanges = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform input type.
|
||||||
|
auto inputTy = function->getInput().transform(ctx, fn);
|
||||||
|
if (!inputTy)
|
||||||
|
return Type();
|
||||||
|
|
||||||
|
// Transform result type.
|
||||||
|
auto resultTy = function->getResult().transform(ctx, fn);
|
||||||
|
if (!resultTy)
|
||||||
|
return Type();
|
||||||
|
|
||||||
|
// Check whether anything changed.
|
||||||
|
if (!anyChanges &&
|
||||||
|
inputTy.getPointer() == function->getInput().getPointer() &&
|
||||||
|
resultTy.getPointer() == function->getResult().getPointer())
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
// If no generic parameters remain, this is a non-generic function type.
|
||||||
|
if (genericParams.empty())
|
||||||
|
return FunctionType::get(inputTy, resultTy, function->getExtInfo(), ctx);
|
||||||
|
|
||||||
|
// Produce the new generic function type.
|
||||||
|
return GenericFunctionType::get(genericParams, requirements, inputTy,
|
||||||
|
resultTy, function->getExtInfo(), ctx);
|
||||||
|
}
|
||||||
|
|
||||||
case TypeKind::Array: {
|
case TypeKind::Array: {
|
||||||
auto array = cast<ArrayType>(base);
|
auto array = cast<ArrayType>(base);
|
||||||
auto baseTy = array->getBaseType().transform(ctx, fn);
|
auto baseTy = array->getBaseType().transform(ctx, fn);
|
||||||
|
|||||||
@@ -727,7 +727,7 @@ public:
|
|||||||
GenericParamList *parseGenericParameters(SourceLoc LAngleLoc);
|
GenericParamList *parseGenericParameters(SourceLoc LAngleLoc);
|
||||||
GenericParamList *maybeParseGenericParams();
|
GenericParamList *maybeParseGenericParams();
|
||||||
bool parseGenericWhereClause(SourceLoc &WhereLoc,
|
bool parseGenericWhereClause(SourceLoc &WhereLoc,
|
||||||
SmallVectorImpl<Requirement> &Requirements);
|
SmallVectorImpl<RequirementRepr> &Requirements);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace swift
|
} // end namespace swift
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ struct ASTContext::Implementation {
|
|||||||
};
|
};
|
||||||
|
|
||||||
llvm::DenseMap<Module*, ModuleType*> ModuleTypes;
|
llvm::DenseMap<Module*, ModuleType*> ModuleTypes;
|
||||||
|
llvm::FoldingSet<GenericFunctionType> GenericFunctionTypes;
|
||||||
llvm::DenseMap<unsigned, BuiltinIntegerType*> IntegerTypes;
|
llvm::DenseMap<unsigned, BuiltinIntegerType*> IntegerTypes;
|
||||||
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
|
llvm::FoldingSet<ProtocolCompositionType> ProtocolCompositionTypes;
|
||||||
llvm::FoldingSet<BuiltinVectorType> BuiltinVectorTypes;
|
llvm::FoldingSet<BuiltinVectorType> BuiltinVectorTypes;
|
||||||
@@ -1186,6 +1187,96 @@ PolymorphicFunctionType::PolymorphicFunctionType(Type input, Type output,
|
|||||||
assert(!input->hasTypeVariable() && !output->hasTypeVariable());
|
assert(!input->hasTypeVariable() && !output->hasTypeVariable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenericFunctionType::Profile(llvm::FoldingSetNodeID &ID,
|
||||||
|
ArrayRef<GenericTypeParamType *> params,
|
||||||
|
ArrayRef<Requirement> requirements,
|
||||||
|
Type input,
|
||||||
|
Type result,
|
||||||
|
const ExtInfo &info) {
|
||||||
|
ID.AddInteger(params.size());
|
||||||
|
for (auto param : params)
|
||||||
|
ID.AddPointer(param);
|
||||||
|
ID.AddInteger(requirements.size());
|
||||||
|
for (const auto &req : requirements) {
|
||||||
|
ID.AddInteger(static_cast<unsigned>(req.getKind()));
|
||||||
|
ID.AddPointer(req.getFirstType().getPointer());
|
||||||
|
ID.AddPointer(req.getSecondType().getPointer());
|
||||||
|
}
|
||||||
|
ID.AddPointer(input.getPointer());
|
||||||
|
ID.AddPointer(result.getPointer());
|
||||||
|
ID.AddInteger(info.getFuncAttrKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericFunctionType *
|
||||||
|
GenericFunctionType::get(ArrayRef<GenericTypeParamType *> params,
|
||||||
|
ArrayRef<Requirement> requirements,
|
||||||
|
Type input,
|
||||||
|
Type output,
|
||||||
|
const ExtInfo &info,
|
||||||
|
const ASTContext &ctx) {
|
||||||
|
assert(!input->hasTypeVariable() && !output->hasTypeVariable());
|
||||||
|
|
||||||
|
llvm::FoldingSetNodeID id;
|
||||||
|
GenericFunctionType::Profile(id, params, requirements, input, output, info);
|
||||||
|
|
||||||
|
// Do we already have this generic function type?
|
||||||
|
void *insertPos;
|
||||||
|
if (auto result
|
||||||
|
= ctx.Impl.GenericFunctionTypes.FindNodeOrInsertPos(id, insertPos))
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// We have to construct this generic function type. Determine whether
|
||||||
|
// it's canonical.
|
||||||
|
bool isCanonical = input->isCanonical() && output->isCanonical();
|
||||||
|
if (isCanonical) {
|
||||||
|
for (auto param : params) {
|
||||||
|
if (!param->isCanonical()) {
|
||||||
|
isCanonical = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isCanonical ) {
|
||||||
|
for (const auto &req : requirements) {
|
||||||
|
if (!req.getFirstType()->isCanonical() ||
|
||||||
|
!req.getSecondType()->isCanonical()) {
|
||||||
|
isCanonical = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate storage for the object.
|
||||||
|
size_t bytes = sizeof(GenericFunctionType)
|
||||||
|
+ sizeof(GenericTypeParamType *) * params.size()
|
||||||
|
+ sizeof(Requirement) * requirements.size();
|
||||||
|
void *mem = ctx.Allocate(bytes, alignof(GenericFunctionType));
|
||||||
|
|
||||||
|
auto result = new (mem) GenericFunctionType(params, requirements, input,
|
||||||
|
output, info,
|
||||||
|
isCanonical? &ctx : nullptr);
|
||||||
|
ctx.Impl.GenericFunctionTypes.InsertNode(result, insertPos);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenericFunctionType::GenericFunctionType(
|
||||||
|
ArrayRef<GenericTypeParamType *> genericParams,
|
||||||
|
ArrayRef<Requirement> requirements,
|
||||||
|
Type input,
|
||||||
|
Type result,
|
||||||
|
const ExtInfo &info,
|
||||||
|
const ASTContext *ctx)
|
||||||
|
: AnyFunctionType(TypeKind::GenericFunction, ctx, input, result,
|
||||||
|
/*hasTypeVariable=*/false, info),
|
||||||
|
NumGenericParams(genericParams.size()),
|
||||||
|
NumRequirements(requirements.size())
|
||||||
|
{
|
||||||
|
std::copy(genericParams.begin(), genericParams.end(),
|
||||||
|
getGenericParamsBuffer().data());
|
||||||
|
std::copy(requirements.begin(), requirements.end(),
|
||||||
|
getRequirementsBuffer().data());
|
||||||
|
}
|
||||||
|
|
||||||
/// Return a uniqued array type with the specified base type and the
|
/// Return a uniqued array type with the specified base type and the
|
||||||
/// specified size.
|
/// specified size.
|
||||||
ArrayType *ArrayType::get(Type BaseType, uint64_t Size, const ASTContext &C) {
|
ArrayType *ArrayType::get(Type BaseType, uint64_t Size, const ASTContext &C) {
|
||||||
|
|||||||
@@ -1116,6 +1116,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
|
|||||||
case TypeKind::ArraySlice:
|
case TypeKind::ArraySlice:
|
||||||
case TypeKind::Function:
|
case TypeKind::Function:
|
||||||
case TypeKind::PolymorphicFunction:
|
case TypeKind::PolymorphicFunction:
|
||||||
|
case TypeKind::GenericFunction:
|
||||||
OS << '(';
|
OS << '(';
|
||||||
visit(T);
|
visit(T);
|
||||||
OS << ')';
|
OS << ')';
|
||||||
@@ -1317,6 +1318,58 @@ public:
|
|||||||
OS << " -> " << T->getResult();
|
OS << " -> " << T->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void visitGenericFunctionType(GenericFunctionType *T) {
|
||||||
|
AttributePrinter Attrs(OS);
|
||||||
|
Attrs.printCC(T->getAbstractCC());
|
||||||
|
if (T->isThin())
|
||||||
|
Attrs.next() << "thin";
|
||||||
|
if (T->isNoReturn())
|
||||||
|
Attrs.next() << "noreturn";
|
||||||
|
|
||||||
|
Attrs.finish();
|
||||||
|
|
||||||
|
// Print the generic parameters.
|
||||||
|
OS << '<';
|
||||||
|
bool isFirstParam = true;
|
||||||
|
for (auto param : T->getGenericParams()) {
|
||||||
|
if (isFirstParam)
|
||||||
|
isFirstParam = false;
|
||||||
|
else
|
||||||
|
OS << ", ";
|
||||||
|
|
||||||
|
visit(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print the requirements.
|
||||||
|
bool isFirstReq = true;
|
||||||
|
for (const auto &req : T->getRequirements()) {
|
||||||
|
if (isFirstReq) {
|
||||||
|
OS << " where ";
|
||||||
|
isFirstReq = false;
|
||||||
|
} else {
|
||||||
|
OS << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
visit(req.getFirstType());
|
||||||
|
switch (req.getKind()) {
|
||||||
|
case RequirementKind::Conformance:
|
||||||
|
OS << " : ";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RequirementKind::SameType:
|
||||||
|
OS << " == ";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
visit(req.getSecondType());
|
||||||
|
}
|
||||||
|
OS << '>';
|
||||||
|
|
||||||
|
OS << ' ';
|
||||||
|
printWithParensIfNotSimple(T->getInput());
|
||||||
|
|
||||||
|
OS << " -> " << T->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
void visitArrayType(ArrayType *T) {
|
void visitArrayType(ArrayType *T) {
|
||||||
printWithParensIfNotSimple(T->getBaseType());
|
printWithParensIfNotSimple(T->getBaseType());
|
||||||
OS << '[' << T->getSize() << ']';
|
OS << '[' << T->getSize() << ']';
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ bool Decl::isTransparent() const {
|
|||||||
GenericParamList::GenericParamList(SourceLoc LAngleLoc,
|
GenericParamList::GenericParamList(SourceLoc LAngleLoc,
|
||||||
ArrayRef<GenericParam> Params,
|
ArrayRef<GenericParam> Params,
|
||||||
SourceLoc WhereLoc,
|
SourceLoc WhereLoc,
|
||||||
MutableArrayRef<Requirement> Requirements,
|
MutableArrayRef<RequirementRepr> Requirements,
|
||||||
SourceLoc RAngleLoc)
|
SourceLoc RAngleLoc)
|
||||||
: Brackets(LAngleLoc, RAngleLoc), NumParams(Params.size()),
|
: Brackets(LAngleLoc, RAngleLoc), NumParams(Params.size()),
|
||||||
WhereLoc(WhereLoc), Requirements(Requirements),
|
WhereLoc(WhereLoc), Requirements(Requirements),
|
||||||
@@ -129,7 +129,7 @@ GenericParamList *GenericParamList::create(ASTContext &Context,
|
|||||||
+ sizeof(GenericParam) * Params.size();
|
+ sizeof(GenericParam) * Params.size();
|
||||||
void *Mem = Context.Allocate(Size, alignof(GenericParamList));
|
void *Mem = Context.Allocate(Size, alignof(GenericParamList));
|
||||||
return new (Mem) GenericParamList(LAngleLoc, Params, SourceLoc(),
|
return new (Mem) GenericParamList(LAngleLoc, Params, SourceLoc(),
|
||||||
MutableArrayRef<Requirement>(),
|
MutableArrayRef<RequirementRepr>(),
|
||||||
RAngleLoc);
|
RAngleLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ GenericParamList::create(const ASTContext &Context,
|
|||||||
SourceLoc LAngleLoc,
|
SourceLoc LAngleLoc,
|
||||||
ArrayRef<GenericParam> Params,
|
ArrayRef<GenericParam> Params,
|
||||||
SourceLoc WhereLoc,
|
SourceLoc WhereLoc,
|
||||||
MutableArrayRef<Requirement> Requirements,
|
MutableArrayRef<RequirementRepr> Requirements,
|
||||||
SourceLoc RAngleLoc) {
|
SourceLoc RAngleLoc) {
|
||||||
unsigned Size = sizeof(GenericParamList)
|
unsigned Size = sizeof(GenericParamList)
|
||||||
+ sizeof(GenericParam) * Params.size();
|
+ sizeof(GenericParam) * Params.size();
|
||||||
|
|||||||
@@ -655,6 +655,10 @@ void Mangler::mangleType(CanType type, ExplosionKind explosion,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TypeKind::GenericFunction: {
|
||||||
|
llvm_unreachable("cannot mangle generic function types yet");
|
||||||
|
}
|
||||||
|
|
||||||
case TypeKind::GenericTypeParam: {
|
case TypeKind::GenericTypeParam: {
|
||||||
llvm_unreachable("cannot mangle generic type parameters yet");
|
llvm_unreachable("cannot mangle generic type parameters yet");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ bool CanType::hasReferenceSemanticsImpl(CanType type) {
|
|||||||
case TypeKind::BoundGenericClass:
|
case TypeKind::BoundGenericClass:
|
||||||
case TypeKind::Function:
|
case TypeKind::Function:
|
||||||
case TypeKind::PolymorphicFunction:
|
case TypeKind::PolymorphicFunction:
|
||||||
|
case TypeKind::GenericFunction:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case TypeKind::UnboundGeneric:
|
case TypeKind::UnboundGeneric:
|
||||||
@@ -220,6 +221,9 @@ bool TypeBase::isUnspecializedGeneric() {
|
|||||||
funcTy->getResult()->isUnspecializedGeneric();
|
funcTy->getResult()->isUnspecializedGeneric();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TypeKind::GenericFunction:
|
||||||
|
return true;
|
||||||
|
|
||||||
case TypeKind::Class:
|
case TypeKind::Class:
|
||||||
case TypeKind::Struct:
|
case TypeKind::Struct:
|
||||||
case TypeKind::Enum:
|
case TypeKind::Enum:
|
||||||
@@ -623,6 +627,34 @@ CanType TypeBase::getCanonicalType() {
|
|||||||
In->getASTContext());
|
In->getASTContext());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TypeKind::GenericFunction: {
|
||||||
|
// Canonicalize generic parameters.
|
||||||
|
GenericFunctionType *function = cast<GenericFunctionType>(this);
|
||||||
|
SmallVector<GenericTypeParamType *, 4> genericParams;
|
||||||
|
for (auto param : function->getGenericParams()) {
|
||||||
|
auto newParam = param->getCanonicalType()->castTo<GenericTypeParamType>();
|
||||||
|
genericParams.push_back(newParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform requirements.
|
||||||
|
SmallVector<Requirement, 4> requirements;
|
||||||
|
for (const auto &req : function->getRequirements()) {
|
||||||
|
auto firstType = req.getFirstType()->getCanonicalType();
|
||||||
|
auto secondType = req.getSecondType()->getCanonicalType();
|
||||||
|
requirements.push_back(Requirement(req.getKind(), firstType,
|
||||||
|
secondType));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform input type.
|
||||||
|
auto inputTy = function->getInput()->getCanonicalType();
|
||||||
|
auto resultTy = function->getResult()->getCanonicalType();
|
||||||
|
|
||||||
|
Result = GenericFunctionType::get(genericParams, requirements, inputTy,
|
||||||
|
resultTy, function->getExtInfo(),
|
||||||
|
inputTy->getASTContext());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case TypeKind::Function: {
|
case TypeKind::Function: {
|
||||||
FunctionType *FT = cast<FunctionType>(this);
|
FunctionType *FT = cast<FunctionType>(this);
|
||||||
Type In = FT->getInput()->getCanonicalType();
|
Type In = FT->getInput()->getCanonicalType();
|
||||||
@@ -693,6 +725,7 @@ TypeBase *TypeBase::getDesugaredType() {
|
|||||||
case TypeKind::Tuple:
|
case TypeKind::Tuple:
|
||||||
case TypeKind::Function:
|
case TypeKind::Function:
|
||||||
case TypeKind::PolymorphicFunction:
|
case TypeKind::PolymorphicFunction:
|
||||||
|
case TypeKind::GenericFunction:
|
||||||
case TypeKind::Array:
|
case TypeKind::Array:
|
||||||
case TypeKind::LValue:
|
case TypeKind::LValue:
|
||||||
case TypeKind::ProtocolComposition:
|
case TypeKind::ProtocolComposition:
|
||||||
@@ -849,7 +882,8 @@ bool TypeBase::isSpelledLike(Type other) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TypeKind::PolymorphicFunction: {
|
case TypeKind::PolymorphicFunction:
|
||||||
|
case TypeKind::GenericFunction: {
|
||||||
// Polymorphic function types should never be explicitly spelled.
|
// Polymorphic function types should never be explicitly spelled.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -429,6 +429,12 @@ namespace {
|
|||||||
return llvm::UndefValue::get(IGF.IGM.TypeMetadataPtrTy);
|
return llvm::UndefValue::get(IGF.IGM.TypeMetadataPtrTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::Value *visitGenericFunctionType(CanGenericFunctionType type) {
|
||||||
|
IGF.unimplemented(SourceLoc(),
|
||||||
|
"metadata ref for generic function type");
|
||||||
|
return llvm::UndefValue::get(IGF.IGM.TypeMetadataPtrTy);
|
||||||
|
}
|
||||||
|
|
||||||
llvm::Value *visitFunctionType(CanFunctionType type) {
|
llvm::Value *visitFunctionType(CanFunctionType type) {
|
||||||
if (auto metatype = tryGetLocal(type))
|
if (auto metatype = tryGetLocal(type))
|
||||||
return metatype;
|
return metatype;
|
||||||
|
|||||||
@@ -648,6 +648,7 @@ TypeCacheEntry TypeConverter::convertType(CanType ty) {
|
|||||||
return convertProtocolType(cast<ProtocolType>(ty));
|
return convertProtocolType(cast<ProtocolType>(ty));
|
||||||
case TypeKind::ProtocolComposition:
|
case TypeKind::ProtocolComposition:
|
||||||
return convertProtocolCompositionType(cast<ProtocolCompositionType>(ty));
|
return convertProtocolCompositionType(cast<ProtocolCompositionType>(ty));
|
||||||
|
case TypeKind::GenericFunction:
|
||||||
case TypeKind::GenericTypeParam:
|
case TypeKind::GenericTypeParam:
|
||||||
case TypeKind::DependentMember:
|
case TypeKind::DependentMember:
|
||||||
llvm_unreachable("can't convert dependent type");
|
llvm_unreachable("can't convert dependent type");
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ public:
|
|||||||
->visitArchetypeType(cast<ArchetypeType>(origTy),
|
->visitArchetypeType(cast<ArchetypeType>(origTy),
|
||||||
substTy);
|
substTy);
|
||||||
|
|
||||||
|
case TypeKind::GenericFunction:
|
||||||
case TypeKind::GenericTypeParam:
|
case TypeKind::GenericTypeParam:
|
||||||
case TypeKind::DependentMember:
|
case TypeKind::DependentMember:
|
||||||
// FIXME: This should duplicate, then subsume, the archetype path?
|
// FIXME: This should duplicate, then subsume, the archetype path?
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ GenericParamList *Parser::parseGenericParameters(SourceLoc LAngleLoc) {
|
|||||||
|
|
||||||
// Parse the optional where-clause.
|
// Parse the optional where-clause.
|
||||||
SourceLoc WhereLoc;
|
SourceLoc WhereLoc;
|
||||||
SmallVector<Requirement, 4> Requirements;
|
SmallVector<RequirementRepr, 4> Requirements;
|
||||||
if (Tok.is(tok::kw_where) &&
|
if (Tok.is(tok::kw_where) &&
|
||||||
parseGenericWhereClause(WhereLoc, Requirements)) {
|
parseGenericWhereClause(WhereLoc, Requirements)) {
|
||||||
Invalid = true;
|
Invalid = true;
|
||||||
@@ -146,8 +146,8 @@ GenericParamList *Parser::maybeParseGenericParams() {
|
|||||||
/// same-type-requirement:
|
/// same-type-requirement:
|
||||||
/// type-identifier '==' type-identifier
|
/// type-identifier '==' type-identifier
|
||||||
bool Parser::parseGenericWhereClause(SourceLoc &WhereLoc,
|
bool Parser::parseGenericWhereClause(SourceLoc &WhereLoc,
|
||||||
SmallVectorImpl<Requirement> &Requirements) {
|
SmallVectorImpl<RequirementRepr> &Requirements) {
|
||||||
// Parse the 'requires'.
|
// Parse the 'where'.
|
||||||
WhereLoc = consumeToken(tok::kw_where);
|
WhereLoc = consumeToken(tok::kw_where);
|
||||||
bool Invalid = false;
|
bool Invalid = false;
|
||||||
do {
|
do {
|
||||||
@@ -176,7 +176,7 @@ bool Parser::parseGenericWhereClause(SourceLoc &WhereLoc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the requirement.
|
// Add the requirement.
|
||||||
Requirements.push_back(Requirement::getConformance(FirstType.get(),
|
Requirements.push_back(RequirementRepr::getConformance(FirstType.get(),
|
||||||
ColonLoc,
|
ColonLoc,
|
||||||
Protocol.get()));
|
Protocol.get()));
|
||||||
} else if ((Tok.isAnyOperator() && Tok.getText() == "==") ||
|
} else if ((Tok.isAnyOperator() && Tok.getText() == "==") ||
|
||||||
@@ -196,7 +196,7 @@ bool Parser::parseGenericWhereClause(SourceLoc &WhereLoc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add the requirement
|
// Add the requirement
|
||||||
Requirements.push_back(Requirement::getSameType(FirstType.get(),
|
Requirements.push_back(RequirementRepr::getSameType(FirstType.get(),
|
||||||
EqualLoc,
|
EqualLoc,
|
||||||
SecondType.get()));
|
SecondType.get()));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ CanAnyFunctionType TypeConverter::getUncurriedFunctionType(CanAnyFunctionType t,
|
|||||||
// The uncurried generic parameter list components.
|
// The uncurried generic parameter list components.
|
||||||
bool isPolymorphic = false;
|
bool isPolymorphic = false;
|
||||||
SmallVector<GenericParam, 4> genericParams;
|
SmallVector<GenericParam, 4> genericParams;
|
||||||
SmallVector<Requirement, 4> requirements;
|
SmallVector<RequirementRepr, 4> requirements;
|
||||||
SmallVector<ArchetypeType *, 4> allArchetypes;
|
SmallVector<ArchetypeType *, 4> allArchetypes;
|
||||||
GenericParamList *outerParameters = nullptr;
|
GenericParamList *outerParameters = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,6 @@ auto ArchetypeBuilder::PotentialArchetype::getArchetype(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Find the protocol that has an associated type with this name.
|
// Find the protocol that has an associated type with this name.
|
||||||
llvm::SmallSetVector<AssociatedTypeDecl *, 2> assocTypes;
|
|
||||||
for (auto proto : ParentArchetype->getConformsTo()) {
|
for (auto proto : ParentArchetype->getConformsTo()) {
|
||||||
SmallVector<ValueDecl *, 2> decls;
|
SmallVector<ValueDecl *, 2> decls;
|
||||||
if (tu.lookupQualified(proto->getDeclaredType(), Name,
|
if (tu.lookupQualified(proto->getDeclaredType(), Name,
|
||||||
@@ -156,6 +155,23 @@ auto ArchetypeBuilder::PotentialArchetype::getArchetype(
|
|||||||
return Archetype;
|
return Archetype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AssociatedTypeDecl *
|
||||||
|
ArchetypeBuilder::PotentialArchetype::getAssociatedType(TranslationUnit &tu,
|
||||||
|
Identifier name) {
|
||||||
|
for (auto proto : getRepresentative()->getConformsTo()) {
|
||||||
|
SmallVector<ValueDecl *, 2> decls;
|
||||||
|
if (tu.lookupQualified(proto->getDeclaredType(), name,
|
||||||
|
NL_VisitSupertypes, nullptr, decls)) {
|
||||||
|
for (auto decl : decls) {
|
||||||
|
if (auto assocType = dyn_cast<AssociatedTypeDecl>(decl))
|
||||||
|
return assocType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void ArchetypeBuilder::PotentialArchetype::dump(llvm::raw_ostream &Out,
|
void ArchetypeBuilder::PotentialArchetype::dump(llvm::raw_ostream &Out,
|
||||||
unsigned Indent) {
|
unsigned Indent) {
|
||||||
// Print name.
|
// Print name.
|
||||||
@@ -397,7 +413,7 @@ bool ArchetypeBuilder::addSameTypeRequirement(PotentialArchetype *T1,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArchetypeBuilder::addRequirement(const Requirement &Req) {
|
bool ArchetypeBuilder::addRequirement(const RequirementRepr &Req) {
|
||||||
switch (Req.getKind()) {
|
switch (Req.getKind()) {
|
||||||
case RequirementKind::Conformance: {
|
case RequirementKind::Conformance: {
|
||||||
PotentialArchetype *PA = resolveType(Req.getSubject());
|
PotentialArchetype *PA = resolveType(Req.getSubject());
|
||||||
|
|||||||
@@ -1715,6 +1715,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case TypeKind::PolymorphicFunction:
|
case TypeKind::PolymorphicFunction:
|
||||||
|
case TypeKind::GenericFunction:
|
||||||
llvm_unreachable("Polymorphic function type should have been opened");
|
llvm_unreachable("Polymorphic function type should have been opened");
|
||||||
|
|
||||||
case TypeKind::Array: {
|
case TypeKind::Array: {
|
||||||
@@ -2239,6 +2240,7 @@ ConstraintSystem::simplifyConstructionConstraint(Type valueType, Type argType,
|
|||||||
case TypeKind::Error:
|
case TypeKind::Error:
|
||||||
return SolutionKind::Error;
|
return SolutionKind::Error;
|
||||||
|
|
||||||
|
case TypeKind::GenericFunction:
|
||||||
case TypeKind::GenericTypeParam:
|
case TypeKind::GenericTypeParam:
|
||||||
case TypeKind::DependentMember:
|
case TypeKind::DependentMember:
|
||||||
llvm_unreachable("unmapped dependent type");
|
llvm_unreachable("unmapped dependent type");
|
||||||
|
|||||||
@@ -199,7 +199,13 @@ static void validateAttributes(TypeChecker &TC, Decl *VD);
|
|||||||
/// This routine validates all of the types in the parsed inheritance clause,
|
/// This routine validates all of the types in the parsed inheritance clause,
|
||||||
/// recording the superclass (if any and if allowed) as well as the protocols
|
/// recording the superclass (if any and if allowed) as well as the protocols
|
||||||
/// to which this type declaration conforms.
|
/// to which this type declaration conforms.
|
||||||
static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
void TypeChecker::checkInheritanceClause(Decl *decl,
|
||||||
|
GenericTypeResolver *resolver) {
|
||||||
|
// Establish a default generic type resolver.
|
||||||
|
PartialGenericTypeToArchetypeResolver defaultResolver(*this);
|
||||||
|
if (!resolver)
|
||||||
|
resolver = &defaultResolver;
|
||||||
|
|
||||||
MutableArrayRef<TypeLoc> inheritedClause;
|
MutableArrayRef<TypeLoc> inheritedClause;
|
||||||
|
|
||||||
// If we already checked the inheritance clause, don't do so again.
|
// If we already checked the inheritance clause, don't do so again.
|
||||||
@@ -225,13 +231,13 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
SourceRange superclassRange;
|
SourceRange superclassRange;
|
||||||
llvm::SmallSetVector<ProtocolDecl *, 4> allProtocols;
|
llvm::SmallSetVector<ProtocolDecl *, 4> allProtocols;
|
||||||
llvm::SmallDenseMap<CanType, SourceRange> inheritedTypes;
|
llvm::SmallDenseMap<CanType, SourceRange> inheritedTypes;
|
||||||
addImplicitConformances(tc, decl, allProtocols);
|
addImplicitConformances(*this, decl, allProtocols);
|
||||||
for (unsigned i = 0, n = inheritedClause.size(); i != n; ++i) {
|
for (unsigned i = 0, n = inheritedClause.size(); i != n; ++i) {
|
||||||
auto &inherited = inheritedClause[i];
|
auto &inherited = inheritedClause[i];
|
||||||
|
|
||||||
// Validate the type.
|
// Validate the type.
|
||||||
if (tc.validateType(inherited)) {
|
if (validateType(inherited, /*allowUnboundGenerics=*/false, resolver)) {
|
||||||
inherited.setInvalidType(tc.Context);
|
inherited.setInvalidType(Context);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,14 +248,14 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
auto knownType = inheritedTypes.find(inheritedCanTy);
|
auto knownType = inheritedTypes.find(inheritedCanTy);
|
||||||
if (knownType != inheritedTypes.end()) {
|
if (knownType != inheritedTypes.end()) {
|
||||||
SourceLoc afterPriorLoc
|
SourceLoc afterPriorLoc
|
||||||
= Lexer::getLocForEndOfToken(tc.Context.SourceMgr,
|
= Lexer::getLocForEndOfToken(Context.SourceMgr,
|
||||||
inheritedClause[i-1].getSourceRange().End);
|
inheritedClause[i-1].getSourceRange().End);
|
||||||
SourceLoc afterMyEndLoc
|
SourceLoc afterMyEndLoc
|
||||||
= Lexer::getLocForEndOfToken(tc.Context.SourceMgr,
|
= Lexer::getLocForEndOfToken(Context.SourceMgr,
|
||||||
inherited.getSourceRange().End);
|
inherited.getSourceRange().End);
|
||||||
|
|
||||||
tc.diagnose(inherited.getSourceRange().Start,
|
diagnose(inherited.getSourceRange().Start,
|
||||||
diag::duplicate_inheritance, inheritedTy)
|
diag::duplicate_inheritance, inheritedTy)
|
||||||
.fixItRemoveChars(afterPriorLoc, afterMyEndLoc)
|
.fixItRemoveChars(afterPriorLoc, afterMyEndLoc)
|
||||||
.highlight(knownType->second);
|
.highlight(knownType->second);
|
||||||
continue;
|
continue;
|
||||||
@@ -263,8 +269,8 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
if (auto protoTy = inheritedTy->getAs<ProtocolType>()) {
|
if (auto protoTy = inheritedTy->getAs<ProtocolType>()) {
|
||||||
if (protoTy->getDecl()->isSpecificProtocol(
|
if (protoTy->getDecl()->isSpecificProtocol(
|
||||||
KnownProtocolKind::DynamicLookup)) {
|
KnownProtocolKind::DynamicLookup)) {
|
||||||
tc.diagnose(inheritedClause[i].getSourceRange().Start,
|
diagnose(inheritedClause[i].getSourceRange().Start,
|
||||||
diag::dynamic_lookup_conformance);
|
diag::dynamic_lookup_conformance);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,8 +285,8 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
if (isa<EnumDecl>(decl)) {
|
if (isa<EnumDecl>(decl)) {
|
||||||
// Check if we already had a raw type.
|
// Check if we already had a raw type.
|
||||||
if (superclassTy) {
|
if (superclassTy) {
|
||||||
tc.diagnose(inherited.getSourceRange().Start,
|
diagnose(inherited.getSourceRange().Start,
|
||||||
diag::multiple_enum_raw_types, superclassTy, inheritedTy)
|
diag::multiple_enum_raw_types, superclassTy, inheritedTy)
|
||||||
.highlight(superclassRange);
|
.highlight(superclassRange);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -289,14 +295,14 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
SourceLoc afterPriorLoc
|
SourceLoc afterPriorLoc
|
||||||
= Lexer::getLocForEndOfToken(
|
= Lexer::getLocForEndOfToken(
|
||||||
tc.Context.SourceMgr,
|
Context.SourceMgr,
|
||||||
inheritedClause[i-1].getSourceRange().End);
|
inheritedClause[i-1].getSourceRange().End);
|
||||||
SourceLoc afterMyEndLoc
|
SourceLoc afterMyEndLoc
|
||||||
= Lexer::getLocForEndOfToken(tc.Context.SourceMgr,
|
= Lexer::getLocForEndOfToken(Context.SourceMgr,
|
||||||
inherited.getSourceRange().End);
|
inherited.getSourceRange().End);
|
||||||
|
|
||||||
tc.diagnose(inherited.getSourceRange().Start,
|
diagnose(inherited.getSourceRange().Start,
|
||||||
diag::raw_type_not_first, inheritedTy)
|
diag::raw_type_not_first, inheritedTy)
|
||||||
.fixItRemoveChars(afterPriorLoc, afterMyEndLoc)
|
.fixItRemoveChars(afterPriorLoc, afterMyEndLoc)
|
||||||
.fixItInsert(inheritedClause[0].getSourceRange().Start,
|
.fixItInsert(inheritedClause[0].getSourceRange().Start,
|
||||||
inheritedTy.getString() + ", ");
|
inheritedTy.getString() + ", ");
|
||||||
@@ -318,8 +324,8 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
|
|
||||||
// Complain about multiple inheritance.
|
// Complain about multiple inheritance.
|
||||||
// Don't emit a Fix-It here. The user has to think harder about this.
|
// Don't emit a Fix-It here. The user has to think harder about this.
|
||||||
tc.diagnose(inherited.getSourceRange().Start,
|
diagnose(inherited.getSourceRange().Start,
|
||||||
diag::multiple_inheritance, superclassTy, inheritedTy)
|
diag::multiple_inheritance, superclassTy, inheritedTy)
|
||||||
.highlight(superclassRange);
|
.highlight(superclassRange);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -330,11 +336,11 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
// FIXME: Allow type aliases to 'inherit' from classes, as an additional
|
// FIXME: Allow type aliases to 'inherit' from classes, as an additional
|
||||||
// kind of requirement?
|
// kind of requirement?
|
||||||
if (!canInheritClass(decl)) {
|
if (!canInheritClass(decl)) {
|
||||||
tc.diagnose(decl->getLoc(),
|
diagnose(decl->getLoc(),
|
||||||
isa<ExtensionDecl>(decl)
|
isa<ExtensionDecl>(decl)
|
||||||
? diag::extension_class_inheritance
|
? diag::extension_class_inheritance
|
||||||
: diag::non_class_inheritance,
|
: diag::non_class_inheritance,
|
||||||
getDeclaredType(decl), inheritedTy)
|
getDeclaredType(decl), inheritedTy)
|
||||||
.highlight(inherited.getSourceRange());
|
.highlight(inherited.getSourceRange());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -343,14 +349,14 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
SourceLoc afterPriorLoc
|
SourceLoc afterPriorLoc
|
||||||
= Lexer::getLocForEndOfToken(
|
= Lexer::getLocForEndOfToken(
|
||||||
tc.Context.SourceMgr,
|
Context.SourceMgr,
|
||||||
inheritedClause[i-1].getSourceRange().End);
|
inheritedClause[i-1].getSourceRange().End);
|
||||||
SourceLoc afterMyEndLoc
|
SourceLoc afterMyEndLoc
|
||||||
= Lexer::getLocForEndOfToken(tc.Context.SourceMgr,
|
= Lexer::getLocForEndOfToken(Context.SourceMgr,
|
||||||
inherited.getSourceRange().End);
|
inherited.getSourceRange().End);
|
||||||
|
|
||||||
tc.diagnose(inherited.getSourceRange().Start,
|
diagnose(inherited.getSourceRange().Start,
|
||||||
diag::superclass_not_first, inheritedTy)
|
diag::superclass_not_first, inheritedTy)
|
||||||
.fixItRemoveChars(afterPriorLoc, afterMyEndLoc)
|
.fixItRemoveChars(afterPriorLoc, afterMyEndLoc)
|
||||||
.fixItInsert(inheritedClause[0].getSourceRange().Start,
|
.fixItInsert(inheritedClause[0].getSourceRange().Start,
|
||||||
inheritedTy.getString() + ", ");
|
inheritedTy.getString() + ", ");
|
||||||
@@ -369,11 +375,11 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// We can't inherit from a non-class, non-protocol type.
|
// We can't inherit from a non-class, non-protocol type.
|
||||||
tc.diagnose(decl->getLoc(),
|
diagnose(decl->getLoc(),
|
||||||
canInheritClass(decl)
|
canInheritClass(decl)
|
||||||
? diag::inheritance_from_non_protocol_or_class
|
? diag::inheritance_from_non_protocol_or_class
|
||||||
: diag::inheritance_from_non_protocol,
|
: diag::inheritance_from_non_protocol,
|
||||||
inheritedTy);
|
inheritedTy);
|
||||||
// FIXME: Note pointing to the declaration 'inheritedTy' references?
|
// FIXME: Note pointing to the declaration 'inheritedTy' references?
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,7 +388,7 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
if (allProtocols.empty() && !superclassTy)
|
if (allProtocols.empty() && !superclassTy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto allProtocolsCopy = tc.Context.AllocateCopy(allProtocols);
|
auto allProtocolsCopy = Context.AllocateCopy(allProtocols);
|
||||||
if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
|
if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
|
||||||
assert(!superclassTy && "Extensions can't add superclasses");
|
assert(!superclassTy && "Extensions can't add superclasses");
|
||||||
ext->setProtocols(allProtocolsCopy);
|
ext->setProtocols(allProtocolsCopy);
|
||||||
@@ -407,7 +413,7 @@ static void checkInheritanceClause(TypeChecker &tc, Decl *decl) {
|
|||||||
unsigned conformancesSize
|
unsigned conformancesSize
|
||||||
= sizeof(ProtocolConformance *) * allProtocols.size();
|
= sizeof(ProtocolConformance *) * allProtocols.size();
|
||||||
ProtocolConformance **conformances
|
ProtocolConformance **conformances
|
||||||
= (ProtocolConformance **)tc.Context.Allocate(
|
= (ProtocolConformance **)Context.Allocate(
|
||||||
conformancesSize,
|
conformancesSize,
|
||||||
alignof(ProtocolConformance *));
|
alignof(ProtocolConformance *));
|
||||||
memset(conformances, 0, conformancesSize);
|
memset(conformances, 0, conformancesSize);
|
||||||
@@ -427,7 +433,7 @@ static ArrayRef<ProtocolDecl *> getInheritedForCycleCheck(TypeChecker &tc,
|
|||||||
static ArrayRef<ClassDecl *> getInheritedForCycleCheck(TypeChecker &tc,
|
static ArrayRef<ClassDecl *> getInheritedForCycleCheck(TypeChecker &tc,
|
||||||
ClassDecl *classDecl,
|
ClassDecl *classDecl,
|
||||||
ClassDecl **scratch) {
|
ClassDecl **scratch) {
|
||||||
checkInheritanceClause(tc, classDecl);
|
tc.checkInheritanceClause(classDecl);
|
||||||
|
|
||||||
if (classDecl->hasSuperclass()) {
|
if (classDecl->hasSuperclass()) {
|
||||||
*scratch = classDecl->getSuperclass()->getClassOrBoundGenericClass();
|
*scratch = classDecl->getSuperclass()->getClassOrBoundGenericClass();
|
||||||
@@ -440,7 +446,7 @@ static ArrayRef<ClassDecl *> getInheritedForCycleCheck(TypeChecker &tc,
|
|||||||
static ArrayRef<EnumDecl *> getInheritedForCycleCheck(TypeChecker &tc,
|
static ArrayRef<EnumDecl *> getInheritedForCycleCheck(TypeChecker &tc,
|
||||||
EnumDecl *enumDecl,
|
EnumDecl *enumDecl,
|
||||||
EnumDecl **scratch) {
|
EnumDecl **scratch) {
|
||||||
checkInheritanceClause(tc, enumDecl);
|
tc.checkInheritanceClause(enumDecl);
|
||||||
|
|
||||||
if (enumDecl->hasRawType()) {
|
if (enumDecl->hasRawType()) {
|
||||||
*scratch = enumDecl->getRawType()->getEnumOrBoundGenericEnum();
|
*scratch = enumDecl->getRawType()->getEnumOrBoundGenericEnum();
|
||||||
@@ -585,7 +591,8 @@ static CanType getExtendedType(ExtensionDecl *ED) {
|
|||||||
return ExtendedTy;
|
return ExtendedTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a fresh archetype building.
|
/// Create a fresh archetype builder.
|
||||||
|
/// FIXME: Duplicated with TypeCheckGeneric.cpp; this one should go away.
|
||||||
static ArchetypeBuilder createArchetypeBuilder(TypeChecker &TC) {
|
static ArchetypeBuilder createArchetypeBuilder(TypeChecker &TC) {
|
||||||
return ArchetypeBuilder(
|
return ArchetypeBuilder(
|
||||||
TC.TU, TC.Diags,
|
TC.TU, TC.Diags,
|
||||||
@@ -593,13 +600,11 @@ static ArchetypeBuilder createArchetypeBuilder(TypeChecker &TC) {
|
|||||||
return TC.getDirectConformsTo(protocol);
|
return TC.getDirectConformsTo(protocol);
|
||||||
},
|
},
|
||||||
[&](AbstractTypeParamDecl *assocType) -> ArrayRef<ProtocolDecl *> {
|
[&](AbstractTypeParamDecl *assocType) -> ArrayRef<ProtocolDecl *> {
|
||||||
checkInheritanceClause(TC, assocType);
|
TC.checkInheritanceClause(assocType);
|
||||||
return assocType->getProtocols();
|
return assocType->getProtocols();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Revert the given dependently-typed TypeLoc to a state where generic
|
|
||||||
/// parameters have not yet been resolved.
|
|
||||||
static void revertDependentTypeLoc(TypeLoc &tl, DeclContext *dc) {
|
static void revertDependentTypeLoc(TypeLoc &tl, DeclContext *dc) {
|
||||||
// Make sure we validate the type again.
|
// Make sure we validate the type again.
|
||||||
tl.setType(Type(), /*validated=*/false);
|
tl.setType(Type(), /*validated=*/false);
|
||||||
@@ -663,9 +668,7 @@ static void revertDependentTypeLoc(TypeLoc &tl, DeclContext *dc) {
|
|||||||
tl.getTypeRepr()->walk(RevertWalker(dc));
|
tl.getTypeRepr()->walk(RevertWalker(dc));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Revert the dependently-typed TypeLocs within the given pattern to a
|
static void revertDependentPattern(Pattern *pattern, DeclContext *dc) {
|
||||||
/// state where generic parameters have not yet been resolved.
|
|
||||||
void revertDependentPattern(Pattern *pattern, DeclContext *dc) {
|
|
||||||
// Clear out the pattern's type.
|
// Clear out the pattern's type.
|
||||||
if (pattern->hasType())
|
if (pattern->hasType())
|
||||||
pattern->overwriteType(Type());
|
pattern->overwriteType(Type());
|
||||||
@@ -718,9 +721,9 @@ void revertDependentPattern(Pattern *pattern, DeclContext *dc) {
|
|||||||
/// Check the given generic parameter list, introduce the generic parameters
|
/// Check the given generic parameter list, introduce the generic parameters
|
||||||
/// and requirements into the archetype builder, but don't assign archetypes
|
/// and requirements into the archetype builder, but don't assign archetypes
|
||||||
/// yet.
|
/// yet.
|
||||||
void checkGenericParamList(ArchetypeBuilder &builder,
|
static void checkGenericParamList(ArchetypeBuilder &builder,
|
||||||
GenericParamList *genericParams,
|
GenericParamList *genericParams,
|
||||||
TypeChecker &TC) {
|
TypeChecker &TC) {
|
||||||
assert(genericParams && "Missing generic parameters");
|
assert(genericParams && "Missing generic parameters");
|
||||||
unsigned Depth = genericParams->getDepth();
|
unsigned Depth = genericParams->getDepth();
|
||||||
|
|
||||||
@@ -733,7 +736,7 @@ void checkGenericParamList(ArchetypeBuilder &builder,
|
|||||||
TypeParam->setDepth(Depth);
|
TypeParam->setDepth(Depth);
|
||||||
|
|
||||||
// Check the constraints on the type parameter.
|
// Check the constraints on the type parameter.
|
||||||
checkInheritanceClause(TC, TypeParam);
|
TC.checkInheritanceClause(TypeParam);
|
||||||
|
|
||||||
// Add the generic parameter to the builder.
|
// Add the generic parameter to the builder.
|
||||||
builder.addGenericParameter(TypeParam, Index++);
|
builder.addGenericParameter(TypeParam, Index++);
|
||||||
@@ -805,12 +808,46 @@ void checkGenericParamList(ArchetypeBuilder &builder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Revert the dependent types within the given generic parameter list.
|
||||||
|
static void revertGenericParamList(GenericParamList *genericParams,
|
||||||
|
DeclContext *dc) {
|
||||||
|
// FIXME: Revert the inherited clause of the generic parameter list.
|
||||||
|
#if 0
|
||||||
|
for (auto param : *genericParams) {
|
||||||
|
auto typeParam = param.getAsTypeParam();
|
||||||
|
|
||||||
|
typeParam->setCheckedInheritanceClause(false);
|
||||||
|
for (auto &inherited : typeParam->getInherited())
|
||||||
|
revertDependentTypeLoc(inherited, dc);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Revert the requirements of the generic parameter list.
|
||||||
|
for (auto &req : genericParams->getRequirements()) {
|
||||||
|
if (req.isInvalid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (req.getKind()) {
|
||||||
|
case RequirementKind::Conformance: {
|
||||||
|
revertDependentTypeLoc(req.getSubjectLoc(), dc);
|
||||||
|
revertDependentTypeLoc(req.getConstraintLoc(), dc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RequirementKind::SameType:
|
||||||
|
revertDependentTypeLoc(req.getFirstTypeLoc(), dc);
|
||||||
|
revertDependentTypeLoc(req.getSecondTypeLoc(), dc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Finalize the given generic parameter list, assigning archetypes to
|
/// Finalize the given generic parameter list, assigning archetypes to
|
||||||
/// the generic parameters.
|
/// the generic parameters.
|
||||||
void finalizeGenericParamList(ArchetypeBuilder &builder,
|
static void finalizeGenericParamList(ArchetypeBuilder &builder,
|
||||||
GenericParamList *genericParams,
|
GenericParamList *genericParams,
|
||||||
DeclContext *dc,
|
DeclContext *dc,
|
||||||
TypeChecker &TC) {
|
TypeChecker &TC) {
|
||||||
// Wire up the archetypes.
|
// Wire up the archetypes.
|
||||||
builder.assignArchetypes();
|
builder.assignArchetypes();
|
||||||
for (auto GP : *genericParams) {
|
for (auto GP : *genericParams) {
|
||||||
@@ -861,6 +898,34 @@ void finalizeGenericParamList(ArchetypeBuilder &builder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TypeChecker::revertGenericFuncSignature(FuncDecl *func) {
|
||||||
|
// Revert the result type.
|
||||||
|
if (!func->getBodyResultTypeLoc().isNull()) {
|
||||||
|
revertDependentTypeLoc(func->getBodyResultTypeLoc(), func);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revert the argument patterns.
|
||||||
|
ArrayRef<Pattern *> argPatterns = func->getArgParamPatterns();
|
||||||
|
if (func->getDeclContext()->isTypeContext())
|
||||||
|
argPatterns = argPatterns.slice(1);
|
||||||
|
for (auto argPattern : argPatterns) {
|
||||||
|
revertDependentPattern(argPattern, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revert the body patterns.
|
||||||
|
ArrayRef<Pattern *> bodyPatterns = func->getBodyParamPatterns();
|
||||||
|
if (func->getDeclContext()->isTypeContext())
|
||||||
|
bodyPatterns = bodyPatterns.slice(1);
|
||||||
|
for (auto bodyPattern : bodyPatterns) {
|
||||||
|
revertDependentPattern(bodyPattern, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revert the generic parameter list.
|
||||||
|
revertGenericParamList(func->getGenericParams(), func);
|
||||||
|
|
||||||
|
// Clear out the types.
|
||||||
|
func->revertType();
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -1077,7 +1142,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isa<ProtocolDecl>(TAD->getDeclContext()))
|
if (!isa<ProtocolDecl>(TAD->getDeclContext()))
|
||||||
checkInheritanceClause(TC, TAD);
|
TC.checkInheritanceClause(TAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsFirstPass)
|
if (!IsFirstPass)
|
||||||
@@ -1551,69 +1616,33 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<ArchetypeBuilder> builder;
|
bool isInvalid = false;
|
||||||
|
|
||||||
|
// If we have generic parameters, check the generic signature now.
|
||||||
if (auto gp = FD->getGenericParams()) {
|
if (auto gp = FD->getGenericParams()) {
|
||||||
gp->setOuterParameters(outerGenericParams);
|
gp->setOuterParameters(outerGenericParams);
|
||||||
builder.emplace(createArchetypeBuilder(TC));
|
|
||||||
checkGenericParamList(*builder, gp, TC);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have generic parameters, create archetypes now.
|
if (TC.validateGenericFuncSignature(FD))
|
||||||
bool isInvalid = false;
|
|
||||||
if (builder) {
|
|
||||||
// Type check the function declaration.
|
|
||||||
PartialGenericTypeToArchetypeResolver resolver(TC);
|
|
||||||
semaFuncDecl(FD, /*consumeAttributes=*/false, &resolver);
|
|
||||||
|
|
||||||
// Infer requirements from the parameters of the function.
|
|
||||||
for (auto pattern : FD->getArgParamPatterns()) {
|
|
||||||
builder->inferRequirements(pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Infer requirements from the result type.
|
|
||||||
if (auto resultType = FD->getBodyResultTypeLoc().getTypeRepr())
|
|
||||||
builder->inferRequirements(resultType);
|
|
||||||
|
|
||||||
// Revert all of the types within the signature of the
|
|
||||||
auto revertSignature = [&]() {
|
|
||||||
// Revert the result type.
|
|
||||||
if (!FD->getBodyResultTypeLoc().isNull()) {
|
|
||||||
revertDependentTypeLoc(FD->getBodyResultTypeLoc(), FD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Revert the argument patterns.
|
|
||||||
ArrayRef<Pattern *> argPatterns = FD->getArgParamPatterns();
|
|
||||||
if (FD->getDeclContext()->isTypeContext())
|
|
||||||
argPatterns = argPatterns.slice(1);
|
|
||||||
for (auto argPattern : argPatterns) {
|
|
||||||
revertDependentPattern(argPattern, FD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Revert the body patterns.
|
|
||||||
ArrayRef<Pattern *> bodyPatterns = FD->getBodyParamPatterns();
|
|
||||||
if (FD->getDeclContext()->isTypeContext())
|
|
||||||
bodyPatterns = bodyPatterns.slice(1);
|
|
||||||
for (auto bodyPattern : bodyPatterns) {
|
|
||||||
revertDependentPattern(bodyPattern, FD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear out the types.
|
|
||||||
FD->revertType();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Go through and revert all of the dependent types we computed.
|
|
||||||
revertSignature();
|
|
||||||
|
|
||||||
// Completely resolve the generic signature.
|
|
||||||
CompleteGenericTypeResolver completeResolver(TC, *builder);
|
|
||||||
semaFuncDecl(FD, /*consumeAttributes=*/false, &completeResolver);
|
|
||||||
|
|
||||||
if (FD->getType()->is<ErrorType>()) {
|
|
||||||
isInvalid = true;
|
isInvalid = true;
|
||||||
} else {
|
else {
|
||||||
// Assign archetypes... after reverting the signature once again.
|
// Create a fresh archetype builder.
|
||||||
revertSignature();
|
ArchetypeBuilder builder = createArchetypeBuilder(TC);
|
||||||
finalizeGenericParamList(*builder, FD->getGenericParams(), FD, TC);
|
checkGenericParamList(builder, gp, TC);
|
||||||
|
|
||||||
|
// Infer requirements from parameter patterns.
|
||||||
|
for (auto pattern : FD->getArgParamPatterns()) {
|
||||||
|
builder.inferRequirements(pattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infer requirements from the result type.
|
||||||
|
if (!FD->getBodyResultTypeLoc().isNull()) {
|
||||||
|
builder.inferRequirements(FD->getBodyResultTypeLoc().getTypeRepr());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revert all of the types within the signature of the function.
|
||||||
|
TC.revertGenericFuncSignature(FD);
|
||||||
|
|
||||||
|
finalizeGenericParamList(builder, FD->getGenericParams(), FD, TC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1745,7 +1774,7 @@ public:
|
|||||||
ED->setInvalid();
|
ED->setInvalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkInheritanceClause(TC, ED);
|
TC.checkInheritanceClause(ED);
|
||||||
if (auto nominal = ExtendedTy->getAnyNominal())
|
if (auto nominal = ExtendedTy->getAnyNominal())
|
||||||
TC.validateDecl(nominal);
|
TC.validateDecl(nominal);
|
||||||
|
|
||||||
@@ -1973,7 +2002,7 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) {
|
|||||||
case DeclKind::Class: {
|
case DeclKind::Class: {
|
||||||
auto nominal = cast<NominalTypeDecl>(D);
|
auto nominal = cast<NominalTypeDecl>(D);
|
||||||
for (auto ext : nominal->getExtensions())
|
for (auto ext : nominal->getExtensions())
|
||||||
checkInheritanceClause(*this, ext);
|
checkInheritanceClause(ext);
|
||||||
|
|
||||||
if (nominal->hasType())
|
if (nominal->hasType())
|
||||||
return;
|
return;
|
||||||
@@ -1992,7 +2021,7 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) {
|
|||||||
nominal->computeType();
|
nominal->computeType();
|
||||||
|
|
||||||
validateAttributes(*this, D);
|
validateAttributes(*this, D);
|
||||||
checkInheritanceClause(*this, D);
|
checkInheritanceClause(D);
|
||||||
|
|
||||||
// Mark a class as [objc]. This must happen before checking its members.
|
// Mark a class as [objc]. This must happen before checking its members.
|
||||||
if (auto CD = dyn_cast<ClassDecl>(nominal)) {
|
if (auto CD = dyn_cast<ClassDecl>(nominal)) {
|
||||||
@@ -2019,14 +2048,14 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) {
|
|||||||
return;
|
return;
|
||||||
proto->computeType();
|
proto->computeType();
|
||||||
|
|
||||||
checkInheritanceClause(*this, D);
|
checkInheritanceClause(D);
|
||||||
validateAttributes(*this, D);
|
validateAttributes(*this, D);
|
||||||
|
|
||||||
// Fix the 'Self' associated type.
|
// Fix the 'Self' associated type.
|
||||||
AssociatedTypeDecl *selfDecl = nullptr;
|
AssociatedTypeDecl *selfDecl = nullptr;
|
||||||
for (auto member : proto->getMembers()) {
|
for (auto member : proto->getMembers()) {
|
||||||
if (auto AssocType = dyn_cast<AssociatedTypeDecl>(member)) {
|
if (auto AssocType = dyn_cast<AssociatedTypeDecl>(member)) {
|
||||||
checkInheritanceClause(*this, AssocType);
|
checkInheritanceClause(AssocType);
|
||||||
|
|
||||||
if (AssocType->isSelf()) {
|
if (AssocType->isSelf()) {
|
||||||
selfDecl = AssocType;
|
selfDecl = AssocType;
|
||||||
@@ -2119,13 +2148,13 @@ void TypeChecker::validateDecl(ValueDecl *D, bool resolveTypeParams) {
|
|||||||
|
|
||||||
ArrayRef<ProtocolDecl *>
|
ArrayRef<ProtocolDecl *>
|
||||||
TypeChecker::getDirectConformsTo(NominalTypeDecl *nominal) {
|
TypeChecker::getDirectConformsTo(NominalTypeDecl *nominal) {
|
||||||
checkInheritanceClause(*this, nominal);
|
checkInheritanceClause(nominal);
|
||||||
return nominal->getProtocols();
|
return nominal->getProtocols();
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<ProtocolDecl *>
|
ArrayRef<ProtocolDecl *>
|
||||||
TypeChecker::getDirectConformsTo(ExtensionDecl *ext) {
|
TypeChecker::getDirectConformsTo(ExtensionDecl *ext) {
|
||||||
checkInheritanceClause(*this, ext);
|
checkInheritanceClause(ext);
|
||||||
return ext->getProtocols();
|
return ext->getProtocols();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2388,6 +2417,7 @@ bool TypeChecker::isDefaultInitializable(Type ty, Expr **initializer,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TypeKind::GenericFunction:
|
||||||
case TypeKind::GenericTypeParam:
|
case TypeKind::GenericTypeParam:
|
||||||
case TypeKind::DependentMember:
|
case TypeKind::DependentMember:
|
||||||
llvm_unreachable("Should never ask about dependent types");
|
llvm_unreachable("Should never ask about dependent types");
|
||||||
|
|||||||
@@ -130,6 +130,356 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType(
|
|||||||
return ErrorType::get(TC.Context);
|
return ErrorType::get(TC.Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a fresh archetype builder.
|
||||||
|
static ArchetypeBuilder createArchetypeBuilder(TypeChecker &TC) {
|
||||||
|
return ArchetypeBuilder(
|
||||||
|
TC.TU, TC.Diags,
|
||||||
|
[&](ProtocolDecl *protocol) -> ArrayRef<ProtocolDecl *> {
|
||||||
|
return TC.getDirectConformsTo(protocol);
|
||||||
|
},
|
||||||
|
[&](AbstractTypeParamDecl *assocType) -> ArrayRef<ProtocolDecl *> {
|
||||||
|
TC.checkInheritanceClause(assocType);
|
||||||
|
return assocType->getProtocols();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check the generic parameters in the given generic parameter list (and its
|
||||||
|
/// parent generic parameter lists) according to the given resolver.
|
||||||
|
static void checkGenericParameters(TypeChecker &tc, ArchetypeBuilder *builder,
|
||||||
|
GenericParamList *genericParams,
|
||||||
|
GenericTypeResolver &resolver,
|
||||||
|
bool innermost = true) {
|
||||||
|
// If there are outer generic parameters, visit them (so that the archetype
|
||||||
|
// builder knows about them) but don't modify them in any way.
|
||||||
|
// FIXME: Rather than crawling the generic outer parameters, it would be far
|
||||||
|
// better to simply grab the generic parameters and requirements for the
|
||||||
|
// outer context directly. However, we don't currently store those anywhere.
|
||||||
|
if (auto outerGenericParams = genericParams->getOuterParameters())
|
||||||
|
checkGenericParameters(tc, builder, outerGenericParams, resolver,
|
||||||
|
/*innermost=*/false);
|
||||||
|
|
||||||
|
// Visit each of the generic parameters.
|
||||||
|
unsigned depth = genericParams->getDepth();
|
||||||
|
unsigned index = 0;
|
||||||
|
for (auto param : *genericParams) {
|
||||||
|
auto typeParam = param.getAsTypeParam();
|
||||||
|
|
||||||
|
// Check the generic type parameter.
|
||||||
|
if (innermost) {
|
||||||
|
// Set the depth of this type parameter.
|
||||||
|
typeParam->setDepth(depth);
|
||||||
|
|
||||||
|
// Check the inheritance clause of this type parameter.
|
||||||
|
tc.checkInheritanceClause(typeParam, &resolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builder) {
|
||||||
|
// Add the generic parameter to the builder.
|
||||||
|
builder->addGenericParameter(typeParam, index++);
|
||||||
|
|
||||||
|
// Infer requirements from the inherited types.
|
||||||
|
// FIXME: This doesn't actually do what we want for outer generic
|
||||||
|
// parameters, because they've been resolved to archetypes too eagerly.
|
||||||
|
for (const auto &inherited : typeParam->getInherited()) {
|
||||||
|
builder->inferRequirements(inherited.getTypeRepr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Visit each of the requirements, adding them to the builder.
|
||||||
|
// Add the requirements clause to the builder, validating the types in
|
||||||
|
// the requirements clause along the way.
|
||||||
|
for (auto &req : genericParams->getRequirements()) {
|
||||||
|
if (req.isInvalid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (req.getKind()) {
|
||||||
|
case RequirementKind::Conformance: {
|
||||||
|
// Validate the types.
|
||||||
|
if (tc.validateType(req.getSubjectLoc(),
|
||||||
|
/*allowUnboundGenerics=*/false,
|
||||||
|
&resolver)) {
|
||||||
|
req.setInvalid();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tc.validateType(req.getConstraintLoc(),
|
||||||
|
/*allowUnboundGenerics=*/false,
|
||||||
|
&resolver)) {
|
||||||
|
req.setInvalid();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Feels too early to perform this check.
|
||||||
|
if (!req.getConstraint()->isExistentialType() &&
|
||||||
|
!req.getConstraint()->getClassOrBoundGenericClass()) {
|
||||||
|
tc.diagnose(genericParams->getWhereLoc(),
|
||||||
|
diag::requires_conformance_nonprotocol,
|
||||||
|
req.getSubjectLoc(), req.getConstraintLoc());
|
||||||
|
req.getConstraintLoc().setInvalidType(tc.Context);
|
||||||
|
req.setInvalid();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DynamicLookup cannot be used in a generic constraint.
|
||||||
|
if (auto protoTy = req.getConstraint()->getAs<ProtocolType>()) {
|
||||||
|
if (protoTy->getDecl()->isSpecificProtocol(
|
||||||
|
KnownProtocolKind::DynamicLookup)) {
|
||||||
|
tc.diagnose(req.getConstraintLoc().getSourceRange().Start,
|
||||||
|
diag::dynamic_lookup_conformance);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RequirementKind::SameType:
|
||||||
|
if (tc.validateType(req.getFirstTypeLoc(),
|
||||||
|
/*allowUnboundGenerics=*/false,
|
||||||
|
&resolver)) {
|
||||||
|
req.setInvalid();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tc.validateType(req.getSecondTypeLoc(),
|
||||||
|
/*allowUnboundGenerics=*/false,
|
||||||
|
&resolver)) {
|
||||||
|
req.setInvalid();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builder && builder->addRequirement(req))
|
||||||
|
req.setInvalid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect all of the generic parameter types at every level in the generic
|
||||||
|
/// parameter list.
|
||||||
|
static void collectGenericParamTypes(
|
||||||
|
GenericParamList *genericParams,
|
||||||
|
SmallVectorImpl<GenericTypeParamType *> &allParams) {
|
||||||
|
if (!genericParams)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Collect outer generic parameters first.
|
||||||
|
collectGenericParamTypes(genericParams->getOuterParameters(), allParams);
|
||||||
|
|
||||||
|
// Add our parameters.
|
||||||
|
for (auto param : *genericParams) {
|
||||||
|
allParams.push_back(param.getAsTypeParam()->getDeclaredType()
|
||||||
|
->castTo<GenericTypeParamType>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/// \brief Function object that orders potential archetypes by name.
|
||||||
|
struct OrderPotentialArchetypeByName {
|
||||||
|
using PotentialArchetype = ArchetypeBuilder::PotentialArchetype;
|
||||||
|
|
||||||
|
bool operator()(std::pair<Identifier, PotentialArchetype *> X,
|
||||||
|
std::pair<Identifier, PotentialArchetype *> Y) const {
|
||||||
|
return X.first.str() < Y.second->getName().str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(std::pair<Identifier, PotentialArchetype *> X,
|
||||||
|
Identifier Y) const {
|
||||||
|
return X.first.str() < Y.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(Identifier X,
|
||||||
|
std::pair<Identifier, PotentialArchetype *> Y) const {
|
||||||
|
return X.str() < Y.first.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(Identifier X, Identifier Y) const {
|
||||||
|
return X.str() < Y.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Add the requirements for the given potential archetype and its nested
|
||||||
|
/// potential archetypes to the set of requirements.
|
||||||
|
static void
|
||||||
|
addRequirements(
|
||||||
|
TranslationUnit &tu, Type type,
|
||||||
|
ArchetypeBuilder::PotentialArchetype *pa,
|
||||||
|
llvm::SmallPtrSet<ArchetypeBuilder::PotentialArchetype *, 16> &knownPAs,
|
||||||
|
SmallVectorImpl<Requirement> &requirements) {
|
||||||
|
using PotentialArchetype = ArchetypeBuilder::PotentialArchetype;
|
||||||
|
|
||||||
|
// Add superclass requirement, if needed.
|
||||||
|
if (auto superclass = pa->getSuperclass()) {
|
||||||
|
// FIXME: Distinguish superclass from conformance?
|
||||||
|
// FIXME: What if the superclass type involves a type parameter?
|
||||||
|
requirements.push_back(Requirement(RequirementKind::Conformance,
|
||||||
|
type, superclass));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add conformance requirements.
|
||||||
|
for (auto proto : pa->getConformsTo()) {
|
||||||
|
requirements.push_back(Requirement(RequirementKind::Conformance,
|
||||||
|
type, proto->getDeclaredType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect the nested types, sorted by name.
|
||||||
|
// FIXME: Could collect these from the conformance requirements, above.
|
||||||
|
SmallVector<std::pair<Identifier, PotentialArchetype*>, 16>
|
||||||
|
nestedTypes(pa->getNestedTypes().begin(), pa->getNestedTypes().end());
|
||||||
|
std::sort(nestedTypes.begin(), nestedTypes.end(),
|
||||||
|
OrderPotentialArchetypeByName());
|
||||||
|
|
||||||
|
// Add requirements for associated types.
|
||||||
|
for (const auto &nested : nestedTypes) {
|
||||||
|
auto rep = nested.second->getRepresentative();
|
||||||
|
if (knownPAs.insert(rep)) {
|
||||||
|
// Form the dependent type that refers to this archetype.
|
||||||
|
auto assocType = pa->getAssociatedType(tu, nested.first);
|
||||||
|
if (!assocType)
|
||||||
|
continue; // FIXME: If we do this late enough, there will be no failure.
|
||||||
|
|
||||||
|
auto nestedType = DependentMemberType::get(type, assocType,
|
||||||
|
tu.getASTContext());
|
||||||
|
addRequirements(tu, nestedType, rep, knownPAs, requirements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect the set of requirements placed on the given generic parameters and
|
||||||
|
/// their associated types.
|
||||||
|
static void collectRequirements(ArchetypeBuilder &builder,
|
||||||
|
ArrayRef<GenericTypeParamType *> params,
|
||||||
|
SmallVectorImpl<Requirement> &requirements) {
|
||||||
|
// Find the "primary" potential archetypes, from which we'll collect all
|
||||||
|
// of the requirements.
|
||||||
|
llvm::SmallPtrSet<ArchetypeBuilder::PotentialArchetype *, 16> knownPAs;
|
||||||
|
llvm::SmallVector<GenericTypeParamType *, 8> primary;
|
||||||
|
for (auto param : params) {
|
||||||
|
auto pa = builder.resolveType(param);
|
||||||
|
assert(pa && "Missing potential archetype for generic parameter");
|
||||||
|
|
||||||
|
// We only care about the representative.
|
||||||
|
pa = pa->getRepresentative();
|
||||||
|
|
||||||
|
// If the potential archetype has a parent, it isn't primary.
|
||||||
|
if (pa->getRepresentative()->getParent())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (knownPAs.insert(pa))
|
||||||
|
primary.push_back(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each of the primary potential archetypes, add the requirements,
|
||||||
|
// along with the requirements of its nested types.
|
||||||
|
for (auto param : primary) {
|
||||||
|
auto pa = builder.resolveType(param)->getRepresentative();
|
||||||
|
addRequirements(builder.getTranslationUnit(), param, pa, knownPAs,
|
||||||
|
requirements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check the signature of a generic function.
|
||||||
|
static bool checkGenericFuncSignature(TypeChecker &tc,
|
||||||
|
ArchetypeBuilder *builder,
|
||||||
|
FuncDecl *func,
|
||||||
|
GenericTypeResolver &resolver) {
|
||||||
|
bool badType = false;
|
||||||
|
|
||||||
|
// Check the generic parameter list.
|
||||||
|
checkGenericParameters(tc, builder, func->getGenericParams(), resolver);
|
||||||
|
|
||||||
|
// Check the parameter patterns.
|
||||||
|
for (auto pattern : func->getArgParamPatterns()) {
|
||||||
|
// Check the pattern.
|
||||||
|
if (tc.typeCheckPattern(pattern, func, /*allowUnboundGenerics=*/false,
|
||||||
|
&resolver))
|
||||||
|
badType = true;
|
||||||
|
|
||||||
|
// Infer requirements from the pattern.
|
||||||
|
if (builder) {
|
||||||
|
builder->inferRequirements(pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a declared result type, check that as well.
|
||||||
|
if (!func->getBodyResultTypeLoc().isNull()) {
|
||||||
|
// Check the result type of the function.
|
||||||
|
if (tc.validateType(func->getBodyResultTypeLoc(),
|
||||||
|
/*allowUnboundGenerics=*/false,
|
||||||
|
&resolver)) {
|
||||||
|
badType = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Infer requirements from it.
|
||||||
|
if (builder) {
|
||||||
|
builder->inferRequirements(func->getBodyResultTypeLoc().getTypeRepr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return badType;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TypeChecker::validateGenericFuncSignature(FuncDecl *func) {
|
||||||
|
// Create the archetype builder.
|
||||||
|
ArchetypeBuilder builder = createArchetypeBuilder(*this);
|
||||||
|
|
||||||
|
// Type check the function declaration, treating all generic type
|
||||||
|
// parameters as dependent, unresolved.
|
||||||
|
PartialGenericTypeToArchetypeResolver partialResolver(*this);
|
||||||
|
if (checkGenericFuncSignature(*this, &builder, func, partialResolver)) {
|
||||||
|
func->setType(ErrorType::get(Context));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The archetype builder now has all of the requirements, although there might
|
||||||
|
// still be errors that have not yet been diagnosed. Revert the generic
|
||||||
|
// function signature and type-check it again, completely.
|
||||||
|
revertGenericFuncSignature(func);
|
||||||
|
CompleteGenericTypeResolver completeResolver(*this, builder);
|
||||||
|
if (checkGenericFuncSignature(*this, nullptr, func, completeResolver)) {
|
||||||
|
func->setType(ErrorType::get(Context));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The generic function signature is complete and well-formed. Determine
|
||||||
|
// the type of the generic function.
|
||||||
|
|
||||||
|
// Collect the complete set of generic parameter types.
|
||||||
|
SmallVector<GenericTypeParamType *, 4> allGenericParams;
|
||||||
|
collectGenericParamTypes(func->getGenericParams(), allGenericParams);
|
||||||
|
|
||||||
|
// Collect the requirements placed on the generic parameter types.
|
||||||
|
SmallVector<Requirement, 4> requirements;
|
||||||
|
collectRequirements(builder, allGenericParams, requirements);
|
||||||
|
|
||||||
|
// Compute the function type.
|
||||||
|
auto funcTy = func->getBodyResultTypeLoc().getType();
|
||||||
|
if (!funcTy) {
|
||||||
|
funcTy = TupleType::getEmpty(Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto patterns = func->getArgParamPatterns();
|
||||||
|
for (unsigned i = 0, e = patterns.size(); i != e; ++i) {
|
||||||
|
Type argTy = patterns[e - i - 1]->getType();
|
||||||
|
|
||||||
|
// Validate and consume the function type attributes.
|
||||||
|
// FIXME: Hacked up form of validateAndConsumeFunctionTypeAttributes().
|
||||||
|
auto info = AnyFunctionType::ExtInfo()
|
||||||
|
.withIsNoReturn(func->getAttrs().isNoReturn());
|
||||||
|
|
||||||
|
if (i == e-1) {
|
||||||
|
funcTy = GenericFunctionType::get(allGenericParams, requirements,
|
||||||
|
argTy, funcTy, info, Context);
|
||||||
|
} else {
|
||||||
|
funcTy = FunctionType::get(argTy, funcTy, info, Context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
SpecializeExpr *
|
SpecializeExpr *
|
||||||
TypeChecker::buildSpecializeExpr(Expr *Sub, Type Ty,
|
TypeChecker::buildSpecializeExpr(Expr *Sub, Type Ty,
|
||||||
const TypeSubstitutionMap &Substitutions,
|
const TypeSubstitutionMap &Substitutions,
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
namespace swift {
|
namespace swift {
|
||||||
|
|
||||||
|
class ArchetypeBuilder;
|
||||||
class GenericTypeResolver;
|
class GenericTypeResolver;
|
||||||
class TypeChecker;
|
class TypeChecker;
|
||||||
|
|
||||||
@@ -325,6 +326,22 @@ public:
|
|||||||
validateDecl(VD, true);
|
validateDecl(VD, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Validate the signature of a generic function.
|
||||||
|
///
|
||||||
|
/// \param func The generic function.
|
||||||
|
///
|
||||||
|
/// \returns true if an error occurred, or false otherwise.
|
||||||
|
bool validateGenericFuncSignature(FuncDecl *func);
|
||||||
|
|
||||||
|
/// Revert the signature of a generic function to its pre-type-checked state,
|
||||||
|
/// so that it can be type checked again when we have resolved its generic
|
||||||
|
/// parameters.
|
||||||
|
void revertGenericFuncSignature(FuncDecl *func);
|
||||||
|
|
||||||
|
/// Check the inheritance clause of the given declaration.
|
||||||
|
void checkInheritanceClause(Decl *decl,
|
||||||
|
GenericTypeResolver *resolver = nullptr);
|
||||||
|
|
||||||
/// Retrieve the set of protocols to which this nominal type declaration
|
/// Retrieve the set of protocols to which this nominal type declaration
|
||||||
/// directly conforms, i.e., as specified in its own inheritance clause.
|
/// directly conforms, i.e., as specified in its own inheritance clause.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -455,7 +455,7 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC) {
|
|||||||
archetypes.push_back(getType(next)->castTo<ArchetypeType>());
|
archetypes.push_back(getType(next)->castTo<ArchetypeType>());
|
||||||
|
|
||||||
SmallVector<GenericParam, 8> params;
|
SmallVector<GenericParam, 8> params;
|
||||||
SmallVector<Requirement, 8> requirements;
|
SmallVector<RequirementRepr, 8> requirements;
|
||||||
while (true) {
|
while (true) {
|
||||||
lastRecordOffset.reset();
|
lastRecordOffset.reset();
|
||||||
bool shouldContinue = true;
|
bool shouldContinue = true;
|
||||||
@@ -486,7 +486,7 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC) {
|
|||||||
auto subject = TypeLoc::withoutLoc(getType(rawTypeIDs[0]));
|
auto subject = TypeLoc::withoutLoc(getType(rawTypeIDs[0]));
|
||||||
auto constraint = TypeLoc::withoutLoc(getType(rawTypeIDs[1]));
|
auto constraint = TypeLoc::withoutLoc(getType(rawTypeIDs[1]));
|
||||||
|
|
||||||
requirements.push_back(Requirement::getConformance(subject,
|
requirements.push_back(RequirementRepr::getConformance(subject,
|
||||||
SourceLoc(),
|
SourceLoc(),
|
||||||
constraint));
|
constraint));
|
||||||
break;
|
break;
|
||||||
@@ -496,7 +496,7 @@ GenericParamList *ModuleFile::maybeReadGenericParams(DeclContext *DC) {
|
|||||||
auto first = TypeLoc::withoutLoc(getType(rawTypeIDs[0]));
|
auto first = TypeLoc::withoutLoc(getType(rawTypeIDs[0]));
|
||||||
auto second = TypeLoc::withoutLoc(getType(rawTypeIDs[1]));
|
auto second = TypeLoc::withoutLoc(getType(rawTypeIDs[1]));
|
||||||
|
|
||||||
requirements.push_back(Requirement::getSameType(first,
|
requirements.push_back(RequirementRepr::getSameType(first,
|
||||||
SourceLoc(),
|
SourceLoc(),
|
||||||
second));
|
second));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1493,6 +1493,10 @@ void Serializer::writeType(Type ty) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TypeKind::GenericFunction: {
|
||||||
|
llvm_unreachable("Cannot serialize generic function types yet");
|
||||||
|
}
|
||||||
|
|
||||||
case TypeKind::GenericTypeParam: {
|
case TypeKind::GenericTypeParam: {
|
||||||
auto genericParam = cast<GenericTypeParamType>(ty.getPointer());
|
auto genericParam = cast<GenericTypeParamType>(ty.getPointer());
|
||||||
unsigned abbrCode = DeclTypeAbbrCodes[GenericTypeParamTypeLayout::Code];
|
unsigned abbrCode = DeclTypeAbbrCodes[GenericTypeParamTypeLayout::Code];
|
||||||
|
|||||||
Reference in New Issue
Block a user