Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions include/swift/AST/GenericEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,10 +277,18 @@ class alignas(1 << DeclAlignInBits) GenericEnvironment final
/// Map a generic parameter type to a contextual type.
Type mapTypeIntoContext(GenericTypeParamType *type) const;

/// Map a type containing parameter packs to a contextual type
/// in the opened element generic context.
/// Map an interface type containing parameter packs to a contextual
/// type in the opened element generic context.
Type mapPackTypeIntoElementContext(Type type) const;

/// Map a contextual type containing parameter packs to a contextual
/// type in the opened element generic context.
Type mapContextualPackTypeIntoElementContext(Type type) const;

/// Map a contextual type containing parameter packs to a contextual
/// type in the opened element generic context.
CanType mapContextualPackTypeIntoElementContext(CanType type) const;

/// Map a type containing pack element type parameters to a contextual
/// type in the pack generic context.
Type mapElementTypeIntoPackContext(Type type) const;
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -6829,6 +6829,7 @@ class PackType final : public TypeBase, public llvm::FoldingSetNode,
};
BEGIN_CAN_TYPE_WRAPPER(PackType, Type)
static CanPackType get(const ASTContext &ctx, ArrayRef<CanType> elements);
static CanPackType get(const ASTContext &ctx, CanTupleEltTypeArrayRef elts);

CanType getElementType(unsigned elementNo) const {
return CanType(getPointer()->getElementType(elementNo));
Expand Down
100 changes: 100 additions & 0 deletions include/swift/Basic/IndexedViewRange.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//===- IndexedViewRange.h - Iterators for indexed projections ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines IndexedViewRange, a template class which makes it
// easy to define a range for a "collection" that is normally just vended
// with an indexed accessor.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_BASIC_INDEXEDVIEWRANGE_H
#define SWIFT_BASIC_INDEXEDVIEWRANGE_H

#include <iterator>
#include <memory>
#include "llvm/ADT/iterator_range.h"

namespace swift {

/// An iterator over a range of values provided by an indexed accessor
/// on a base type.
template <class BaseType, class ProjectedType,
ProjectedType (&Project)(BaseType, size_t)>
class IndexedViewIterator {
public:
using value_type = ProjectedType;
using reference = ProjectedType;
using pointer = void;
using difference_type = ptrdiff_t;
using iterator_category = std::random_access_iterator_tag;
private:
BaseType Base;
size_t Index;
public:
IndexedViewIterator(BaseType base, size_t index)
: Base(base), Index(index) {}
public:
ProjectedType operator*() const { return Project(Base, Index); }
ProjectedType operator->() const { return Project(Base, Index); }
IndexedViewIterator &operator++() { Index++; return *this; }
IndexedViewIterator operator++(int) { return iterator(Base, Index++); }
IndexedViewIterator &operator--() { Index--; return *this; }
IndexedViewIterator operator--(int) { return iterator(Base, Index--); }
bool operator==(IndexedViewIterator rhs) const { return Index == rhs.Index; }
bool operator!=(IndexedViewIterator rhs) const { return Index != rhs.Index; }

IndexedViewIterator &operator+=(difference_type i) {
Index += i;
return *this;
}
IndexedViewIterator operator+(difference_type i) const {
return IndexedViewIterator(Base, Index + i);
}
friend IndexedViewIterator operator+(difference_type i,
IndexedViewIterator rhs) {
return IndexedViewIterator(rhs.Base, rhs.Index + i);
}
IndexedViewIterator &operator-=(difference_type i) {
Index -= i;
return *this;
}
IndexedViewIterator operator-(difference_type i) const {
return IndexedViewIterator(Base, Index - i);
}
difference_type operator-(IndexedViewIterator rhs) const {
return Index - rhs.Index;
}
ProjectedType operator[](difference_type i) const {
return Project(Base, Index + i);
}
bool operator<(IndexedViewIterator rhs) const {
return Index < rhs.Index;
}
bool operator<=(IndexedViewIterator rhs) const {
return Index <= rhs.Index;
}
bool operator>(IndexedViewIterator rhs) const {
return Index > rhs.Index;
}
bool operator>=(IndexedViewIterator rhs) const {
return Index >= rhs.Index;
}
};

template <class BaseType, class ProjectedType,
ProjectedType (&Project)(BaseType, size_t)>
using IndexedViewRange =
llvm::iterator_range<IndexedViewIterator<BaseType, ProjectedType, Project>>;

} // end namespace swift

#endif // SWIFT_BASIC_INDEXEDVIEWRANGE_H
14 changes: 14 additions & 0 deletions include/swift/SIL/AbstractionPattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#ifndef SWIFT_SIL_ABSTRACTIONPATTERN_H
#define SWIFT_SIL_ABSTRACTIONPATTERN_H

#include "swift/Basic/IndexedViewRange.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Types.h"

Expand Down Expand Up @@ -1332,6 +1333,17 @@ class AbstractionPattern {
llvm_unreachable("bad kind");
}

static AbstractionPattern
projectTupleElementType(const AbstractionPattern *base, size_t index) {
return base->getTupleElementType(index);
}

IndexedViewRange<const AbstractionPattern *, AbstractionPattern,
projectTupleElementType> getTupleElementTypes() const {
assert(isTuple());
return { { this, 0 }, { this, getNumTupleElements() } };
}

/// Is the given pack type a valid substitution of this abstraction
/// pattern?
bool matchesPack(CanPackType substType);
Expand Down Expand Up @@ -1472,6 +1484,8 @@ class AbstractionPattern {
void forEachPackExpandedComponent(
llvm::function_ref<void(AbstractionPattern pattern)> fn) const;

SmallVector<AbstractionPattern, 4> getPackExpandedComponents() const;

/// If this pattern refers to a foreign ObjC method that was imported as
/// async, return the bridged-back-to-ObjC completion handler type.
CanType getObjCMethodAsyncCompletionHandlerForeignType(
Expand Down
6 changes: 6 additions & 0 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3303,6 +3303,12 @@ CanPackType CanPackType::get(const ASTContext &C, ArrayRef<CanType> elements) {
return CanPackType(PackType::get(C, ncElements));
}

CanPackType CanPackType::get(const ASTContext &C,
CanTupleEltTypeArrayRef elements) {
SmallVector<Type, 8> ncElements(elements.begin(), elements.end());
return CanPackType(PackType::get(C, ncElements));
}

PackType *PackType::get(const ASTContext &C, ArrayRef<Type> elements) {
RecursiveTypeProperties properties;
bool isCanonical = true;
Expand Down
23 changes: 23 additions & 0 deletions lib/AST/GenericEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,29 @@ Type GenericEnvironment::mapTypeIntoContext(GenericTypeParamType *type) const {
return result;
}

Type
GenericEnvironment::mapContextualPackTypeIntoElementContext(Type type) const {
if (!type->hasArchetype()) return type;

// FIXME: this is potentially wrong if there are multiple
// openings in play at once, because we really shouldn't touch
// other element archetypes.
return mapPackTypeIntoElementContext(type->mapTypeOutOfContext());
}

CanType
GenericEnvironment::mapContextualPackTypeIntoElementContext(CanType type) const {
if (!type->hasArchetype()) return type;

// FIXME: this is potentially wrong if there are multiple
// openings in play at once, because we really shouldn't touch
// other element archetypes.
// FIXME: if we do this properly, there's no way for this rewrite
// to produce a non-canonical type.
return mapPackTypeIntoElementContext(type->mapTypeOutOfContext())
->getCanonicalType();
}

Type
GenericEnvironment::mapPackTypeIntoElementContext(Type type) const {
assert(getKind() == Kind::OpenedElement);
Expand Down
9 changes: 1 addition & 8 deletions lib/AST/ParameterPack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,13 +478,6 @@ bool SILPackType::containsPackExpansionType() const {
CanPackType
CanTupleType::getInducedPackTypeImpl(CanTupleType tuple, unsigned start, unsigned count) {
assert(start + count <= tuple->getNumElements() && "range out of range");

auto &ctx = tuple->getASTContext();
if (count == 0) return CanPackType::get(ctx, {});

SmallVector<CanType, 4> eltTypes;
eltTypes.reserve(count);
for (unsigned i = start, e = start + count; i != e; ++i)
eltTypes.push_back(tuple.getElementType(i));
return CanPackType::get(ctx, eltTypes);
return CanPackType::get(ctx, tuple.getElementTypes().slice(start, count));
}
7 changes: 2 additions & 5 deletions lib/IRGen/GenPack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,7 @@ static llvm::Value *emitPackExpansionElementMetadata(
// Replace pack archetypes with element archetypes in the pattern type.
auto instantiatedPatternTy =
context.environment
->mapPackTypeIntoElementContext(patternTy->mapTypeOutOfContext())
->getCanonicalType();
->mapContextualPackTypeIntoElementContext(patternTy);

// Emit the element metadata.
auto element = IGF.emitTypeMetadataRef(instantiatedPatternTy, request)
Expand Down Expand Up @@ -505,9 +504,7 @@ static llvm::Value *emitPackExpansionElementWitnessTable(

// Replace pack archetypes with element archetypes in the pattern type.
auto instantiatedPatternTy =
context.environment
->mapPackTypeIntoElementContext(patternTy->mapTypeOutOfContext())
->getCanonicalType();
context.environment->mapContextualPackTypeIntoElementContext(patternTy);
auto instantiatedConformance =
context.environment->getGenericSignature()->lookupConformance(
instantiatedPatternTy, conformance.getRequirement());
Expand Down
9 changes: 9 additions & 0 deletions lib/SIL/IR/AbstractionPattern.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,15 @@ AbstractionPattern AbstractionPattern::getPackExpansionCountType() const {
llvm_unreachable("bad kind");
}

SmallVector<AbstractionPattern, 4>
AbstractionPattern::getPackExpandedComponents() const {
SmallVector<AbstractionPattern, 4> result;
forEachPackExpandedComponent([&](AbstractionPattern pattern) {
result.push_back(pattern);
});
return result;
}

void AbstractionPattern::forEachPackExpandedComponent(
llvm::function_ref<void (AbstractionPattern)> fn) const {
assert(isPackExpansion());
Expand Down
32 changes: 32 additions & 0 deletions lib/SILGen/Initialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,31 @@ class Initialization {
llvm_unreachable("Must implement if canPerformPackExpansionInitialization"
"returns true");
}

/// Given that this supports pack expansion initialization, can it
/// perform *in place* pack expansion initialization by producing
/// a pack element of the given type?
///
/// The dominance relationship gets a little screwed up here; only
/// return true if it's okay for the address to be written into a
/// pack and then initialized later.
virtual bool
canPerformInPlacePackInitialization(GenericEnvironment *env,
SILType eltAddrTy) const {
return false;
}

/// Given that this supports in-place pack expansion initialization,
/// return the address of the storage.
///
/// For convenience, the same element type that was accepted before
/// is passed again.
virtual SILValue getAddressForInPlacePackInitialization(SILGenFunction &SGF,
SILLocation loc,
SILType eltAddrTy) {
llvm_unreachable("Must implement if canPerformInPlacePackInitialization"
"returns true");
}

/// Return true if we can get the addresses of elements with the
/// 'splitIntoTupleElements' method. Subclasses can override this to
Expand Down Expand Up @@ -365,6 +390,13 @@ class InPlacePackExpansionInitialization : public Initialization {
SILValue indexWithinComponent,
llvm::function_ref<void(Initialization *into)> fn) override;

bool canPerformInPlacePackInitialization(GenericEnvironment *env,
SILType eltAddrTy) const override;

SILValue getAddressForInPlacePackInitialization(SILGenFunction &SGF,
SILLocation loc,
SILType eltAddrTy) override;

virtual CanPackExpansionType getLoweredExpansionType() const = 0;
virtual CleanupHandle enterPartialDestroyCleanup(SILGenFunction &SGF,
SILValue indexWithinComponent) = 0;
Expand Down
Loading