Files
swift-mirror/lib/AST/RequirementMachine/PropertyMap.h

239 lines
7.0 KiB
C++

//===--- PropertyMap.h - Properties of type parameter terms 0000-*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2021 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
//
//===----------------------------------------------------------------------===//
//
// A description of this data structure and its purpose can be found in
// PropertyMap.cpp.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_PROPERTYMAP_H
#define SWIFT_PROPERTYMAP_H
#include "swift/AST/LayoutConstraint.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/TinyPtrVector.h"
#include <algorithm>
#include <vector>
#include "Debug.h"
#include "RewriteContext.h"
#include "RewriteSystem.h"
namespace llvm {
class raw_ostream;
}
namespace swift {
class ProtocolDecl;
enum class RequirementKind : unsigned;
namespace rewriting {
class MutableTerm;
class Term;
/// A new rule introduced during property map construction, as a result of
/// unifying two property symbols that apply to the same common suffix term.
struct InducedRule {
MutableTerm LHS;
MutableTerm RHS;
RewritePath Path;
InducedRule(MutableTerm LHS, MutableTerm RHS, RewritePath Path)
: LHS(LHS), RHS(RHS), Path(Path) {}
// FIXME: Eventually all induced rules will have a rewrite path.
InducedRule(MutableTerm LHS, MutableTerm RHS)
: LHS(LHS), RHS(RHS) {}
};
/// Stores a convenient representation of all "property-like" rewrite rules of
/// the form T.[p] => T, where [p] is a property symbol, for some term 'T'.
class PropertyBag {
friend class PropertyMap;
/// The fully reduced term whose properties are recorded in this property bag.
Term Key;
/// All protocols this type conforms to.
llvm::TinyPtrVector<const ProtocolDecl *> ConformsTo;
/// The corresponding protocol conformance rules.
llvm::SmallVector<unsigned, 1> ConformsToRules;
/// The most specific layout constraint this type satisfies.
LayoutConstraint Layout;
/// The corresponding layout rule for the above.
Optional<unsigned> LayoutRule;
/// The most specific superclass constraint this type satisfies.
Optional<Symbol> Superclass;
/// The corresponding superclass rule for the above.
Optional<unsigned> SuperclassRule;
/// All concrete conformances of Superclass to the protocols in the
/// ConformsTo list.
llvm::TinyPtrVector<ProtocolConformance *> SuperclassConformances;
/// The most specific concrete type constraint this type satisfies.
Optional<Symbol> ConcreteType;
/// The corresponding layout rule for the above.
Optional<unsigned> ConcreteTypeRule;
/// All concrete conformances of ConcreteType to the protocols in the
/// ConformsTo list.
llvm::TinyPtrVector<ProtocolConformance *> ConcreteConformances;
explicit PropertyBag(Term key) : Key(key) {}
void addProperty(Symbol property,
unsigned ruleID,
RewriteContext &ctx,
SmallVectorImpl<InducedRule> &inducedRules,
bool debug);
void copyPropertiesFrom(const PropertyBag *next,
RewriteContext &ctx);
PropertyBag(const PropertyBag &) = delete;
PropertyBag(PropertyBag &&) = delete;
PropertyBag &operator=(const PropertyBag &) = delete;
PropertyBag &operator=(PropertyBag &&) = delete;
public:
Term getKey() const { return Key; }
void dump(llvm::raw_ostream &out) const;
bool hasSuperclassBound() const {
return Superclass.hasValue();
}
Type getSuperclassBound() const {
return Superclass->getSuperclass();
}
Type getSuperclassBound(
TypeArrayView<GenericTypeParamType> genericParams,
const MutableTerm &lookupTerm,
RewriteContext &ctx) const;
bool isConcreteType() const {
return ConcreteType.hasValue();
}
Type getConcreteType() const {
return ConcreteType->getConcreteType();
}
Type getConcreteType(
TypeArrayView<GenericTypeParamType> genericParams,
const MutableTerm &lookupTerm,
RewriteContext &ctx) const;
LayoutConstraint getLayoutConstraint() const {
return Layout;
}
ArrayRef<const ProtocolDecl *> getConformsTo() const {
return ConformsTo;
}
llvm::TinyPtrVector<const ProtocolDecl *>
getConformsToExcludingSuperclassConformances() const;
MutableTerm getPrefixAfterStrippingKey(const MutableTerm &lookupTerm) const;
void verify(const RewriteSystem &system) const;
};
/// Stores all rewrite rules of the form T.[p] => T, where [p] is a property
/// symbol, for all terms 'T'.
///
/// Out-of-line methods are documented in PropertyMap.cpp.
class PropertyMap {
RewriteContext &Context;
RewriteSystem &System;
std::vector<PropertyBag *> Entries;
Trie<PropertyBag *, MatchKind::Longest> Trie;
using ConcreteTypeInDomain = std::pair<CanType, ArrayRef<const ProtocolDecl *>>;
llvm::DenseMap<ConcreteTypeInDomain, Term> ConcreteTypeInDomainMap;
llvm::DenseSet<std::pair<unsigned, unsigned>> ConcreteConformanceRules;
DebugOptions Debug;
PropertyBag *getOrCreateProperties(Term key);
PropertyMap(const PropertyMap &) = delete;
PropertyMap(PropertyMap &&) = delete;
PropertyMap &operator=(const PropertyMap &) = delete;
PropertyMap &operator=(PropertyMap &&) = delete;
public:
explicit PropertyMap(RewriteSystem &system)
: Context(system.getRewriteContext()),
System(system) {
Debug = Context.getDebugOptions();
}
~PropertyMap();
PropertyBag *lookUpProperties(const MutableTerm &key) const;
std::pair<CompletionResult, unsigned>
buildPropertyMap(unsigned maxIterations,
unsigned maxDepth);
void dump(llvm::raw_ostream &out) const;
private:
void clear();
void addProperty(Term key, Symbol property, unsigned ruleID,
SmallVectorImpl<InducedRule> &inducedRules);
void computeConcreteTypeInDomainMap();
void concretizeNestedTypesFromConcreteParents(
SmallVectorImpl<InducedRule> &inducedRules) const;
void concretizeNestedTypesFromConcreteParent(
Term key, RequirementKind requirementKind,
CanType concreteType, ArrayRef<Term> substitutions,
ArrayRef<const ProtocolDecl *> conformsTo,
llvm::TinyPtrVector<ProtocolConformance *> &conformances,
SmallVectorImpl<InducedRule> &inducedRules) const;
MutableTerm computeConstraintTermForTypeWitness(
Term key, CanType concreteType, CanType typeWitness,
const MutableTerm &subjectType, ArrayRef<Term> substitutions) const;
void recordConcreteConformanceRules(
SmallVectorImpl<InducedRule> &inducedRules);
void recordConcreteConformanceRule(
unsigned concreteRuleID,
unsigned conformanceRuleID,
const ProtocolDecl *proto,
SmallVectorImpl<InducedRule> &inducedRules);
void verify() const;
};
} // end namespace rewriting
} // end namespace swift
#endif