Skip to content

Eliminate witness markers #5704

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 10, 2016
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
87 changes: 16 additions & 71 deletions include/swift/AST/GenericSignature.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,71 +31,6 @@ class ProtocolType;
class Substitution;
class SubstitutionMap;

/// Iterator that walks the generic parameter types declared in a generic
/// signature and their dependent members.
class GenericSignatureWitnessIterator {
ArrayRef<Requirement> p;

void checkValid() const {
assert(!p.empty() &&
p.front().getKind() == RequirementKind::WitnessMarker);
}

bool shouldSkip() const {
return (!p.empty() &&
p.front().getKind() != RequirementKind::WitnessMarker);
}

public:
GenericSignatureWitnessIterator() = default;
GenericSignatureWitnessIterator(ArrayRef<Requirement> requirements)
: p(requirements) {
while (shouldSkip()) { p = p.slice(1); }
}

GenericSignatureWitnessIterator &operator++() {
checkValid();
do { p = p.slice(1); } while (shouldSkip());
return *this;
}

GenericSignatureWitnessIterator operator++(int) {
auto copy = *this;
++(*this);
return copy;
}

Type operator*() const {
checkValid();
return p.front().getFirstType();
}

Type operator->() const {
checkValid();
return p.front().getFirstType();
}

bool operator==(const GenericSignatureWitnessIterator &o) {
return p.data() == o.p.data() && p.size() == o.p.size();
}

bool operator!=(const GenericSignatureWitnessIterator &o) {
return p.data() != o.p.data() || p.size() != o.p.size();
}

static GenericSignatureWitnessIterator emptyRange() {
return GenericSignatureWitnessIterator();
}

// Allow the witness iterator to be used with a ranged for.
GenericSignatureWitnessIterator begin() const {
return *this;
}
GenericSignatureWitnessIterator end() const {
return GenericSignatureWitnessIterator({p.end(), p.end()});
}
};

/// Describes the generic signature of a particular declaration, including
/// both the generic type parameters and the requirements placed on those
/// generic parameters.
Expand Down Expand Up @@ -207,12 +142,22 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
const SubstitutionMap &subMap,
SmallVectorImpl<Substitution> &result) const;

/// Return a range that iterates through first all of the generic parameters
/// of the signature, followed by all of their recursive member types exposed
/// through protocol requirements.
GenericSignatureWitnessIterator getAllDependentTypes() const {
return GenericSignatureWitnessIterator(getRequirements());
}
/// Return a range that iterates through all of the types that require
/// substitution, which includes the generic parameter types as well as
/// other dependent types that require additional conformances.
SmallVector<Type, 4> getAllDependentTypes() const;

/// Enumerate all of the dependent types in the type signature that will
/// occur in substitution lists (in order), along with the set of
/// conformance requirements placed on that dependent type.
///
/// \param fn Callback function that will receive each (type, requirements)
/// pair, in the order they occur within a list of substitutions. If this
/// returns \c true, the enumeration will be aborted.
///
/// \returns true if any call to \c fn returned \c true, otherwise \c false.
bool enumeratePairedRequirements(
llvm::function_ref<bool(Type, ArrayRef<Requirement>)> fn) const;

/// Determines whether this GenericSignature is canonical.
bool isCanonical() const;
Expand Down
12 changes: 2 additions & 10 deletions include/swift/AST/Requirement.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@ enum class RequirementKind : unsigned {
/// A same-type requirement T == U, where T and U are types that shall be
/// equivalent.
SameType,
/// A marker that indicates where the witness for the given (first)
/// type should be located.
///
/// FIXME: This is a crutch used to help us eliminate various walks over
/// "all archetypes".
WitnessMarker

// Note: there is code that packs this enum in a 2-bit bitfield. Audit users
// when adding enumerators.
Expand All @@ -56,10 +50,8 @@ class Requirement {
/// Create a conformance or same-type requirement.
Requirement(RequirementKind kind, Type first, Type second)
: FirstTypeAndKind(first, kind), SecondType(second) {
if (kind != RequirementKind::WitnessMarker) {
assert(first);
assert(second);
}
assert(first);
assert(second);
}

/// \brief Determine the kind of requirement.
Expand Down
7 changes: 3 additions & 4 deletions include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
const uint16_t VERSION_MINOR = 282; // Last change: @_inlineable
const uint16_t VERSION_MINOR = 283; // Last change: witness markers removed

using DeclID = PointerEmbeddedInt<unsigned, 31>;
using DeclIDField = BCFixed<31>;
Expand Down Expand Up @@ -236,9 +236,8 @@ static inline OperatorKind getStableFixity(DeclKind kind) {
// VERSION_MAJOR.
enum GenericRequirementKind : uint8_t {
Conformance = 0,
SameType,
WitnessMarker,
Superclass
SameType = 1,
Superclass = 2,
};
using GenericRequirementKindField = BCFixed<2>;

Expand Down
6 changes: 2 additions & 4 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3542,8 +3542,7 @@ void GenericSignature::Profile(llvm::FoldingSetNodeID &ID,

for (auto &reqt : requirements) {
ID.AddPointer(reqt.getFirstType().getPointer());
if (reqt.getKind() != RequirementKind::WitnessMarker)
ID.AddPointer(reqt.getSecondType().getPointer());
ID.AddPointer(reqt.getSecondType().getPointer());
ID.AddInteger(unsigned(reqt.getKind()));
}
}
Expand Down Expand Up @@ -4056,8 +4055,7 @@ CanGenericSignature ASTContext::getSingleGenericParameterSignature() const {
return theSig;

auto param = GenericTypeParamType::get(0, 0, *this);
auto witnessReqt = Requirement(RequirementKind::WitnessMarker, param, Type());
auto sig = GenericSignature::get(param, witnessReqt);;
auto sig = GenericSignature::get(param, { });
auto canonicalSig = CanGenericSignature(sig);
Impl.SingleGenericParameterSignature = canonicalSig;
return canonicalSig;
Expand Down
15 changes: 0 additions & 15 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,6 @@ struct SynthesizedExtensionAnalyzer::Implementation {
assert(Ext->getGenericSignature() && "No generic signature.");
for (auto Req : Ext->getGenericSignature()->getRequirements()) {
auto Kind = Req.getKind();
if (Kind == RequirementKind::WitnessMarker)
continue;

Type First = Req.getFirstType().subst(
M, subMap, SubstOptions());
Expand All @@ -251,9 +249,6 @@ struct SynthesizedExtensionAnalyzer::Implementation {
Second = Second->getCanonicalType();

switch (Kind) {
case RequirementKind::WitnessMarker:
break;

case RequirementKind::Conformance:
case RequirementKind::Superclass:
if (!canPossiblyConvertTo(First, Second, *DC))
Expand Down Expand Up @@ -1208,7 +1203,6 @@ static unsigned getDepthOfRequirement(const Requirement &req) {
switch (req.getKind()) {
case RequirementKind::Conformance:
case RequirementKind::Superclass:
case RequirementKind::WitnessMarker:
return getDepthOfType(req.getFirstType());

case RequirementKind::SameType: {
Expand Down Expand Up @@ -1337,9 +1331,6 @@ void PrintAST::printSingleDepthOfGenericSignature(
// Print the requirements.
bool isFirstReq = true;
for (const auto &req : requirements) {
if (req.getKind() == RequirementKind::WitnessMarker)
continue;

auto first = req.getFirstType();
auto second = req.getSecondType();

Expand Down Expand Up @@ -1387,9 +1378,6 @@ void PrintAST::printRequirement(const Requirement &req) {
case RequirementKind::SameType:
Printer << " == ";
break;

case RequirementKind::WitnessMarker:
llvm_unreachable("Handled above");
}
printType(req.getSecondType());
}
Expand Down Expand Up @@ -4119,9 +4107,6 @@ void GenericSignature::dump() const {

void Requirement::dump() const {
switch (getKind()) {
case RequirementKind::WitnessMarker:
llvm::errs() << "witness_marker: ";
break;
case RequirementKind::Conformance:
llvm::errs() << "conforms_to: ";
break;
Expand Down
31 changes: 0 additions & 31 deletions lib/AST/ArchetypeBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1517,9 +1517,6 @@ void ArchetypeBuilder::addRequirement(const Requirement &req,
case RequirementKind::SameType:
addSameTypeRequirement(req.getFirstType(), req.getSecondType(), source);
return;

case RequirementKind::WitnessMarker:
return;
}

llvm_unreachable("Unhandled requirement?");
Expand Down Expand Up @@ -1569,9 +1566,6 @@ class ArchetypeBuilder::InferRequirementsWalker : public TypeWalker {
RequirementSource source(RequirementSource::Inferred, Loc);
for (const auto &req : genericSig->getRequirements()) {
switch (req.getKind()) {
case RequirementKind::WitnessMarker:
break;

case RequirementKind::SameType: {
auto firstType = req.getFirstType().subst(
&Builder.getModule(),
Expand Down Expand Up @@ -1891,10 +1885,6 @@ void ArchetypeBuilder::enumerateRequirements(llvm::function_ref<
continue;
}

// Add the witness marker.
f(RequirementKind::WitnessMarker, archetype, Type(),
RequirementSource(RequirementSource::Explicit, SourceLoc()));

// If we have a superclass, produce a superclass requirement
if (Type superclass = archetype->getSuperclass()) {
f(RequirementKind::Superclass, archetype, superclass,
Expand Down Expand Up @@ -1957,10 +1947,6 @@ void ArchetypeBuilder::dump(llvm::raw_ostream &out) {
source.dump(out, &Context.SourceMgr);
out << "]";
break;

case RequirementKind::WitnessMarker:
out << "\n " << archetype->getDebugName() << " witness marker";
break;
}
});
out << "\n";
Expand Down Expand Up @@ -2046,15 +2032,6 @@ Type ArchetypeBuilder::substDependentType(Type type) {
static void collectRequirements(ArchetypeBuilder &builder,
ArrayRef<GenericTypeParamType *> params,
SmallVectorImpl<Requirement> &requirements) {
// Don't emit WitnessMarker requirements for secondary types with
// no requirements.
auto dropRedundantWitnessMarker = [&]() {
if (!requirements.empty() &&
requirements.back().getKind() == RequirementKind::WitnessMarker &&
!requirements.back().getFirstType()->is<GenericTypeParamType>())
requirements.pop_back();
};

builder.enumerateRequirements([&](RequirementKind kind,
ArchetypeBuilder::PotentialArchetype *archetype,
llvm::PointerUnion<Type, ArchetypeBuilder::PotentialArchetype *> type,
Expand All @@ -2078,12 +2055,6 @@ static void collectRequirements(ArchetypeBuilder &builder,
if (depTy->hasError())
return;

if (kind == RequirementKind::WitnessMarker) {
dropRedundantWitnessMarker();
requirements.push_back(Requirement(kind, depTy, Type()));
return;
}

Type repTy;
if (auto concreteTy = type.dyn_cast<Type>()) {
// Maybe we were equated to a concrete type...
Expand All @@ -2099,8 +2070,6 @@ static void collectRequirements(ArchetypeBuilder &builder,

requirements.push_back(Requirement(kind, depTy, repTy));
});

dropRedundantWitnessMarker();
}

GenericSignature *ArchetypeBuilder::getGenericSignature() {
Expand Down
8 changes: 1 addition & 7 deletions lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,8 @@ getBuiltinGenericFunction(Identifier Id,
GenericParamTypes.push_back(gp->getDeclaredType()
->castTo<GenericTypeParamType>());
}
// Create witness markers for all of the generic param types.
SmallVector<Requirement, 2> requirements;
for (auto param : GenericParamTypes) {
requirements.push_back(Requirement(RequirementKind::WitnessMarker,
param, Type()));
}
GenericSignature *Sig =
GenericSignature::get(GenericParamTypes, requirements);
GenericSignature::get(GenericParamTypes, { });
GenericEnvironment *Env =
GenericEnvironment::get(Context, GenericParamTypes,
InterfaceToArchetypeMap);
Expand Down
Loading