> On Sep 26, 2017, at 18:02, Robert Widmann via swift-dev <swift-dev@swift.org> > wrote: > >> >> On Sep 25, 2017, at 10:01 AM, Nevin Brackett-Rozinsky >> <nevin.brackettrozin...@gmail.com <mailto:nevin.brackettrozin...@gmail.com>> >> wrote: >> >> func triple(_ x: Int) -> Int { >> return 3 * x >> } >> >> extension Int { >> func triple() -> Int { >> return triple(self) // Error here >> } >> } >> >> >> The error reads: >> >> Playground execution failed: >> error: Test.playground:5:16: error: use of 'triple' refers to instance >> method 'triple()' rather than global function 'triple' in module >> '__lldb_expr_52' >> return triple(self) // Error here >> ^ >> Test.playground:5:16: note: use '__lldb_expr_52.' to reference the global >> function in module '__lldb_expr_52' >> return triple(self) // Error here >> ^ >> __lldb_expr_52. >> >> >> Notice where the error says, “use of 'triple' refers to instance method >> 'triple()' rather than global function 'triple'”. >> >> Notice further that the instance method takes 0 arguments. In particular, >> “self.triple()” is a valid way to call it, and “self.triple(self)” is not. >> >> It is true that the instance method could be called as a type method with 1 >> argument, “Int.triple(self)”. However, “triple(self)” is not a valid way to >> call the type method, which we can demonstrate by removing the global >> function entirely: >> >> >> extension Int { >> func triple() -> Int { >> return triple(self) // Error here >> } >> } >> >> >> This time the error reads: >> >> Playground execution failed: >> error: Test.playground:3:23: error: argument passed to call that takes no >> arguments >> return triple(self) >> ~^~~~~ >> >> >> So the compiler correctly recognizes that “triple(self)” is not a valid call >> to the instance method. Indeed, it has the wrong arity. From there, it seems >> to me a small step to reason that, in the case where a function with the >> proper signature *does* exist, that it should be called. >> >> • • • >> >> Also, as a minor point, going back to the original code, notice there are >> two diagnostic messages. The second one says, “use '__lldb_expr_52.' to >> reference the global function”. However, that does not work, and indeed >> every time I run the playground the number shown changes. >> >> So it seems that in a playground, the diagnostic is incorrect, as the >> proposed solution does not work. Is there in fact a way to specify the >> module for a playground, so as to unambiguously call a global function? > > That doesn’t work at the REPL because LLDB is handing you a new module > context every time you execute an expression. When you factor this into a > playground/framework/executable you can disambiguate with the name of the > module. > >> >> • • • >> >> In any case, the proper behavior seems clear-cut to my mind. The shorthand >> for calling an instance method without “self.” should apply only if there is >> a matching instance method to call. When there is no instance method which >> could possibly match, but there is a global function that does, then the >> unqualified call should resolve to the global function. > > You may be able to get away with this by teaching lookup for overloads to > pull in global declarations, but you’ll need to adjust the ranking to > penalize this as well. This is assuming there aren’t scoping issues we’re > ignoring with a rule that, at first blush, seems like common sense. I’m not > sure this is StarterBug material - but updating the diagnostic to be more > clear would definitely be.
This is definitely a change that would need to go through swift-evolution. There are a number of potential issues and possibilities for breaking existing code that’s relying on this shadowing behavior, intentionally or unintentionally. Jordan
_______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev