-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathOpenedExistentials.h
141 lines (116 loc) · 5.76 KB
/
OpenedExistentials.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//===--- OpenedExistentials.h - Utilities for existential types -*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2024 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_OPENED_EXISTENTIALS_H
#define SWIFT_OPENED_EXISTENTIALS_H
#include "swift/AST/Type.h"
#include "swift/Basic/OptionalEnum.h"
#include <optional>
namespace swift {
class CanGenericSignature;
class GenericTypeParamType;
/// Describes the least favorable positions at which a requirement refers
/// to a given generic parameter in terms of variance, for use in the
/// is-inheritable and is-available-existential checks.
class GenericParameterReferenceInfo final {
using OptionalTypePosition = OptionalEnum<decltype(TypePosition::Covariant)>;
public:
/// Whether the uncurried interface type of the declaration, stripped of any
/// optionality, is a direct reference to the generic parameter at hand. For
/// example, "func foo(x: Int) -> () -> Self?" has a covariant 'Self' result.
bool hasCovariantSelfResult;
OptionalTypePosition selfRef;
OptionalTypePosition assocTypeRef;
/// A reference to 'Self'.
static GenericParameterReferenceInfo forSelfRef(TypePosition position) {
return GenericParameterReferenceInfo(false, position, std::nullopt);
}
/// A reference to the generic parameter in covariant result position.
static GenericParameterReferenceInfo forCovariantResult() {
return GenericParameterReferenceInfo(true, TypePosition::Covariant,
std::nullopt);
}
/// A reference to 'Self' through an associated type.
static GenericParameterReferenceInfo forAssocTypeRef(TypePosition position) {
return GenericParameterReferenceInfo(false, std::nullopt, position);
}
GenericParameterReferenceInfo &operator|=(const GenericParameterReferenceInfo &other);
explicit operator bool() const {
return hasCovariantSelfResult || selfRef || assocTypeRef;
}
GenericParameterReferenceInfo()
: hasCovariantSelfResult(false), selfRef(std::nullopt),
assocTypeRef(std::nullopt) {}
private:
GenericParameterReferenceInfo(bool hasCovariantSelfResult, OptionalTypePosition selfRef,
OptionalTypePosition assocTypeRef)
: hasCovariantSelfResult(hasCovariantSelfResult), selfRef(selfRef),
assocTypeRef(assocTypeRef) {}
};
/// Find references to the given generic parameter in the type signature of the
/// given declaration using the given generic signature.
///
/// \param skipParamIndex If the value is a function or subscript declaration,
/// specifies the index of the parameter that shall be skipped.
GenericParameterReferenceInfo
findGenericParameterReferences(const ValueDecl *value, CanGenericSignature sig,
GenericTypeParamType *origParam,
GenericTypeParamType *openedParam,
std::optional<unsigned> skipParamIndex);
/// Find references to 'Self' in the type signature of this declaration.
GenericParameterReferenceInfo findExistentialSelfReferences(const ValueDecl *value);
/// Determine whether referencing the given member on the
/// given existential base type is supported. This is the case only if the
/// type of the member, spelled in the context of \p baseTy, does not contain
/// 'Self' or 'Self'-rooted dependent member types in non-covariant position.
bool isMemberAvailableOnExistential(Type baseTy,
const ValueDecl *member);
/// Flags that should be applied to the existential argument type after
/// opening.
enum class OpenedExistentialAdjustmentFlags {
/// The argument should be made inout after opening.
InOut = 0x01,
LValue = 0x02,
};
using OpenedExistentialAdjustments =
OptionSet<OpenedExistentialAdjustmentFlags>;
/// Determine whether we should open up the existential argument to the
/// given parameters.
///
/// \param callee The function or subscript being called.
/// \param paramIdx The index specifying which function parameter is being
/// initialized.
/// \param paramTy The type of the parameter as it was opened in the constraint
/// system.
/// \param argTy The type of the argument.
///
/// \returns If the argument type is existential and opening it can bind a
/// generic parameter in the callee, returns the generic parameter, type
/// variable (from the opened parameter type) the existential type that needs
/// to be opened (from the argument type), and the adjustments that need to be
/// applied to the existential type after it is opened.
std::optional<std::tuple<GenericTypeParamType *, TypeVariableType *,
Type, OpenedExistentialAdjustments>>
canOpenExistentialCallArgument(ValueDecl *callee, unsigned paramIdx,
Type paramTy, Type argTy);
/// Given a type that includes an existential type that has been opened to
/// the given type variable, replace the opened type variable and its member
/// types with their upper bounds.
Type typeEraseOpenedExistentialReference(Type type, Type existentialBaseType,
TypeVariableType *openedTypeVar,
TypePosition outermostPosition);
/// Given a type that includes opened existential archetypes derived from
/// the given generic environment, replace the archetypes with their upper
/// bounds.
Type typeEraseOpenedArchetypesFromEnvironment(Type type,
GenericEnvironment *env);
} // end namespace swift
#endif