Skip to content

Commit d52f7d1

Browse files
committed
AST/SIL: Refactor and simplify AST.Type, AST.CanonicalType and SIL.Type
* let `SIL.Type` conform to `TypeProperties` to share the implementation of common type properties between the AST types and `SIL.Type` * call references to an `AST.Type` `rawType` (instead of just `type`) * remove unneeded stuff * add comments
1 parent 76a1742 commit d52f7d1

File tree

17 files changed

+293
-330
lines changed

17 files changed

+293
-330
lines changed

SwiftCompilerSources/Sources/AST/Type.swift

Lines changed: 115 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ public struct Type: TypeProperties, CustomStringConvertible, NoReflectionChildre
3030

3131
public let bridged: BridgedASTType
3232

33-
public var type: Type { self }
33+
// Needed to conform to TypeProperties
34+
public var rawType: Type { self }
3435

3536
public init?(bridgedOrNil: BridgedASTType) {
3637
if bridgedOrNil.type == nil {
@@ -47,6 +48,17 @@ public struct Type: TypeProperties, CustomStringConvertible, NoReflectionChildre
4748

4849
public var instanceTypeOfMetatype: Type { Type(bridged: bridged.getInstanceTypeOfMetatype()) }
4950

51+
public var superClassType: Type? {
52+
precondition(isClass)
53+
let bridgedSuperClassTy = bridged.getSuperClassType()
54+
if bridgedSuperClassTy.type != nil {
55+
return Type(bridged: bridgedSuperClassTy)
56+
}
57+
return nil
58+
}
59+
60+
public var builtinVectorElementType: Type { Type(bridged: bridged.getBuiltinVectorElementType()) }
61+
5062
public func subst(with substitutionMap: SubstitutionMap) -> Type {
5163
return Type(bridged: bridged.subst(substitutionMap.bridged))
5264
}
@@ -63,49 +75,123 @@ public struct CanonicalType: TypeProperties, CustomStringConvertible, NoReflecti
6375

6476
public init(bridged: BridgedCanType) { self.bridged = bridged }
6577

66-
public var type: Type { Type(bridged: bridged.getType()) }
78+
public var rawType: Type { Type(bridged: bridged.getRawType()) }
79+
80+
public var instanceTypeOfMetatype: CanonicalType { rawType.instanceTypeOfMetatype.canonical }
81+
82+
public var superClassType: CanonicalType? { rawType.superClassType?.canonical }
83+
84+
public var builtinVectorElementType: CanonicalType { rawType.builtinVectorElementType.canonical }
6785

68-
public var instanceTypeOfMetatype: CanonicalType { type.instanceTypeOfMetatype.canonical }
69-
7086
public func subst(with substitutionMap: SubstitutionMap) -> CanonicalType {
71-
return type.subst(with: substitutionMap).canonical
87+
return rawType.subst(with: substitutionMap).canonical
7288
}
7389

7490
public func subst(type: CanonicalType, with targetType: CanonicalType) -> CanonicalType {
75-
return self.type.subst(type: type.type, with: targetType.type).canonical
91+
return self.rawType.subst(type: type.rawType, with: targetType.rawType).canonical
7692
}
7793
}
7894

79-
/// Contains common properties of AST.Type and AST.CanonicalType
95+
/// Implements the common members of `AST.Type`, `AST.CanonicalType` and `SIL.Type`.
8096
public protocol TypeProperties {
81-
var type: Type { get }
97+
var rawType: Type { get }
8298
}
8399

84100
extension TypeProperties {
85-
public var description: String { String(taking: type.bridged.getDebugDescription()) }
86-
87-
public var isLegalFormalType: Bool { type.bridged.isLegalFormalType() }
88-
public var hasTypeParameter: Bool { type.bridged.hasTypeParameter() }
89-
public var hasLocalArchetype: Bool { type.bridged.hasLocalArchetype() }
90-
public var isExistentialArchetype: Bool { type.bridged.isExistentialArchetype() }
91-
public var isExistentialArchetypeWithError: Bool { type.bridged.isExistentialArchetypeWithError() }
92-
public var isExistential: Bool { type.bridged.isExistential() }
93-
public var isEscapable: Bool { type.bridged.isEscapable() }
94-
public var isNoEscape: Bool { type.bridged.isNoEscape() }
95-
public var isInteger: Bool { type.bridged.isInteger() }
96-
public var isOptional: Bool { type.bridged.isOptional() }
97-
public var isMetatypeType: Bool { type.bridged.isMetatypeType() }
98-
public var isExistentialMetatypeType: Bool { type.bridged.isExistentialMetatypeType() }
101+
public var description: String { String(taking: rawType.bridged.getDebugDescription()) }
102+
103+
//===--------------------------------------------------------------------===//
104+
// Checks for different kinds of types
105+
//===--------------------------------------------------------------------===//
106+
107+
public var isBuiltinInteger: Bool { rawType.bridged.isBuiltinInteger() }
108+
109+
public func isBuiltinInteger(withFixedWidth width: Int) -> Bool {
110+
rawType.bridged.isBuiltinFixedWidthInteger(width)
111+
}
112+
113+
public var isBuiltinFloat: Bool { rawType.bridged.isBuiltinFloat() }
114+
public var isBuiltinVector: Bool { rawType.bridged.isBuiltinVector() }
115+
116+
public var isClass: Bool {
117+
if let nominal = nominal, nominal is ClassDecl {
118+
return true
119+
}
120+
return false
121+
}
122+
123+
public var isStruct: Bool {
124+
if let nominal = nominal, nominal is StructDecl {
125+
return true
126+
}
127+
return false
128+
}
129+
130+
public var isEnum: Bool {
131+
if let nominal = nominal, nominal is EnumDecl {
132+
return true
133+
}
134+
return false
135+
}
136+
137+
public var isTuple: Bool { rawType.bridged.isTuple() }
138+
public var isFunction: Bool { rawType.bridged.isFunction() }
139+
public var isExistentialArchetype: Bool { rawType.bridged.isExistentialArchetype() }
140+
public var isExistentialArchetypeWithError: Bool { rawType.bridged.isExistentialArchetypeWithError() }
141+
public var isExistential: Bool { rawType.bridged.isExistential() }
142+
public var isClassExistential: Bool { rawType.bridged.isClassExistential() }
143+
public var isUnownedStorageType: Bool { return rawType.bridged.isUnownedStorageType() }
144+
public var isMetatype: Bool { rawType.bridged.isMetatypeType() }
145+
public var isExistentialMetatype: Bool { rawType.bridged.isExistentialMetatypeType() }
146+
public var isDynamicSelf: Bool { rawType.bridged.isDynamicSelf()}
147+
148+
/// True if this is the type which represents an integer literal used in a type position.
149+
/// For example `N` in `struct T<let N: Int> {}`
150+
public var isInteger: Bool { rawType.bridged.isInteger() }
151+
152+
public var canBeClass: Type.TraitResult { rawType.bridged.canBeClass().result }
153+
154+
/// True if this the nominal type `Swift.Optional`.
155+
public var isOptional: Bool { rawType.bridged.isOptional() }
156+
157+
/// True if this type is a value type (struct/enum) that defines a `deinit`.
158+
public var isValueTypeWithDeinit: Bool {
159+
if let nominal = nominal, nominal.valueTypeDestructor != nil {
160+
return true
161+
}
162+
return false
163+
}
164+
165+
//===--------------------------------------------------------------------===//
166+
// Type properties
167+
//===--------------------------------------------------------------------===//
168+
169+
public var isLegalFormalType: Bool { rawType.bridged.isLegalFormalType() }
170+
public var hasArchetype: Bool { rawType.bridged.hasArchetype() }
171+
public var hasTypeParameter: Bool { rawType.bridged.hasTypeParameter() }
172+
public var hasLocalArchetype: Bool { rawType.bridged.hasLocalArchetype() }
173+
public var isEscapable: Bool { rawType.bridged.isEscapable() }
174+
public var isNoEscape: Bool { rawType.bridged.isNoEscape() }
175+
99176
public var representationOfMetatype: AST.`Type`.MetatypeRepresentation {
100-
type.bridged.getRepresentationOfMetatype().representation
177+
rawType.bridged.getRepresentationOfMetatype().representation
101178
}
102-
public var invocationGenericSignatureOfFunctionType: GenericSignature {
103-
GenericSignature(bridged: type.bridged.getInvocationGenericSignatureOfFunctionType())
179+
180+
/// Assumes this is a nominal type. Returns a substitution map that sends each
181+
/// generic parameter of the declaration's generic signature to the corresponding
182+
/// generic argument of this nominal type.
183+
///
184+
/// Eg: Array<Int> ---> { Element := Int }
185+
public var contextSubstitutionMap: SubstitutionMap {
186+
SubstitutionMap(bridged: rawType.bridged.getContextSubstitutionMap())
104187
}
105188

106-
public var canBeClass: Type.TraitResult { type.bridged.canBeClass().result }
189+
// True if this type has generic parameters or it is in a context (e.g. an outer type) which has generic parameters.
190+
public var isGenericAtAnyLevel: Bool { rawType.bridged.isGenericAtAnyLevel() }
107191

108-
public var anyNominal: NominalTypeDecl? { type.bridged.getAnyNominal().getAs(NominalTypeDecl.self) }
192+
public var nominal: NominalTypeDecl? {
193+
rawType.bridged.getNominalOrBoundGenericNominal().getAs(NominalTypeDecl.self)
194+
}
109195

110196
/// Performas a global conformance lookup for this type for `protocol`.
111197
/// It checks conditional requirements.
@@ -118,7 +204,7 @@ extension TypeProperties {
118204
/// Returns an invalid conformance if the search failed, otherwise an
119205
/// abstract, concrete or pack conformance, depending on the lookup type.
120206
public func checkConformance(to protocol: ProtocolDecl) -> Conformance {
121-
return Conformance(bridged: type.bridged.checkConformance(`protocol`.bridged))
207+
return Conformance(bridged: rawType.bridged.checkConformance(`protocol`.bridged))
122208
}
123209
}
124210

@@ -174,6 +260,6 @@ extension Type: Equatable {
174260

175261
extension CanonicalType: Equatable {
176262
public static func ==(lhs: CanonicalType, rhs: CanonicalType) -> Bool {
177-
lhs.type == rhs.type
263+
lhs.rawType == rhs.rawType
178264
}
179265
}

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/ClosureSpecialization.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,7 @@ private extension PartialApplyInst {
11271127
if self.numArguments == 1,
11281128
let fun = self.referencedFunction,
11291129
fun.thunkKind == .reabstractionThunk || fun.thunkKind == .thunk,
1130-
self.arguments[0].type.isFunction,
1130+
self.arguments[0].type.isLoweredFunction,
11311131
self.arguments[0].type.isReferenceCounted(in: self.parentFunction) || self.callee.type.isThickFunction
11321132
{
11331133
return true

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyAllocStack.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ private extension AllocStackInst {
179179
/// use %3
180180
/// ```
181181
func optimizeExistential(_ context: SimplifyContext) -> Bool {
182-
guard type.astType.isExistential || type.astType.isExistentialArchetype,
182+
guard type.isExistential || type.isExistentialArchetype,
183183
let concreteFormalType = getConcreteTypeOfExistential()
184184
else {
185185
return false
@@ -266,7 +266,7 @@ private extension AllocStackInst {
266266
}
267267
let concreteType: CanonicalType
268268
if let initExistential {
269-
assert(self.type.astType.isExistential)
269+
assert(self.type.isExistential)
270270
if let cft = initExistential.concreteTypeOfDependentExistentialArchetype {
271271
// Case 1: We will replace the alloc_stack of an existential with the concrete type.
272272
// `alloc_stack $any P` -> `alloc_stack $ConcreteType`
@@ -281,9 +281,9 @@ private extension AllocStackInst {
281281
}
282282
// Case 2: We will replace the alloc_stack of an existential with the existential archetype.
283283
// `alloc_stack $any P` -> `alloc_stack $@opened("...")`
284-
concreteType = initExistential.type.astType
284+
concreteType = initExistential.type.canonicalType
285285
}
286-
} else if self.type.astType.isExistentialArchetype, let cft = self.concreteTypeOfDependentExistentialArchetype {
286+
} else if self.type.isExistentialArchetype, let cft = self.concreteTypeOfDependentExistentialArchetype {
287287
// Case 3: We will replace the alloc_stack of an existential archetype with the concrete type:
288288
// `alloc_stack $@opened("...")` -> `alloc_stack $ConcreteType`
289289
concreteType = cft

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -143,22 +143,22 @@ private extension FullApplySite {
143143
// Note that an opened existential value is address only, so it cannot be a direct result anyway
144144
// (but it can be once we have opaque values).
145145
// Also don't support things like direct `Array<@opened("...")>` return values.
146-
if let singleDirectResult, singleDirectResult.type.astType.hasLocalArchetype {
146+
if let singleDirectResult, singleDirectResult.type.hasLocalArchetype {
147147
return false
148148
}
149-
if let singleDirectErrorResult, singleDirectErrorResult.type.astType.hasLocalArchetype {
149+
if let singleDirectErrorResult, singleDirectErrorResult.type.hasLocalArchetype {
150150
return false
151151
}
152152

153153
return arguments.allSatisfy { value in
154-
let astTy = value.type.astType
154+
let type = value.type
155155
// Allow three cases:
156156
// case 1. the argument _is_ the existential archetype
157-
return astTy.isExistentialArchetype ||
157+
return type.isExistentialArchetype ||
158158
// case 2. the argument _is_ a metatype of the existential archetype
159-
(astTy.isMetatypeType && astTy.instanceTypeOfMetatype.isExistentialArchetype) ||
159+
(type.isMetatype && type.canonicalType.instanceTypeOfMetatype.isExistentialArchetype) ||
160160
// case 3. the argument has nothing to do with the existential archetype (or any other local archetype)
161-
!astTy.hasLocalArchetype
161+
!type.hasLocalArchetype
162162
}
163163
}
164164

@@ -167,19 +167,18 @@ private extension FullApplySite {
167167
_ context: SimplifyContext
168168
) -> [Value] {
169169
let newArgs = arguments.map { (arg) -> Value in
170-
let argTy = arg.type.astType
171-
if argTy.isExistentialArchetype {
170+
if arg.type.isExistentialArchetype {
172171
// case 1. the argument _is_ the existential archetype:
173172
// just insert an address cast to satisfy type equivalence.
174173
let builder = Builder(before: self, context)
175174
let concreteSILType = concreteType.loweredType(in: self.parentFunction)
176175
return builder.createUncheckedAddrCast(from: arg, to: concreteSILType.addressType)
177176
}
178-
if argTy.isMetatypeType, argTy.instanceTypeOfMetatype.isExistentialArchetype {
177+
if arg.type.isMetatype, arg.type.canonicalType.instanceTypeOfMetatype.isExistentialArchetype {
179178
// case 2. the argument _is_ a metatype of the existential archetype:
180179
// re-create the metatype with the concrete type.
181180
let builder = Builder(before: self, context)
182-
return builder.createMetatype(ofInstanceType: concreteType, representation: argTy.representationOfMetatype)
181+
return builder.createMetatype(ofInstanceType: concreteType, representation: arg.type.representationOfMetatype)
183182
}
184183
// case 3. the argument has nothing to do with the existential archetype (or any other local archetype)
185184
return arg
@@ -194,9 +193,9 @@ private extension FullApplySite {
194193
let openedArcheType = substitutionMap.replacementTypes.first(where: { $0.isExistentialArchetype })!
195194

196195
let newReplacementTypes = substitutionMap.replacementTypes.map {
197-
return $0 == openedArcheType ? concreteType.type : $0
196+
return $0 == openedArcheType ? concreteType.rawType : $0
198197
}
199-
let genSig = callee.type.astType.invocationGenericSignatureOfFunctionType
198+
let genSig = callee.type.invocationGenericSignatureOfFunction
200199
return SubstitutionMap(genericSignature: genSig, replacementTypes: newReplacementTypes)
201200
}
202201
}

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,12 +193,12 @@ private extension BuiltinInst {
193193
return
194194
}
195195

196-
guard type.astType.representationOfMetatype == .thick else {
196+
guard type.representationOfMetatype == .thick else {
197197
return
198198
}
199199

200200
let builder = Builder(before: self, context)
201-
let newMetatype = builder.createMetatype(ofInstanceType: type.astType.instanceTypeOfMetatype,
201+
let newMetatype = builder.createMetatype(ofInstanceType: type.canonicalType.instanceTypeOfMetatype,
202202
representation: .thin)
203203
operands[argument].set(to: newMetatype, context)
204204
}
@@ -271,11 +271,11 @@ private func typesOfValuesAreEqual(_ lhs: Value, _ rhs: Value, in function: Func
271271

272272
let lhsMetatype = lhsExistential.metatype.type
273273
let rhsMetatype = rhsExistential.metatype.type
274-
if lhsMetatype.isDynamicSelfMetatype != rhsMetatype.isDynamicSelfMetatype {
275-
return nil
276-
}
277274
let lhsTy = lhsMetatype.loweredInstanceTypeOfMetatype(in: function)
278275
let rhsTy = rhsMetatype.loweredInstanceTypeOfMetatype(in: function)
276+
if lhsTy.isDynamicSelf != rhsTy.isDynamicSelf {
277+
return nil
278+
}
279279

280280
// Do we know the exact types? This is not the case e.g. if a type is passed as metatype
281281
// to the function.

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyCheckedCast.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,12 @@ private extension UnconditionalCheckedCastInst {
7070
// Note that init_existential_metatype is better than unconditional_checked_cast because it does not need
7171
// to do any runtime casting.
7272
func tryOptimizeCastToExistentialMetatype(_ context: SimplifyContext) {
73-
guard targetFormalType.isExistentialMetatypeType,
74-
sourceFormalType.isMetatypeType,
75-
!sourceFormalType.isExistentialMetatypeType
76-
else {
73+
guard targetFormalType.isExistentialMetatype, sourceFormalType.isMetatype else {
7774
return
7875
}
7976

8077
let instanceTy = targetFormalType.instanceTypeOfMetatype
81-
guard let nominal = instanceTy.anyNominal,
78+
guard let nominal = instanceTy.nominal,
8279
let proto = nominal as? ProtocolDecl
8380
else {
8481
return

SwiftCompilerSources/Sources/Optimizer/Utilities/FunctionSignatureTransforms.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ private func removeMetatypArguments(in specializedFunction: Function, _ context:
148148
if funcArg.type.isRemovableMetatype(in: specializedFunction) {
149149
// Rematerialize the metatype value in the entry block.
150150
let builder = Builder(atBeginOf: entryBlock, context)
151-
let instanceType = funcArg.type.astType.instanceTypeOfMetatype
151+
let instanceType = funcArg.type.canonicalType.instanceTypeOfMetatype
152152
let metatype = builder.createMetatype(ofInstanceType: instanceType, representation: .thick)
153153
funcArg.uses.replaceAll(with: metatype, context)
154154
entryBlock.eraseArgument(at: funcArgIdx, context)
@@ -232,7 +232,7 @@ private func replace(apply: FullApplySite, to specializedCallee: Function, _ con
232232
private extension Type {
233233
func isRemovableMetatype(in function: Function) -> Bool {
234234
if isMetatype {
235-
if astType.representationOfMetatype == .thick {
235+
if representationOfMetatype == .thick {
236236
let instanceTy = loweredInstanceTypeOfMetatype(in: function)
237237
// For structs and enums we know the metatype statically.
238238
return instanceTy.isStruct || instanceTy.isEnum

SwiftCompilerSources/Sources/Optimizer/Utilities/GenericSpecialization.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ func specializeWitnessTable(forConformance conformance: Conformance,
145145
let substType = witness.subst(with: conformance.specializedSubstitutions)
146146
return .associatedType(requirement: requirement, witness: substType)
147147
case .associatedConformance(let requirement, let proto, _):
148-
let concreteAssociateConf = conformance.getAssociatedConformance(ofAssociatedType: requirement.type, to: proto)
148+
let concreteAssociateConf = conformance.getAssociatedConformance(ofAssociatedType: requirement.rawType, to: proto)
149149
if concreteAssociateConf.isSpecialized {
150150
specializeWitnessTable(forConformance: concreteAssociateConf,
151151
errorLocation: errorLocation,

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ extension Instruction {
478478
let iemt = oemt.operand.value as? InitExistentialMetatypeInst,
479479
let mt = iemt.metatype as? MetatypeInst
480480
{
481-
return mt.type.astType.instanceTypeOfMetatype
481+
return mt.type.canonicalType.instanceTypeOfMetatype
482482
}
483483
// TODO: also handle open_existential_addr and open_existential_ref.
484484
// Those cases are currently handled in SILCombine's `propagateConcreteTypeOfInitExistential`.

0 commit comments

Comments
 (0)