Files
swift-mirror/include/swift/Sema/PreparedOverload.h
Slava Pestov a8d896ab8f Sema: Don't reuse PreparedOverload from normal type checking in salvage()
We want to re-prepare our overloads, since now they will contain fixes.
2025-10-10 15:44:12 -04:00

279 lines
8.1 KiB
C++

//===--- PreparedOverload.h - A Choice from an Overload Set ----*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2025 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
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SEMA_PREPAREDOVERLOAD_H
#define SWIFT_SEMA_PREPAREDOVERLOAD_H
#include "swift/AST/PropertyWrappers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/TrailingObjects.h"
namespace swift {
class ExistentialArchetypeType;
class GenericTypeParamType;
class TypeVariableType;
namespace constraints {
class ConstraintLocatorBuilder;
class ConstraintSystem;
/// Describes the type produced when referencing a declaration.
struct DeclReferenceType {
/// The "opened" type, which is the type of the declaration where any
/// generic parameters have been replaced with type variables.
///
/// The mapping from generic parameters to type variables will have been
/// recorded by \c recordOpenedTypes when this type is produced.
Type openedType;
/// The opened type, after performing contextual type adjustments such as
/// removing concurrency-related annotations for a `@preconcurrency`
/// operation.
Type adjustedOpenedType;
/// The type of the reference, based on the original opened type. This is the
/// type that the expression used to form the declaration reference would
/// have if no adjustments had been applied.
Type referenceType;
/// The type of the reference, which is the adjusted opened type after
/// (e.g.) applying the base of a member access. This is the type of the
/// expression used to form the declaration reference.
Type adjustedReferenceType;
/// The type that could be thrown by accessing this declaration.
Type thrownErrorTypeOnAccess;
};
/// Describes a dependent type that has been opened to a particular type
/// variable.
using OpenedType = std::pair<GenericTypeParamType *, TypeVariableType *>;
/// A change to be introduced into the constraint system when this
/// overload choice is chosen.
struct PreparedOverloadChange {
enum ChangeKind : unsigned {
/// A generic parameter was opened to a type variable.
AddedTypeVariable,
/// A generic requirement was opened to a constraint.
AddedConstraint,
/// Special case of a Bind constraint.
AddedBindConstraint,
/// A mapping of generic parameter types to type variables
/// was recorded.
OpenedTypes,
/// An existential type was opened.
OpenedExistentialType,
/// A pack expansion type was opened.
OpenedPackExpansionType,
/// A property wrapper was applied to a parameter.
AppliedPropertyWrapper,
/// A fix was recorded because a property wrapper application failed.
AddedFix,
/// The type of an AST node was changed.
RecordedNodeType
};
/// The kind of change.
ChangeKind Kind;
union {
/// For ChangeKind::AddedTypeVariable.
TypeVariableType *TypeVar;
/// For ChangeKind::AddedConstraint.
Constraint *TheConstraint;
/// For ChangeKind::AddedBindConstraint.
struct {
TypeBase *FirstType;
TypeBase *SecondType;
} Bind;
/// For ChangeKind::OpenedTypes.
struct {
const OpenedType *Data;
size_t Count;
} Replacements;
/// For ChangeKind::OpenedExistentialType.
ExistentialArchetypeType *TheExistential;
/// For ChangeKind::OpenedPackExpansionType.
struct {
PackExpansionType *TheExpansion;
TypeVariableType *TypeVar;
} PackExpansion;
/// For ChangeKind::AppliedPropertyWrapper.
struct {
TypeBase *WrapperType;
PropertyWrapperInitKind InitKind;
} PropertyWrapper;
/// For ChangeKind::Fix.
struct {
ConstraintFix *TheFix;
unsigned Impact;
} Fix;
/// For ChangeKind::RecordedNodeType.
struct {
ASTNode Node;
Type TheType;
} Node;
};
PreparedOverloadChange()
: Kind(ChangeKind::AddedTypeVariable),
TypeVar(nullptr) { }
};
/// A "pre-cooked" representation of all type variables and constraints
/// that are generated as part of an overload choice.
class PreparedOverload final :
public llvm::TrailingObjects<PreparedOverload, PreparedOverloadChange> {
public:
using Change = PreparedOverloadChange;
private:
Type OpenedType;
Type ThrownErrorType;
unsigned Count : 31;
/// A prepared overload for diagnostics is different than one without,
/// because of fixes and such.
unsigned ForDiagnostics : 1;
size_t numTrailingObjects(OverloadToken<Change>) const {
return Count;
}
public:
PreparedOverload(Type openedType, Type thrownErrorType,
ArrayRef<Change> changes, bool forDiagnostics)
: OpenedType(openedType), ThrownErrorType(thrownErrorType),
Count(changes.size()), ForDiagnostics(forDiagnostics) {
std::uninitialized_copy(changes.begin(), changes.end(),
getTrailingObjects());
}
Type getOpenedType() const {
return OpenedType;
}
Type getThrownErrorType() const {
return ThrownErrorType;
}
bool wasForDiagnostics() const {
return ForDiagnostics;
}
ArrayRef<Change> getChanges() const { return getTrailingObjects(Count); }
};
struct PreparedOverloadBuilder {
SmallVector<PreparedOverload::Change, 8> Changes;
ConstraintLocator *Locator;
PreparedOverloadBuilder(ConstraintLocator *locator)
: Locator(locator) {}
void addedTypeVariable(TypeVariableType *typeVar) {
PreparedOverload::Change change;
change.Kind = PreparedOverload::Change::AddedTypeVariable;
change.TypeVar = typeVar;
Changes.push_back(change);
}
void addedConstraint(Constraint *constraint) {
PreparedOverload::Change change;
change.Kind = PreparedOverload::Change::AddedConstraint;
change.TheConstraint = constraint;
Changes.push_back(change);
}
void addedBindConstraint(Type firstType, Type secondType) {
PreparedOverload::Change change;
change.Kind = PreparedOverload::Change::AddedBindConstraint;
change.Bind.FirstType = firstType.getPointer();
change.Bind.SecondType = secondType.getPointer();
Changes.push_back(change);
}
void openedTypes(ArrayRef<OpenedType> replacements) {
PreparedOverload::Change change;
change.Kind = PreparedOverload::Change::OpenedTypes;
change.Replacements.Data = replacements.data();
change.Replacements.Count = replacements.size();
Changes.push_back(change);
}
void openedExistentialType(ExistentialArchetypeType *openedExistential) {
PreparedOverload::Change change;
change.Kind = PreparedOverload::Change::OpenedExistentialType;
change.TheExistential = openedExistential;
Changes.push_back(change);
}
void openedPackExpansionType(PackExpansionType *packExpansion,
TypeVariableType *typeVar) {
PreparedOverload::Change change;
change.Kind = PreparedOverload::Change::OpenedPackExpansionType;
change.PackExpansion.TheExpansion = packExpansion;
change.PackExpansion.TypeVar = typeVar;
Changes.push_back(change);
}
void appliedPropertyWrapper(AppliedPropertyWrapper wrapper) {
PreparedOverload::Change change;
change.Kind = PreparedOverload::Change::AppliedPropertyWrapper;
change.PropertyWrapper.WrapperType = wrapper.wrapperType.getPointer();
change.PropertyWrapper.InitKind = wrapper.initKind;
Changes.push_back(change);
}
void addedFix(ConstraintFix *fix, unsigned impact) {
PreparedOverload::Change change;
change.Kind = PreparedOverload::Change::AddedFix;
change.Fix.TheFix = fix;
change.Fix.Impact = impact;
Changes.push_back(change);
}
void recordedNodeType(ASTNode node, Type type) {
PreparedOverload::Change change;
change.Kind = PreparedOverload::Change::RecordedNodeType;
change.Node.Node = node;
change.Node.TheType = type;
Changes.push_back(change);
}
};
} // end namespace constraints
} // end namespace swift
#endif