diff --git a/CHANGELOG.md b/CHANGELOG.md index 196afd7ff270c..e5ddaa96c3bfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG | Contents | | :--------------------- | +| [Swift 4.0](#swift-40) | | [Swift 3.1](#swift-31) | | [Swift 3.0](#swift-30) | | [Swift 2.2](#swift-22) | @@ -17,6 +18,28 @@ CHANGELOG +Swift 4.0 +--------- + +* [SE-0148][]: + + Subscript declarations can now be defined to have generic parameter lists. + Example: + + ``` + extension JSON { + subscript(key: String) -> T? + where T : JSONConvertible { + // ... + } + } + ``` + +* [SE-0110][]: + + In Swift 4 mode, Swift's type system properly distinguishes between functions that + take one tuple argument, and functions that take multiple arguments. + * More types of C macros which define integer constants are supported by the importer. Specifically the `+, -, *, /, ^, >>, ==, <, <=, >, >=` operators are now recognized, and the previously-supported `<<, &&, ||, &, |` diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h index 6c2f7845458a0..e97e6cf35f7a6 100644 --- a/include/swift/SIL/TypeLowering.h +++ b/include/swift/SIL/TypeLowering.h @@ -622,7 +622,8 @@ class TypeConverter { CanSILFunctionType getMaterializeForSetCallbackType(AbstractStorageDecl *storage, CanGenericSignature genericSig, - Type selfType); + Type selfType, + SILFunctionTypeRepresentation rep); /// Return the SILFunctionType for a native function value of the /// given type. diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp index 0687e7b20b409..6ac7b44f5e256 100644 --- a/lib/IRGen/IRGenSIL.cpp +++ b/lib/IRGen/IRGenSIL.cpp @@ -1887,14 +1887,11 @@ static llvm::Value *emitWitnessTableForLoweredCallee(IRGenSILFunction &IGF, // // We recover the witness table from the substitution that was used to // produce the substituted callee type. - // - // There can be multiple substitutions, but the first one is the Self type. - assert(subs.size() >= 1); - assert(subs[0].getConformances().size() == 1); - - auto conformance = subs[0].getConformances()[0]; - assert(conformance.getRequirement() == proto); (void) proto; - auto substSelfType = subs[0].getReplacement()->getCanonicalType(); + auto subMap = origCalleeType->getGenericSignature() + ->getSubstitutionMap(subs); + auto origSelfType = proto->getSelfInterfaceType()->getCanonicalType(); + auto substSelfType = origSelfType.subst(subMap)->getCanonicalType(); + auto conformance = *subMap.lookupConformance(origSelfType, proto); llvm::Value *argMetadata = IGF.emitTypeMetadataRef(substSelfType); wtable = emitWitnessTableRef(IGF, substSelfType, &argMetadata, diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp index dfd06f9532a29..4ec33cf5778f9 100644 --- a/lib/SIL/SILVerifier.cpp +++ b/lib/SIL/SILVerifier.cpp @@ -2876,8 +2876,12 @@ class SILVerifier : public SILVerifierBase { requireObjectType(BuiltinRawPointerType, CI, "thin_function_to_pointer result"); - require(opTI->getRepresentation() == SILFunctionType::Representation::Thin, - "thin_function_to_pointer only works on thin functions"); + auto rep = opTI->getRepresentation(); + require(rep == SILFunctionTypeRepresentation::Thin || + rep == SILFunctionTypeRepresentation::Method || + rep == SILFunctionTypeRepresentation::WitnessMethod, + "thin_function_to_pointer only works on thin, method or " + "witness_method functions"); } void checkPointerToThinFunctionInst(PointerToThinFunctionInst *CI) { @@ -2886,8 +2890,12 @@ class SILVerifier : public SILVerifierBase { requireObjectType(BuiltinRawPointerType, CI->getOperand(), "pointer_to_thin_function operand"); - require(resultTI->getRepresentation() == SILFunctionType::Representation::Thin, - "pointer_to_thin_function only works on thin functions"); + auto rep = resultTI->getRepresentation(); + require(rep == SILFunctionTypeRepresentation::Thin || + rep == SILFunctionTypeRepresentation::Method || + rep == SILFunctionTypeRepresentation::WitnessMethod, + "pointer_to_thin_function only works on thin, method or " + "witness_method functions"); } void checkCondFailInst(CondFailInst *CFI) { diff --git a/lib/SIL/TypeLowering.cpp b/lib/SIL/TypeLowering.cpp index 01dd21ba1a232..1bda39f4a6e22 100644 --- a/lib/SIL/TypeLowering.cpp +++ b/lib/SIL/TypeLowering.cpp @@ -2130,7 +2130,8 @@ TypeConverter::getProtocolDispatchStrategy(ProtocolDecl *P) { CanSILFunctionType TypeConverter:: getMaterializeForSetCallbackType(AbstractStorageDecl *storage, CanGenericSignature genericSig, - Type selfType) { + Type selfType, + SILFunctionTypeRepresentation rep) { auto &ctx = M.getASTContext(); // Get lowered formal types for callback parameters. @@ -2168,9 +2169,8 @@ getMaterializeForSetCallbackType(AbstractStorageDecl *storage, { canSelfMetatypeType, ParameterConvention::Direct_Unowned }, }; ArrayRef results = {}; - auto extInfo = - SILFunctionType::ExtInfo() - .withRepresentation(SILFunctionTypeRepresentation::Thin); + + auto extInfo = SILFunctionType::ExtInfo().withRepresentation(rep); if (genericSig && genericSig->areAllParamsConcrete()) genericSig = nullptr; diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp index 8c3e03ffe413e..c48011c3ae9c5 100644 --- a/lib/SILGen/SILGenLValue.cpp +++ b/lib/SILGen/SILGenLValue.cpp @@ -879,8 +879,14 @@ namespace { rawPointerTy, ValueOwnershipKind::Trivial); // Cast the callback to the correct polymorphic function type. + SILFunctionTypeRepresentation rep; + if (isa(decl->getDeclContext())) + rep = SILFunctionTypeRepresentation::WitnessMethod; + else + rep = SILFunctionTypeRepresentation::Method; + auto origCallbackFnType = gen.SGM.Types.getMaterializeForSetCallbackType( - decl, materialized.genericSig, materialized.origSelfType); + decl, materialized.genericSig, materialized.origSelfType, rep); auto origCallbackType = SILType::getPrimitiveObjectType(origCallbackFnType); callback = gen.B.createPointerToThinFunction(loc, callback, origCallbackType); diff --git a/lib/SILGen/SILGenMaterializeForSet.cpp b/lib/SILGen/SILGenMaterializeForSet.cpp index d8e7c8e2ec2be..7c84478c60da9 100644 --- a/lib/SILGen/SILGenMaterializeForSet.cpp +++ b/lib/SILGen/SILGenMaterializeForSet.cpp @@ -12,6 +12,136 @@ // // Emission of materializeForSet. // +// There are two cases where materializeForSet is used for inout access: +// +// === Storage is virtually dispatched on a base class === +// +// For example, suppose we have this setup, where a computed property in a +// base class is overridden with a computed property in the derived class: +// +// class Base { var x: T } +// class Derived : Base { override var x: Int { ... } } +// func operate(b: Base) { +// b.x += 1 +// } +// +// As far as caller is concerned, the callback is invoked with the following +// SIL type: +// +// (RawPointer, @inout UnsafeValueBuffer, @inout Base, @thick Base.Type) -> () +// +// The caller will pass the first four formal parameters, followed by the +// type metadata for 'T'. +// +// However if the dynamic type of the parameter 'b' is actually 'Derived', +// then the actual callback has this SIL type: +// +// (RawPointer, @inout UnsafeValueBuffer, @inout Derived, @thick Derived.Type) -> () +// +// This is a fully concrete function type, with no additional generic metadata. +// +// These two callbacks are be ABI-compatible though, because IRGen makes three +// guarantees: +// +// 1) Passing extra arguments (in this case, the type metadata for 'T') is a +// no-op. +// +// 2) IRGen knows to recover the type metadata for 'T' from the +// '@thick Base.Type' parameter, instead of passing it separately. +// +// 3) The metatype for 'Derived' must be layout-compatible with 'Base'; +// since the generic parameter 'T' is made concrete, we expect to find the +// type metadata for 'Int' at the same offset within 'Derived.Type' as the +// generic parameter 'T' in 'Base.Type'. +// +// === Storage is virtually dispatched on a protocol === +// +// For example, +// +// protocol BoxLike { associatedtype Element; var x: Element { get set } } +// func operate(b: B) where B.Element == Int { +// b.x += 1 +// } +// +// As far as the caller is concerned, the callback is invoked with following +// SIL type: +// +// (RawPointer, @inout UnsafeValueBuffer, @inout Self, @thick Self.Type) -> () +// +// At the IRGen level, a call of a SIL function with the above type will pass +// the four formal parameters, followed by the type metadata for 'Self', and +// then followed by the protocol witness table for 'Self : BoxLike'. +// +// As in the class case, the callback won't have the same identical SIL type, +// because it might have a different representation of 'Self'. +// +// So we must consider two separate cases: +// +// 1) The witness is a method of the concrete conforming type, eg, +// +// struct Box : BoxLike { var x: T } +// +// Here, the actual callback will have the following type: +// +// (RawPointer, @inout UnsafeValueBuffer, @inout Box, @thick Box.Type) -> () +// +// As with the class case, IRGen can already do the right thing -- the type +// metadata for 'T' is recovered from the '@thick Box.Type' parameter, +// and the type metadata for 'Self' as well as the conformance +// 'Self : BoxLike' are ignored. +// +// 2) The witness is a protocol extension method, possibly of some other protocol, eg, +// +// protocol SomeOtherProtocol { } +// extension SomeOtherProtocol { var x: Element { ... } } +// struct FunnyBox : BoxLike, SomeOtherProtocol { typealias Element = T } +// +// Here, the actual callback will have the following type: +// +// (RawPointer, @inout UnsafeValueBuffer, @inout Self, @thick Self.Type) -> () +// +// Here, the actual callback expects to receive the four formal parameters, +// followed by the type metadata for 'Self', followed by the witness table +// for the conformance 'Self : SomeOtherProtocol'. Note that the +// conformance cannot be recovered from the thick metatype. +// +// This is *not* ABI-compatible with the type used at the call site, +// because the caller is passing in the conformance of 'Self : BoxLike' +// (the requirement's signature) but the callee is expecting +// 'Self : SomeOtherProtocol' (the witness signature). +// +// For this reason the materializeForSet method in the protocol extension +// of 'SomeOtherProtocol' cannot witness the materializeForSet requirement +// of 'BoxLike'. So instead, the protocol witness thunk for +// materializeForSet cannot delegate to the materializeForSet witness at +// all; it's entirely open-coded, with its own callback that has the right +// calling convention. +// +// === Storage has its own generic parameters === +// +// One final special case is where the storage has its own generic parameters; +// that is, a generic subscript. +// +// Suppose we have the following protocol: +// +// protocol GenericSubscript { subscript(t: T) -> U { get set } } +// +// At the call site, the callback is invoked with the following signature: +// +// (RawPointer, @inout UnsafeValueBuffer, @inout Self, @thick Self.Type) -> () +// +// If the witness is a member of a concrete type 'AnyDictionary', the actual +// callback will have the following signature: +// +// (RawPointer, @inout UnsafeValueBuffer, @inout AnyDictionary, @thick SelfAnyDictionary.Type) -> () +// +// This is not ABI-compatible with the type at the call site, because the type +// metadata for 'T' and 'U' trails the type metadata for 'Self' and the protocol +// witness table for the conformance 'Self : GenericSubscript'. +// +// So again, protocol witness thunks for materializeForSet of a generic +// subscript must be open-coded. +// //===----------------------------------------------------------------------===// #include "SILGen.h" @@ -124,12 +254,15 @@ struct MaterializeForSetEmitter { SILType WitnessStorageType; + SILFunctionTypeRepresentation CallbackRepresentation; + private: MaterializeForSetEmitter(SILGenModule &SGM, SILLinkage linkage, FuncDecl *witness, SubstitutionList subs, GenericEnvironment *genericEnv, - Type selfInterfaceType, Type selfType) + Type selfInterfaceType, Type selfType, + SILFunctionTypeRepresentation callbackRepresentation) : SGM(SGM), Linkage(linkage), RequirementStorage(nullptr), @@ -142,7 +275,8 @@ struct MaterializeForSetEmitter { SelfInterfaceType(selfInterfaceType->getCanonicalType()), SubstSelfType(selfType->getCanonicalType()), TheAccessSemantics(AccessSemantics::Ordinary), - IsSuper(false) { + IsSuper(false), + CallbackRepresentation(callbackRepresentation) { // Determine the formal type of the 'self' parameter. if (WitnessStorage->isStatic()) { @@ -179,7 +313,8 @@ struct MaterializeForSetEmitter { FuncDecl *requirement, FuncDecl *witness, SubstitutionList witnessSubs) { MaterializeForSetEmitter emitter(SGM, linkage, witness, witnessSubs, - genericEnv, selfInterfaceType, selfType); + genericEnv, selfInterfaceType, selfType, + SILFunctionTypeRepresentation::WitnessMethod); emitter.RequirementStorage = requirement->getAccessorStorageDecl(); // Determine the desired abstraction pattern of the storage type @@ -209,7 +344,8 @@ struct MaterializeForSetEmitter { MaterializeForSetEmitter emitter(SGM, constant.getLinkage(ForDefinition), witness, witnessSubs, witness->getGenericEnvironment(), - selfInterfaceType, selfType); + selfInterfaceType, selfType, + SILFunctionTypeRepresentation::Method); emitter.RequirementStorage = emitter.WitnessStorage; emitter.RequirementStoragePattern = emitter.WitnessStoragePattern; @@ -374,9 +510,12 @@ struct MaterializeForSetEmitter { /// Given part of the witness's interface type, produce its /// substitution according to the witness substitutions. CanType getSubstWitnessInterfaceType(CanType type) { - auto subs = SubstSelfType->getRValueInstanceType() - ->getMemberSubstitutionMap(SGM.SwiftModule, WitnessStorage); - return type.subst(subs)->getCanonicalType(); + if (auto *witnessSig = Witness->getGenericSignature()) { + auto subMap = witnessSig->getSubstitutionMap(WitnessSubs); + return type.subst(subMap, SubstFlags::UseErrorType)->getCanonicalType(); + } + + return type; } }; @@ -537,7 +676,8 @@ SILFunction *MaterializeForSetEmitter::createCallback(SILFunction &F, auto callbackType = SGM.Types.getMaterializeForSetCallbackType(WitnessStorage, GenericSig, - SelfInterfaceType); + SelfInterfaceType, + CallbackRepresentation); auto *genericEnv = GenericEnv; if (GenericEnv && GenericEnv->getGenericSignature()->areAllParamsConcrete()) diff --git a/test/Interpreter/generic_subscript.swift b/test/Interpreter/generic_subscript.swift new file mode 100644 index 0000000000000..468765d6e3e8f --- /dev/null +++ b/test/Interpreter/generic_subscript.swift @@ -0,0 +1,132 @@ +//===--- FunctionConversion.swift -----------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// RUN: %target-run-simple-swift +// REQUIRES: executable_test +// + +import StdlibUnittest + + +var GenericSubscriptTestSuite = TestSuite("GenericSubscript") + +struct S : P { + typealias Element = T + var t: T + + subscript(a: (T) -> U, b: (U) -> T) -> U { + get { + print(T.self) + print(U.self) + + return a(t) + } + set { + print(T.self) + print(U.self) + + t = b(newValue) + } + } +} + +protocol P { + associatedtype Element + subscript(a: (Element) -> U, b: (U) -> Element) -> U { get set } +} + +func increment(p: inout T) where T.Element == String { + p[{Int($0)!}, {String($0)}] += 1 +} + +GenericSubscriptTestSuite.test("Basic") { + var s = S(t: "0") + increment(p: &s) + expectEqual(s.t, "1") +} + +protocol AnySubscript { + subscript(k: AnyHashable) -> Any? { get set } +} + +struct AnyDictionary : AnySubscript { + var dict: [AnyHashable : Any] = [:] + + subscript(k: AnyHashable) -> Any? { + get { + return dict[k] + } + set { + dict[k] = newValue + } + } +} + +extension AnySubscript { + subscript(k k: K) -> V? { + get { + return self[k] as! V? + } + set { + self[k] = newValue + } + } +} + +GenericSubscriptTestSuite.test("ProtocolExtensionConcrete") { + var dict = AnyDictionary() + + func doIt(dict: inout AnyDictionary) { + dict["a" ] = 0 + dict[k: "a"]! += 1 + } + + doIt(dict: &dict) + + expectEqual(dict["a"]! as! Int, 1) + expectEqual(dict[k: "a"]!, 1) +} + +GenericSubscriptTestSuite.test("ProtocolExtensionAbstract") { + var dict = AnyDictionary() + + func doIt(dict: inout T) { + dict["a" ] = 0 + dict[k: "a"]! += 1 + } + + doIt(dict: &dict) + + expectEqual(dict["a"]! as! Int, 1) + expectEqual(dict[k: "a"]!, 1) +} + +protocol GenericSubscript : AnySubscript { + subscript(k k: K) -> V? { get set } +} + +extension AnyDictionary : GenericSubscript { } + +GenericSubscriptTestSuite.test("ProtocolExtensionWitness") { + var dict = AnyDictionary() + + func doIt(dict: inout T) { + dict["a" ] = 0 + dict[k: "a"]! += 1 + } + + doIt(dict: &dict) + + expectEqual(dict["a"]! as! Int, 1) + expectEqual(dict[k: "a"]!, 1) +} + +runAllTests() diff --git a/test/SILGen/accessors.swift b/test/SILGen/accessors.swift index 1f740977bf9bc..3f124b0040519 100644 --- a/test/SILGen/accessors.swift +++ b/test/SILGen/accessors.swift @@ -65,7 +65,7 @@ func test0(_ ref: A) { // CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]] // CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer): -// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout A, @thick A.Type) -> () +// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout A, @thick A.Type) -> () // CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $A // SEMANTIC SIL TODO: This is an issue caused by the callback for materializeForSet in the class case taking the value as @inout when it should really take it as @guaranteed. // CHECK-NEXT: store [[BORROWED_ARG_LHS]] to [init] [[TEMP2]] : $*A @@ -128,7 +128,7 @@ func test1(_ ref: B) { // CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]] // // CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer): -// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> () +// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> () // CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B // CHECK-NEXT: store [[BORROWED_ARG_RHS]] to [init] [[TEMP2]] : $*B // CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type @@ -154,7 +154,7 @@ func test1(_ ref: B) { // CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]] // // CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer): -// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> () +// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> () // CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B // CHECK-NEXT: store [[BORROWED_ARG_LHS]] to [init] [[TEMP2]] : $*B // CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type diff --git a/test/SILGen/addressors.swift b/test/SILGen/addressors.swift index 2bd836c9a703d..fe274de285e58 100644 --- a/test/SILGen/addressors.swift +++ b/test/SILGen/addressors.swift @@ -332,7 +332,7 @@ class G { // CHECK: strong_release [[OWNER]] : $Builtin.NativeObject // materializeForSet callback for G.value -// CHECK-LABEL: sil hidden [transparent] @_T010addressors1GC5values5Int32VfmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout G, @thick G.Type) -> () { +// CHECK-LABEL: sil hidden [transparent] @_T010addressors1GC5values5Int32VfmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout G, @thick G.Type) -> () { // CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*G, [[SELFTYPE:%3]] : $@thick G.Type): // CHECK: [[T0:%.*]] = project_value_buffer $Builtin.NativeObject in [[STORAGE]] : $*Builtin.UnsafeValueBuffer // CHECK: [[OWNER:%.*]] = load [[T0]] @@ -452,7 +452,7 @@ class I { // CHECK: strong_unpin [[OWNER]] : $Optional // materializeForSet callback for I.value -// CHECK-LABEL: sil hidden [transparent] @_T010addressors1IC5values5Int32VfmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout I, @thick I.Type) -> () { +// CHECK-LABEL: sil hidden [transparent] @_T010addressors1IC5values5Int32VfmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout I, @thick I.Type) -> () { // CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*I, [[SELFTYPE:%3]] : $@thick I.Type): // CHECK: [[T0:%.*]] = project_value_buffer $Optional in [[STORAGE]] : $*Builtin.UnsafeValueBuffer // CHECK: [[OWNER:%.*]] = load [[T0]] diff --git a/test/SILGen/constrained_extensions.swift b/test/SILGen/constrained_extensions.swift index ea7ee1bcf1e6d..e6820ca965b96 100644 --- a/test/SILGen/constrained_extensions.swift +++ b/test/SILGen/constrained_extensions.swift @@ -10,7 +10,7 @@ extension Array where Element == Int { // CHECK-LABEL: sil @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifg : $@convention(method) (@guaranteed Array) -> Int // CHECK-LABEL: sil @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifs : $@convention(method) (Int, @inout Array) -> () - // CHECK-LABEL: sil [transparent] [fragile] @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array, @thick Array.Type) -> () + // CHECK-LABEL: sil [transparent] [fragile] @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array, @thick Array.Type) -> () // CHECK-LABEL: sil [transparent] [fragile] @_T0Sa22constrained_extensionsSiRszlE16instancePropertySifm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Array) -> (Builtin.RawPointer, Optional) public var instanceProperty: Element { @@ -71,7 +71,7 @@ extension Dictionary where Key == Int { // CHECK-LABEL: sil @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fg : $@convention(method) (@guaranteed Dictionary) -> @out Value // CHECK-LABEL: sil @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fs : $@convention(method) (@in Value, @inout Dictionary) -> () - // CHECK-LABEL: sil [transparent] [fragile] @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary, @thick Dictionary.Type) -> () + // CHECK-LABEL: sil [transparent] [fragile] @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary, @thick Dictionary.Type) -> () // CHECK-LABEL: sil [transparent] [fragile] @_T0s10DictionaryV22constrained_extensionsSiRszr0_lE16instancePropertyq_fm : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Dictionary) -> (Builtin.RawPointer, Optional) public var instanceProperty: Value { get { diff --git a/test/SILGen/lifetime.swift b/test/SILGen/lifetime.swift index 39a4ab5433d99..47cad67e75332 100644 --- a/test/SILGen/lifetime.swift +++ b/test/SILGen/lifetime.swift @@ -380,7 +380,7 @@ func logical_lvalue_lifetime(_ r: RefWithProp, _ i: Int, _ v: Val) { // CHECK: [[ADDR:%.*]] = pointer_to_address [[PTR]] // CHECK: [[MARKED_ADDR:%.*]] = mark_dependence [[ADDR]] : $*Aleph on [[R2]] // CHECK: {{.*}}([[CALLBACK_ADDR:%.*]] : - // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout RefWithProp, @thick RefWithProp.Type) -> () + // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout RefWithProp, @thick RefWithProp.Type) -> () // CHECK: [[TEMP:%.*]] = alloc_stack $RefWithProp // CHECK: store [[R2]] to [init] [[TEMP]] // CHECK: apply [[CALLBACK]]({{.*}}, [[STORAGE]], [[TEMP]], {{%.*}}) diff --git a/test/SILGen/materializeForSet.swift b/test/SILGen/materializeForSet.swift index c39fe7eecb644..7f3d867e6d3d2 100644 --- a/test/SILGen/materializeForSet.swift +++ b/test/SILGen/materializeForSet.swift @@ -6,7 +6,7 @@ class Base { // The ordering here is unfortunate: we generate the property // getters and setters after we've processed the decl. - // CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet4BaseC8computedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> () { + // CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet4BaseC8computedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> () { // CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*Base, [[SELFTYPE:%.*]] : $@thick Base.Type): // CHECK: [[T0:%.*]] = load_borrow [[SELF]] // CHECK: [[T1:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int @@ -21,7 +21,7 @@ class Base { // CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]]) // CHECK: store [[T1]] to [trivial] [[ADDR]] : $*Int // CHECK: [[BUFFER:%.*]] = address_to_pointer [[ADDR]] -// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet4BaseC8computedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> () +// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet4BaseC8computedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Base, @thick Base.Type) -> () // CHECK: [[T2:%.*]] = thin_function_to_pointer [[T0]] // CHECK: [[T3:%.*]] = enum $Optional, #Optional.some!enumelt.1, [[T2]] : $Builtin.RawPointer // CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[T3]] : $Optional) @@ -69,7 +69,7 @@ protocol Abstractable { extension Derived : Abstractable {} -// CHECK: sil hidden [transparent] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14storedFunction6ResultQzycfmytfU_TW : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Derived, @thick Derived.Type) -> () +// CHECK: sil hidden [transparent] @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14storedFunction6ResultQzycfmytfU_TW : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Derived, @thick Derived.Type) -> () // CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*Derived, %3 : $@thick Derived.Type): // CHECK-NEXT: [[T0:%.*]] = load_borrow %2 : $*Derived // CHECK-NEXT: [[SELF:%.*]] = upcast [[T0]] : $Derived to $Base @@ -167,8 +167,8 @@ extension Derived : Abstractable {} // CHECK-NEXT: destroy_addr [[OUT]] : $*@callee_owned () -> Int // CHECK-NEXT: store [[NEWVALUE]] to [init] [[RESULT_ADDR]] : $*@callee_owned () -> @out Int // CHECK-NEXT: [[ADDR:%.*]] = address_to_pointer [[RESULT_ADDR]] : $*@callee_owned () -> @out Int to $Builtin.RawPointer -// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14staticFunction6ResultQzycfmZytfU_TW : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> () -// CHECK-NEXT: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]] : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> () to $Builtin.RawPointer +// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet7DerivedCAA12AbstractableAaaDP14staticFunction6ResultQzycfmZytfU_TW : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> () +// CHECK-NEXT: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]] : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout @thick Derived.Type, @thick Derived.Type.Type) -> () to $Builtin.RawPointer // CHECK-NEXT: [[CALLBACK:%.*]] = enum $Optional, #Optional.some!enumelt.1, [[CALLBACK_ADDR]] : $Builtin.RawPointer // CHECK-NEXT: [[RESULT:%.*]] = tuple ([[ADDR]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional) // CHECK-NEXT: dealloc_stack [[OUT]] : $*@callee_owned () -> Int @@ -213,7 +213,7 @@ class HasDidSet : Base { // CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]]) // CHECK: store [[T1]] to [trivial] [[T2]] : $*Int // CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]] -// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet06HasDidC0C6storedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> () +// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet06HasDidC0C6storedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> () // CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]] // CHECK: [[CALLBACK:%.*]] = enum $Optional, #Optional.some!enumelt.1, [[CALLBACK_ADDR]] // CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional) @@ -232,7 +232,7 @@ class HasDidSet : Base { // CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]]) // CHECK: store [[T1]] to [trivial] [[T2]] : $*Int // CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]] -// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet06HasDidC0C8computedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> () +// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet06HasDidC0C8computedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasDidSet, @thick HasDidSet.Type) -> () // CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]] // CHECK: [[CALLBACK:%.*]] = enum $Optional, #Optional.some!enumelt.1, [[CALLBACK_ADDR]] // CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional) @@ -245,7 +245,7 @@ class HasStoredDidSet { didSet {} } -// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet012HasStoredDidC0C6storedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> () { +// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet012HasStoredDidC0C6storedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> () { // CHECK: bb0([[BUFFER:%.*]] : $Builtin.RawPointer, [[STORAGE:%.*]] : $*Builtin.UnsafeValueBuffer, [[SELF:%.*]] : $*HasStoredDidSet, [[METATYPE:%.*]] : $@thick HasStoredDidSet.Type): // CHECK: [[SELF_VALUE:%.*]] = load_borrow [[SELF]] : $*HasStoredDidSet // CHECK: [[BUFFER_ADDR:%.*]] = pointer_to_address [[BUFFER]] : $Builtin.RawPointer to [strict] $*Int @@ -262,7 +262,7 @@ class HasStoredDidSet { // CHECK: [[T1:%.*]] = apply [[T0]]([[SELF]]) // CHECK: store [[T1]] to [trivial] [[T2]] : $*Int // CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]] -// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet012HasStoredDidC0C6storedSifmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> () +// CHECK: [[CALLBACK_FN:%.*]] = function_ref @_T017materializeForSet012HasStoredDidC0C6storedSifmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasStoredDidSet, @thick HasStoredDidSet.Type) -> () // CHECK: [[CALLBACK_ADDR:%.*]] = thin_function_to_pointer [[CALLBACK_FN]] // CHECK: [[CALLBACK:%.*]] = enum $Optional, #Optional.some!enumelt.1, [[CALLBACK_ADDR]] // CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, [[CALLBACK]] : $Optional) @@ -280,7 +280,7 @@ class HasWeak { // CHECK: [[T1:%.*]] = load_weak [[T0]] : $*@sil_weak Optional // CHECK: store [[T1]] to [init] [[T2]] : $*Optional // CHECK: [[BUFFER:%.*]] = address_to_pointer [[T2]] -// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet7HasWeakC7weakvarACSgXwfmytfU_ : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasWeak, @thick HasWeak.Type) -> () +// CHECK: [[T0:%.*]] = function_ref @_T017materializeForSet7HasWeakC7weakvarACSgXwfmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout HasWeak, @thick HasWeak.Type) -> () // CHECK: [[T4:%.*]] = tuple ([[BUFFER]] : $Builtin.RawPointer, {{.*}} : $Optional) // CHECK: return [[T4]] : $(Builtin.RawPointer, Optional) // CHECK: } @@ -359,6 +359,47 @@ struct Foo: AddressOnlySubscript { func increment(_ x: inout Int) { x += 1 } +// Generic subscripts. + +protocol GenericSubscriptProtocol { + subscript(_: T) -> T { get set } +} + +struct GenericSubscriptWitness : GenericSubscriptProtocol { + subscript(_: T) -> T { get { } set { } } +} + +// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet23GenericSubscriptWitnessV9subscriptxxclufmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericSubscriptWitness, @thick GenericSubscriptWitness.Type) -> () { +// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*GenericSubscriptWitness, %3 : $@thick GenericSubscriptWitness.Type): +// CHECK: [[BUFFER:%.*]] = project_value_buffer $T in %1 : $*Builtin.UnsafeValueBuffer +// CHECK-NEXT: [[INDICES:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*T +// CHECK: [[SETTER:%.*]] = function_ref @_T017materializeForSet23GenericSubscriptWitnessV9subscriptxxclufs : $@convention(method) <τ_0_0> (@in τ_0_0, @in τ_0_0, @inout GenericSubscriptWitness) -> () +// CHECK-NEXT: apply [[SETTER]]([[INDICES]], [[BUFFER]], %2) : $@convention(method) <τ_0_0> (@in τ_0_0, @in τ_0_0, @inout GenericSubscriptWitness) -> () +// CHECK-NEXT: dealloc_value_buffer $*T in %1 : $*Builtin.UnsafeValueBuffer +// CHECK-NEXT: [[RESULT:%.*]] = tuple () +// CHECK-NEXT: return [[RESULT]] : $() + +// CHECK-LABEL sil hidden [transparent] [thunk] @_T017materializeForSet23GenericSubscriptWitnessVAA0dE8ProtocolAaaDP9subscriptqd__qd__clufmTW : $@convention(witness_method) <τ_0_0> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in τ_0_0, @inout GenericSubscriptWitness) -> (Builtin.RawPointer, Optional) { +// CHECK: bb0(%0 : $Builtin.RawPointer, %1 : $*Builtin.UnsafeValueBuffer, %2 : $*T, %3 : $*GenericSubscriptWitness): +// CHECK-NEXT: [[BUFFER:%.*]] = alloc_value_buffer $T in %1 : $*Builtin.UnsafeValueBuffer +// CHECK-NEXT: copy_addr %2 to [initialization] [[BUFFER]] : $*T +// CHECK-NEXT: [[VALUE:%.*]] = pointer_to_address %0 : $Builtin.RawPointer to [strict] $*T +// CHECK-NEXT: [[SELF:%.*]] = load [trivial] %3 : $*GenericSubscriptWitness +// CHECK: [[GETTER:%.*]] = function_ref @_T017materializeForSet23GenericSubscriptWitnessV9subscriptxxclufg : $@convention(method) <τ_0_0> (@in τ_0_0, GenericSubscriptWitness) -> @out τ_0_0 +// CHECK-NEXT: apply [[GETTER]]([[VALUE]], %2, [[SELF]]) : $@convention(method) <τ_0_0> (@in τ_0_0, GenericSubscriptWitness) -> @out τ_0_0 +// CHECK-NEXT: [[VALUE_PTR:%.*]] = address_to_pointer [[VALUE]] : $*T to $Builtin.RawPointer +// CHECK: [[CALLBACK:%.*]] = function_ref @_T017materializeForSet23GenericSubscriptWitnessV9subscriptxxclufmytfU_ +// CHECK-NEXT: [[CALLBACK_PTR:%.*]] = thin_function_to_pointer [[CALLBACK]] : $@convention(method) <τ_0_0> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericSubscriptWitness, @thick GenericSubscriptWitness.Type) -> () to $Builtin.RawPointer +// CHECK-NEXT: [[CALLBACK_OPTIONAL:%.*]] = enum $Optional, #Optional.some!enumelt.1, [[CALLBACK_PTR]] : $Builtin.RawPointer +// CHECK-NEXT: [[RESULT:%.*]] = tuple ([[VALUE_PTR]] : $Builtin.RawPointer, [[CALLBACK_OPTIONAL]] : $Optional) +// CHECK-NEXT: return [[RESULT]] : $(Builtin.RawPointer, Optional) + +extension GenericSubscriptProtocol { + subscript(t: T) -> T { get { } set { } } +} + +struct GenericSubscriptDefaultWitness : GenericSubscriptProtocol { } + // Test for materializeForSet vs static properties of structs. protocol Beverage { @@ -439,7 +480,7 @@ extension Panda { struct TuxedoPanda : Panda { } -// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet11TuxedoPandaVAA0E0AaaDP1xxxcfmytfU_TW : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout TuxedoPanda, @thick TuxedoPanda.Type) -> () +// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet11TuxedoPandaVAA0E0AaaDP1xxxcfmytfU_TW : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout TuxedoPanda, @thick TuxedoPanda.Type) -> () // FIXME: Useless re-abstractions @@ -470,7 +511,7 @@ struct TuxedoPanda : Panda { } // The callback: - // CHECK: function_ref @_T017materializeForSet11TuxedoPandaVAA0E0AaaDP1xxxcfmytfU_TW : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout TuxedoPanda, @thick TuxedoPanda.Type) -> () + // CHECK: function_ref @_T017materializeForSet11TuxedoPandaVAA0E0AaaDP1xxxcfmytfU_TW : $@convention(witness_method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout TuxedoPanda, @thick TuxedoPanda.Type) -> () // CHECK: } diff --git a/test/SILGen/properties.swift b/test/SILGen/properties.swift index e54101b7651dd..3e66fde089830 100644 --- a/test/SILGen/properties.swift +++ b/test/SILGen/properties.swift @@ -227,7 +227,7 @@ func logical_struct_in_reftype_set(_ value: inout Val, z1: Int) { // -- writeback to val.ref.val_prop // CHECK: switch_enum [[OPT_CALLBACK]] : $Optional, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]] // CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer): - // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Ref, @thick Ref.Type) -> () + // CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout Ref, @thick Ref.Type) -> () // CHECK: [[REF_MAT:%.*]] = alloc_stack $Ref // CHECK: store [[VAL_REF]] to [init] [[REF_MAT]] // CHECK: [[T0:%.*]] = metatype $@thick Ref.Type diff --git a/test/SILOptimizer/devirt_materializeForSet.swift b/test/SILOptimizer/devirt_materializeForSet.swift index e84bc406bc1aa..77b805bffd044 100644 --- a/test/SILOptimizer/devirt_materializeForSet.swift +++ b/test/SILOptimizer/devirt_materializeForSet.swift @@ -5,7 +5,7 @@ // CHECK-LABEL: sil [transparent] [fragile] [thunk] @_T024devirt_materializeForSet7BaseFooCAA0F0AaaDP3barSSfmTW // CHECK: checked_cast_br [exact] %{{.*}} : $BaseFoo to $ChildFoo -// CHECK: thin_function_to_pointer %{{.*}} : $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout ChildFoo, @thick ChildFoo.Type) -> () to $Builtin.RawPointer +// CHECK: thin_function_to_pointer %{{.*}} : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout ChildFoo, @thick ChildFoo.Type) -> () to $Builtin.RawPointer // CHECK: enum $Optional, #Optional.some!enumelt.1, %{{.*}} : $Builtin.RawPointer // CHECK: tuple (%{{.*}} : $Builtin.RawPointer, %{{.*}} : $Optional)