Slava gave me a hint: create a SubstitutionMap and then use the methods on GenericEnvironment to turn it into ArrayRef&lt;Substitution&gt;. I&#39;ll try that out tonight and see how far I get.<br><div class="gmail_quote"><div dir="ltr">On Sun, Nov 27, 2016 at 2:12 PM Michael Gottesman &lt;<a href="mailto:mgottesman@apple.com">mgottesman@apple.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">+CC Slava.<br class="gmail_msg">
<br class="gmail_msg">
He has been messing around with this area in the past bit since many of us have looked at this. He is the person you want.<br class="gmail_msg">
<br class="gmail_msg">
Michael<br class="gmail_msg">
<br class="gmail_msg">
&gt; On Nov 25, 2016, at 8:42 PM, Ben Ng &lt;<a href="mailto:me@benng.me" class="gmail_msg" target="_blank">me@benng.me</a>&gt; wrote:<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; Hi everyone,<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; I’ve made good progress with the information in this thread but I can’t figure out how to create the proper set of substitutions for the method that I’m calling.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; The error I’m getting, as expected, is &quot;SIL verification failed: callee of apply without substitutions must not be polymorphic: !fnTy-&gt;isPolymorphic()&quot;<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; I was hoping that there would be a way to delay specialization of the function that I’m replacing so that I can simply reuse those substitutions, but it doesn’t seem like that’s possible.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; At a high level I assumed that I’d simply be able to substitute a type like `Int` for `τ_0_0`, but it looks like I have to use a ProtocolConformanceRef, which I don’t understand.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; I looked into iterating through `getLoweredFunctionType()-&gt;getGenericSignature()-&gt;getGenericParams()`, but I don’t see how I can turn the information there into ProtocolConformanceRef.<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; Thanks for the help as always,<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt; Ben<br class="gmail_msg">
&gt;<br class="gmail_msg">
&gt;&gt; On Nov 16, 2016, at 10:47 PM, Ben Ng &lt;<a href="mailto:me@benng.me" class="gmail_msg" target="_blank">me@benng.me</a>&gt; wrote:<br class="gmail_msg">
&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt; On Nov 16, 2016, at 7:11 PM, Arnold Schwaighofer &lt;<a href="mailto:aschwaighofer@apple.com" class="gmail_msg" target="_blank">aschwaighofer@apple.com</a>&gt; wrote:<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;&gt; On Nov 16, 2016, at 2:58 PM, Ben Ng &lt;<a href="mailto:me@benng.me" class="gmail_msg" target="_blank">me@benng.me</a>&gt; wrote:<br class="gmail_msg">
&gt;&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;&gt; Correct, that is what I am trying to do.<br class="gmail_msg">
&gt;&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;&gt;&gt; On Nov 16, 2016, at 12:22 PM, Arnold Schwaighofer &lt;<a href="mailto:aschwaighofer@apple.com" class="gmail_msg" target="_blank">aschwaighofer@apple.com</a>&gt; wrote:<br class="gmail_msg">
&gt;&gt;&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;&gt;&gt; // Really, by the time you look at this in array value prop<br class="gmail_msg">
&gt;&gt;&gt;&gt;&gt; // this call should have been inline and you would see a call<br class="gmail_msg">
&gt;&gt;&gt;&gt;&gt; // to:<br class="gmail_msg">
&gt;&gt;&gt;&gt;&gt; // a.append(contentsOf: [1])<br class="gmail_msg">
&gt;&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;&gt; I do not understand this comment; I thought that inlining of stdlib functions happened after high-level SIL optimizations are run. Is my understanding incorrect?<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt; Inlining of functions with @_semantics is delayed until after high-level SIL optimizations are run. Other functions are inlined.<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt; <a href="https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/Passes.cpp#L221" rel="noreferrer" class="gmail_msg" target="_blank">https://github.com/apple/swift/blob/master/lib/SILOptimizer/PassManager/Passes.cpp#L221</a><br class="gmail_msg">
&gt;&gt;&gt; <a href="https://github.com/apple/swift/blob/master/lib/SILOptimizer/Transforms/PerformanceInliner.cpp#L722" rel="noreferrer" class="gmail_msg" target="_blank">https://github.com/apple/swift/blob/master/lib/SILOptimizer/Transforms/PerformanceInliner.cpp#L722</a><br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt; I recommend looking at the SIL function dump in ArrayElementValuePropagation of an example function after adding @semantics(“array.mutate_unknown”) to “append(contentsOf:)”.<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt; $ git diff HEAD~<br class="gmail_msg">
&gt;&gt;&gt; diff --git a/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp b/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp<br class="gmail_msg">
&gt;&gt;&gt; index 76328a6..cb976f7 100644<br class="gmail_msg">
&gt;&gt;&gt; --- a/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp<br class="gmail_msg">
&gt;&gt;&gt; +++ b/lib/SILOptimizer/Transforms/ArrayElementValuePropagation.cpp<br class="gmail_msg">
&gt;&gt;&gt; @@ -259,6 +259,8 @@ public:<br class="gmail_msg">
&gt;&gt;&gt; void run() override {<br class="gmail_msg">
&gt;&gt;&gt;   auto &amp;Fn = *getFunction();<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt; +    Fn.dump();<br class="gmail_msg">
&gt;&gt;&gt; +<br class="gmail_msg">
&gt;&gt;&gt;   bool Changed = false;<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;   // Propagate the elements an of array value to its users.<br class="gmail_msg">
&gt;&gt;&gt; diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb<br class="gmail_msg">
&gt;&gt;&gt; index f00cc23..2acfd06 100644<br class="gmail_msg">
&gt;&gt;&gt; --- a/stdlib/public/core/Arrays.swift.gyb<br class="gmail_msg">
&gt;&gt;&gt; +++ b/stdlib/public/core/Arrays.swift.gyb<br class="gmail_msg">
&gt;&gt;&gt; @@ -1344,6 +1344,7 @@ extension ${Self} : RangeReplaceableCollection, _ArrayProtocol {<br class="gmail_msg">
&gt;&gt;&gt; /// - Parameter newElements: The elements to append to the array.<br class="gmail_msg">
&gt;&gt;&gt; ///<br class="gmail_msg">
&gt;&gt;&gt; /// - Complexity: O(*n*), where *n* is the length of the resulting array.<br class="gmail_msg">
&gt;&gt;&gt; +  @_semantics(&quot;array.mutate_unknown&quot;)<br class="gmail_msg">
&gt;&gt;&gt; public mutating func append&lt;C : Collection&gt;(contentsOf newElements: C)<br class="gmail_msg">
&gt;&gt;&gt;   where C.Iterator.Element == Element {<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt; # Rebuild the compiler and stdlib (without stdlib assertions).<br class="gmail_msg">
&gt;&gt;&gt; $ swift/utils/build-script -r  --assertions --no-swift-stdlib-assertions<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt; $ cat TestArray.swift<br class="gmail_msg">
&gt;&gt;&gt; @inline(never)<br class="gmail_msg">
&gt;&gt;&gt; public func test() {<br class="gmail_msg">
&gt;&gt;&gt; var a = [1, 2, 3]<br class="gmail_msg">
&gt;&gt;&gt; a += [1]<br class="gmail_msg">
&gt;&gt;&gt; print(a)<br class="gmail_msg">
&gt;&gt;&gt; }<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt; $ bin/swiftc -O 2&gt;&amp;1 | less<br class="gmail_msg">
&gt;&gt;&gt; ...<br class="gmail_msg">
&gt;&gt;&gt; sil shared [_semantics &quot;array.mutate_unknown&quot;] @_TTSg5Si_GSaSi_GSaSi_s10Collections___TFSa6appenduRd__s10CollectionxzWd__8Iterator7Element_rfT10contentsOfqd___T_ : $@convention(method) (@owned Array&lt;I<br class="gmail_msg">
&gt;&gt;&gt; nt&gt;, @inout Array&lt;Int&gt;) -&gt; () {<br class="gmail_msg">
&gt;&gt;&gt;<br class="gmail_msg">
&gt;&gt;&gt; …<br class="gmail_msg">
&gt;&gt;&gt; // testArray() -&gt; ()<br class="gmail_msg">
&gt;&gt;&gt; sil [noinline] @_TF9TestArray9testArrayFT_T_ : $@convention(thin) () -&gt; () {<br class="gmail_msg">
&gt;&gt;&gt; bb0:<br class="gmail_msg">
&gt;&gt;&gt; %0 = alloc_stack $Array&lt;Int&gt;, var, name &quot;a&quot;, loc &quot;TestArray.swift&quot;:3:7, scope 2 // users: %54, %32, %60, %23, %43<br class="gmail_msg">
&gt;&gt;&gt; %1 = integer_literal $Builtin.Word, 3, loc &quot;TestArray.swift&quot;:3:12, scope 2 // user: %4<br class="gmail_msg">
&gt;&gt;&gt; %2 = integer_literal $Builtin.Int64, 3, scope 5 // user: %3<br class="gmail_msg">
&gt;&gt;&gt; %3 = struct $Int (%2 : $Builtin.Int64), scope 5 // users: %22, %7<br class="gmail_msg">
&gt;&gt;&gt; %4 = alloc_ref [tail_elems $Int * %1 : $Builtin.Word] $_ContiguousArrayStorage&lt;Int&gt;, scope 5 // user: %7<br class="gmail_msg">
&gt;&gt;&gt; %5 = metatype $@thin Array&lt;Int&gt;.Type, scope 5   // users: %25, %7<br class="gmail_msg">
&gt;&gt;&gt; // function_ref specialized static Array._adoptStorage(_ContiguousArrayStorage&lt;A&gt;, count : Int) -&gt; ([A], UnsafeMutablePointer&lt;A&gt;)<br class="gmail_msg">
&gt;&gt;&gt; %6 = function_ref @_TTSg5Si___TZFSa13_adoptStoragefTGCs23_ContiguousArrayStoragex_5countSi_TGSax_GSpx__ : $@convention(method) (@owned _ContiguousArrayStorage&lt;Int&gt;, Int, @thin Array&lt;Int&gt;.Type) -&gt; (@<br class="gmail_msg">
&gt;&gt;&gt; owned Array&lt;Int&gt;, UnsafeMutablePointer&lt;Int&gt;), scope 5 // users: %25, %7<br class="gmail_msg">
&gt;&gt;&gt; %7 = apply %6(%4, %3, %5) : $@convention(method) (@owned _ContiguousArrayStorage&lt;Int&gt;, Int, @thin Array&lt;Int&gt;.Type) -&gt; (@owned Array&lt;Int&gt;, UnsafeMutablePointer&lt;Int&gt;), scope 5 // users: %9, %8<br class="gmail_msg">
&gt;&gt;&gt; %8 = tuple_extract %7 : $(Array&lt;Int&gt;, UnsafeMutablePointer&lt;Int&gt;), 0, scope 5 // user: %23<br class="gmail_msg">
&gt;&gt;&gt; %9 = tuple_extract %7 : $(Array&lt;Int&gt;, UnsafeMutablePointer&lt;Int&gt;), 1, scope 5 // user: %10<br class="gmail_msg">
&gt;&gt;&gt; %10 = struct_extract %9 : $UnsafeMutablePointer&lt;Int&gt;, #UnsafeMutablePointer._rawValue, scope 5 // user: %11<br class="gmail_msg">
&gt;&gt;&gt; %11 = pointer_to_address %10 : $Builtin.RawPointer to [strict] $*Int, loc &quot;TestArray.swift&quot;:3:12, scope 2 // users: %14, %21, %16<br class="gmail_msg">
&gt;&gt;&gt; %12 = integer_literal $Builtin.Int64, 1, loc &quot;TestArray.swift&quot;:3:12, scope 2 // user: %13<br class="gmail_msg">
&gt;&gt;&gt; %13 = struct $Int (%12 : $Builtin.Int64), loc &quot;TestArray.swift&quot;:3:12, scope 2 // users: %37, %30, %25, %14<br class="gmail_msg">
&gt;&gt;&gt; store %13 to %11 : $*Int, loc &quot;TestArray.swift&quot;:3:12, scope 2 // id: %14<br class="gmail_msg">
&gt;&gt;&gt; %15 = integer_literal $Builtin.Word, 1, loc &quot;TestArray.swift&quot;:3:15, scope 2 // users: %34, %24, %16<br class="gmail_msg">
&gt;&gt;&gt; %16 = index_addr %11 : $*Int, %15 : $Builtin.Word, loc &quot;TestArray.swift&quot;:3:15, scope 2 // user: %19<br class="gmail_msg">
&gt;&gt;&gt; %17 = integer_literal $Builtin.Int64, 2, loc &quot;TestArray.swift&quot;:3:15, scope 2 // user: %18<br class="gmail_msg">
&gt;&gt;&gt; %18 = struct $Int (%17 : $Builtin.Int64), loc &quot;TestArray.swift&quot;:3:15, scope 2 // user: %19<br class="gmail_msg">
&gt;&gt;&gt; store %18 to %16 : $*Int, loc &quot;TestArray.swift&quot;:3:15, scope 2 // id: %19<br class="gmail_msg">
&gt;&gt;&gt; %20 = integer_literal $Builtin.Word, 2, loc &quot;TestArray.swift&quot;:3:18, scope 2 // user: %21<br class="gmail_msg">
&gt;&gt;&gt; %21 = index_addr %11 : $*Int, %20 : $Builtin.Word, loc &quot;TestArray.swift&quot;:3:18, scope 2 // user: %22<br class="gmail_msg">
&gt;&gt;&gt; store %3 to %21 : $*Int, loc &quot;TestArray.swift&quot;:3:18, scope 2 // id: %22<br class="gmail_msg">
&gt;&gt;&gt; store %8 to %0 : $*Array&lt;Int&gt;, loc &quot;TestArray.swift&quot;:3:18, scope 2 // id: %23<br class="gmail_msg">
&gt;&gt;&gt; %24 = alloc_ref [tail_elems $Int * %15 : $Builtin.Word] $_ContiguousArrayStorage&lt;Int&gt;, scope 7 // user: %25<br class="gmail_msg">
&gt;&gt;&gt; %25 = apply %6(%24, %13, %5) : $@convention(method) (@owned _ContiguousArrayStorage&lt;Int&gt;, Int, @thin Array&lt;Int&gt;.Type) -&gt; (@owned Array&lt;Int&gt;, UnsafeMutablePointer&lt;Int&gt;), scope 7 // users: %27, %26<br class="gmail_msg">
&gt;&gt;&gt; %26 = tuple_extract %25 : $(Array&lt;Int&gt;, UnsafeMutablePointer&lt;Int&gt;), 0, scope 7 // user: %32<br class="gmail_msg">
&gt;&gt;&gt; %27 = tuple_extract %25 : $(Array&lt;Int&gt;, UnsafeMutablePointer&lt;Int&gt;), 1, scope 7 // user: %28<br class="gmail_msg">
&gt;&gt;&gt; %28 = struct_extract %27 : $UnsafeMutablePointer&lt;Int&gt;, #UnsafeMutablePointer._rawValue, scope 7 // user: %29<br class="gmail_msg">
&gt;&gt;&gt; %29 = pointer_to_address %28 : $Builtin.RawPointer to [strict] $*Int, loc &quot;TestArray.swift&quot;:4:9, scope 2 // user: %30<br class="gmail_msg">
&gt;&gt;&gt; store %13 to %29 : $*Int, loc &quot;TestArray.swift&quot;:4:9, scope 2 // id: %30<br class="gmail_msg">
&gt;&gt;&gt; // function_ref specialized Array.append&lt;A where ...&gt; (contentsOf : A1) -&gt; ()<br class="gmail_msg">
&gt;&gt;&gt; %31 = function_ref @_TTSg5Si_GSaSi_GSaSi_s10Collections___TFSa6appenduRd__s10CollectionxzWd__8Iterator7Element_rfT10contentsOfqd___T_ : $@convention(method) (@owned Array&lt;Int&gt;, @inout Array&lt;Int&gt;) -&gt; (), scope 10 // user: %32<br class="gmail_msg">
&gt;&gt;&gt; %32 = apply %31(%26, %0) : $@convention(method) (@owned Array&lt;Int&gt;, @inout Array&lt;Int&gt;) -&gt; (), scope 10<br class="gmail_msg">
&gt;&gt;<br class="gmail_msg">
&gt;&gt; Ah, I do remember seeing something about how the semantic attribute stops some functions from being inlined early. Thanks for saving me a bunch of head-scratching!<br class="gmail_msg">
&gt;&gt;<br class="gmail_msg">
&gt;&gt;<br class="gmail_msg">
&gt;<br class="gmail_msg">
<br class="gmail_msg">
</blockquote></div>