mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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.
130 lines
4.6 KiB
C++
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
|