Files
swift-mirror/include/swift/AST/Requirement.h
Slava Pestov 1d427eaa12 AST: Add request to compute protocol structural requirements and dependencies
These will be used by the RequirementMachine to compute requirement
signatures. For now, they're not hooked up.

ProtocolDecl::getStructuralRequirements() produces a list of Requirements
with SourceLocs from the structural types written in the protocol's
inheritance clause and 'where' clauses.

ProtocolDecl::getProtocolDependencies() produces a list of protocols which
appear on the right hand side of the protocol's conformance requirements.
2021-09-28 14:31:32 -04:00

130 lines
4.6 KiB
C++

//===--- Requirement.h - Swift Requirement ASTs -----------------*- 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 the Requirement class and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_AST_REQUIREMENT_H
#define SWIFT_AST_REQUIREMENT_H
#include "swift/AST/LayoutConstraint.h"
#include "swift/AST/RequirementBase.h"
#include "swift/AST/Type.h"
#include "swift/Basic/Debug.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/ErrorHandling.h"
namespace swift {
/// A single requirement placed on the type parameters (or associated
/// types thereof) of a
class Requirement
: public RequirementBase<Type,
llvm::PointerIntPair<Type, 3, RequirementKind>,
LayoutConstraint> {
public:
/// Create a conformance or same-type requirement.
Requirement(RequirementKind kind, Type first, Type second)
: RequirementBase(kind, first, second) {}
/// Create a layout constraint requirement.
Requirement(RequirementKind kind, Type first, LayoutConstraint second)
: RequirementBase(kind, first, second) {}
/// Whether this requirement is in its canonical form.
bool isCanonical() const;
/// Get the canonical form of this requirement.
Requirement getCanonical() const;
/// Subst the types involved in this requirement.
///
/// The \c args arguments are passed through to Type::subst. This doesn't
/// touch the superclasses, protocols or layout constraints.
template <typename ...Args>
llvm::Optional<Requirement> subst(Args &&...args) const {
auto newFirst = getFirstType().subst(std::forward<Args>(args)...);
if (newFirst->hasError())
return None;
switch (getKind()) {
case RequirementKind::Conformance:
case RequirementKind::Superclass:
case RequirementKind::SameType: {
auto newSecond = getSecondType().subst(std::forward<Args>(args)...);
if (newSecond->hasError())
return None;
return Requirement(getKind(), newFirst, newSecond);
}
case RequirementKind::Layout:
return Requirement(getKind(), newFirst, getLayoutConstraint());
}
llvm_unreachable("Unhandled RequirementKind in switch.");
}
ProtocolDecl *getProtocolDecl() const;
/// Determines if this substituted requirement is satisfied.
///
/// \param conditionalRequirements An out parameter initialized to an
/// array of requirements that the caller must check to ensure this
/// requirement is completely satisfied.
bool isSatisfied(ArrayRef<Requirement> &conditionalRequirements,
bool allowMissing = false) const;
/// Determines if this substituted requirement can ever be satisfied,
/// possibly with additional substitutions.
///
/// For example, if 'T' is unconstrained, then a superclass requirement
/// 'T : C' can be satisfied; however, if 'T' already has an unrelated
/// superclass requirement, 'T : C' cannot be satisfied.
bool canBeSatisfied() const;
/// Linear order on requirements in a generic signature.
int compare(const Requirement &other) const;
SWIFT_DEBUG_DUMP;
void dump(raw_ostream &out) const;
void print(raw_ostream &os, const PrintOptions &opts) const;
void print(ASTPrinter &printer, const PrintOptions &opts) const;
};
inline void simple_display(llvm::raw_ostream &out, const Requirement &req) {
req.print(out, PrintOptions());
}
/// A requirement as written in source, together with a source location. See
/// ProtocolDecl::getStructuralRequirements().
struct StructuralRequirement {
/// The actual requirement, where the types were resolved with the
/// 'Structural' type resolution stage.
Requirement req;
/// The source location where the requirement is written, used for redundancy
/// and conflict diagnostics.
SourceLoc loc;
/// A flag indicating whether the requirement was inferred from the
/// application of a type constructor. Also used for diagnostics, because
/// an inferred requirement made redundant by an explicit requirement is not
/// diagnosed as redundant, since we want to give users the option of
/// spelling out these requirements explicitly.
bool inferred = false;
};
} // end namespace swift
#endif