You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Performance Hints] Issue diagnostic for code wrapped in implicit nodes
In order to avoid issuing diagnostics for compiler-generate code, we ignore the
syntax subtree rooted at an implicit node. This causes our algorithm to miss
user code wrapped in implicit nodes during desugaring. For example, expressions
in implicit returns from single-expression closures and trailing closures are
completely ignored right now.
This change fixes heproblem by introducing a simple change to the AST walker.
Instead of ignoring the entire implicit-node subtree, we only ignore the
implicit node but continue to descend into its children. This enables our
algorithm to access non-implicit (user code) nodes nested inside
implicit (compiler-generated) nodes.
_ animal:anyAnimal, // expected-error {{Performance: 'animal' uses an existential, leading to heap allocation, reference counting, and dynamic dispatch. Consider using generic constraints or concrete types instead.}}
74
-
to other:anyAnimal// expected-error {{Performance: 'other' uses an existential, leading to heap allocation, reference counting, and dynamic dispatch. Consider using generic constraints or concrete types instead.}}
74
+
to other:anyAnimal // expected-error {{Performance: 'other' uses an existential, leading to heap allocation, reference counting, and dynamic dispatch. Consider using generic constraints or concrete types instead.}}
75
75
){}
76
76
77
77
// Variadic parameters
@@ -144,7 +144,7 @@ func tupleTest() {
144
144
145
145
let(
146
146
animalsA, // expected-error {{Performance: 'animalsA' uses an existential, leading to heap allocation, reference counting, and dynamic dispatch. Consider using generic constraints or concrete types instead.}}
147
-
animalsB // expected-error {{Performance: 'animalsB' uses an existential, leading to heap allocation, reference counting, and dynamic dispatch. Consider using generic constraints or concrete types instead.}}
147
+
animalsB // expected-error {{Performance: 'animalsB' uses an existential, leading to heap allocation, reference counting, and dynamic dispatch. Consider using generic constraints or concrete types instead.}}
148
148
)=([Tiger()asanyAnimal],[Panda()asanyAnimal])
149
149
print(type(of: animalsA))
150
150
print(type(of: animalsB))
@@ -244,3 +244,21 @@ struct Outer<T> {
244
244
func f()->Outer<anyAnimal>.Inner{ // expected-error {{Performance: 'f()' returns an existential, leading to heap allocation, reference counting, and dynamic dispatch. Consider using generic constraints or concrete types instead.}}
letanimals:[anyAnimal]= // expected-error {{Performance: 'animals' uses an existential, leading to heap allocation, reference counting, and dynamic dispatch. Consider using generic constraints or concrete types instead.}}
255
+
animalKinds.map{ animalKind in // expected-error {{Performance: closure returns an existential, leading to heap allocation, reference counting, and dynamic dispatch. Consider using generic constraints or concrete types instead.}}
0 commit comments