Files
swift-mirror/include/swift/SIL/SILWitnessVisitor.h
gregomni 1e3ed8bdd0 Split parsing for typealias & associatedtype, and allow typealias in protocols.
Split up parsing of typealias and associatedtype, including dropping a
now unneeded ParseDeclOptions flag.

Then made typealias in a protocol valid, and act like you would
hope for protocol conformance purposes (i.e. as an alias possibly
involved in the types of other func/var conformances, not as a hidden
generic param in itself).

Also added support for simple type aliases in generic constraints. Aliases
to simple (non-sugared) archetype types (and also - trivially - aliases to
concrete types) can now be part of same-type constraints.

The strategy here is to add type aliases to the tree of
PotentialArchetypes, and if they are an alias to an archetype, also to
immediately find the real associated type and set it as the
representative for the PA. Thus the typealias PA node becomes just a
shortcut farther down into the tree for purposes of lookup and
generating same type requirements.

Then the typealias PA nodes need to be explicitly skipped when walking
the tree for building archetype types and other types of requirements,
in order to keep from getting extra out-of-order archetypes/witness
markers of the real associated type inserted where the typealias is
defined.

Any constraint with a typealias more complex than pointing to a single
nested associated type (e.g. `typealias T = A.B.C.D`), will now get a
specialized diagnoses.
2016-03-13 21:44:23 -07:00

121 lines
4.0 KiB
C++

//===--- SILWitnessVisitor.h - Witness method table visitor -----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 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 SILWitnessVisitor class, which is used to generate and
// perform lookups in witness method tables for protocols and protocol
// conformances.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SIL_SILWITNESSVISITOR_H
#define SWIFT_SIL_SILWITNESSVISITOR_H
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Types.h"
#include "swift/SIL/TypeLowering.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
namespace swift {
/// A CRTP class for visiting the witnesses of a protocol.
///
/// The design here is that each entry (or small group of entries)
/// gets turned into a call to the implementation class describing
/// the exact variant of witness. For example, for member
/// variables, there should be separate callbacks for adding a
/// getter/setter pair, for just adding a getter, and for adding a
/// physical projection (if we decide to support that).
///
/// You must override the following methods:
/// - addOutOfLineBaseProtocol()
/// - addMethod()
/// - addConstructor()
/// - addAssociatedType()
template <class T> class SILWitnessVisitor : public ASTVisitor<T> {
T &asDerived() { return *static_cast<T*>(this); }
public:
void visitProtocolDecl(ProtocolDecl *protocol) {
// Visit inherited protocols.
// TODO: We need to figure out all the guarantees we want here.
// It would be abstractly good to allow conversion to a base
// protocol to be trivial, but it's not clear that there's
// really a structural guarantee we can rely on here.
for (auto baseProto : protocol->getInheritedProtocols(nullptr)) {
// ObjC protocols do not have witnesses.
if (!Lowering::TypeConverter::protocolRequiresWitnessTable(baseProto))
continue;
asDerived().addOutOfLineBaseProtocol(baseProto);
}
/// Visit the witnesses for the direct members of a protocol.
for (Decl *member : protocol->getMembers())
ASTVisitor<T>::visit(member);
}
/// Fallback for unexpected protocol requirements.
void visitDecl(Decl *d) {
d->print(llvm::errs());
llvm_unreachable("unhandled protocol requirement");
}
void visitAbstractStorageDecl(AbstractStorageDecl *sd) {
asDerived().addMethod(sd->getGetter());
if (sd->isSettable(sd->getDeclContext())) {
asDerived().addMethod(sd->getSetter());
if (sd->getMaterializeForSetFunc())
asDerived().addMethod(sd->getMaterializeForSetFunc());
}
}
void visitConstructorDecl(ConstructorDecl *cd) {
asDerived().addConstructor(cd);
}
void visitFuncDecl(FuncDecl *func) {
// Accessors are emitted by their var/subscript declaration.
if (func->isAccessor())
return;
asDerived().addMethod(func);
}
void visitAssociatedTypeDecl(AssociatedTypeDecl *td) {
SmallVector<ProtocolDecl *, 4> protos;
for (auto p : td->getConformingProtocols(nullptr))
protos.push_back(p);
ProtocolType::canonicalizeProtocols(protos);
asDerived().addAssociatedType(td, protos);
}
void visitTypeAliasDecl(TypeAliasDecl *tad) {
// We don't care about these by themselves for witnesses.
}
void visitPatternBindingDecl(PatternBindingDecl *pbd) {
// We only care about the contained VarDecls.
}
void visitIfConfigDecl(IfConfigDecl *icd) {
// We only care about the active members, which were already subsumed by the
// enclosing type.
}
};
} // end namespace swift
#endif