From Apple's documentation:
The #dynamicCallable attribute lets you call named types like you call
functions using a simple syntactic sugar. The primary use case is
dynamic language interoperability.
Why would you want to use an #dynamicCallable instead of direct approch?
#dynamicCallable is a new feature of Swift 5. From Paul Hudson's article on "How to use #dynamicCallable in Swift" (emphasis mine):
SE-0216 adds a new #dynamicCallable attribute to Swift, which
brings with it the ability to mark a type as being directly callable.
It’s syntactic sugar rather than any sort of compiler magic,
effectively transforming this code:
let result = random(numberOfZeroes: 3)
Into this:
let result = random.dynamicallyCall(withKeywordArguments: ["numberOfZeroes": 3])
[...] #dynamicCallable is the natural extension of
#dynamicMemberLookup [SE-0195], and serves the same purpose: to
make it easier for Swift code to work alongside dynamic languages such
as Python and JavaScript. [...] #dynamicCallable is really flexible about which data
types its methods accept and return, allowing you to benefit from all
of Swift’s type safety while still having some wriggle room for
advanced usage.
Introduce user-defined dynamically "callable" types
Proposal: SE-0216
Authors: Chris Lattner, Dan Zheng
Review Manager: John McCall
Implementation: apple/swift#20305
Decision Notes: Rationale
Status: Implemented (Swift 5)
Introduction
This proposal is a follow-up to SE-0195 - Introduce User-defined "Dynamic Member
Lookup" Types,
which shipped in Swift 4.2. It introduces a new #dynamicCallable attribute, which marks
a type as being "callable" with normal syntax. It is simple syntactic sugar
which allows the user to write:
a = someValue(keyword1: 42, "foo", keyword2: 19)
and have it be rewritten by the compiler as:
a = someValue.dynamicallyCall(withKeywordArguments: [
"keyword1": 42, "": "foo", "keyword2": 19
])
Many other languages have analogous features (e.g. Python "callables", C++ operator(), and
functors in many other languages), but the
primary motivation of this proposal is to allow elegant and natural interoperation with
dynamic languages in Swift.
Swift-evolution threads:
- Pitch: Introduce user-defined dynamically "callable"
types.
- Pitch #2: Introduce user-defined dynamically “callable”
types.
- Current pitch thread: Pitch #3: Introduce user-defined dynamically “callable”
types
Motivation and context
Swift is exceptional at interworking with existing C and Objective-C APIs and
we would like to extend this interoperability to dynamic languages like Python,
JavaScript, Perl, and Ruby. We explored this overall goal in a long design
process wherein the Swift evolution community evaluated multiple different
implementation approaches. The conclusion was that the best approach was to put
most of the complexity into dynamic language specific bindings written as
pure-Swift libraries, but add small hooks in Swift to allow these bindings to
provide a natural experience to their clients.
SE-0195
was the first step in this process, which introduced a binding to naturally
express member lookup rules in dynamic languages.
What does interoperability with Python mean? Let's explain this by looking at
an example. Here's some simple Python code:
class Dog:
def __init__(self, name):
self.name = name
self.tricks = [] # creates a new empty list for each `Dog`
def add_trick(self, trick):
self.tricks.append(trick)
With the SE-0195 #dynamicMemberLookup feature
introduced in Swift 4.2, it is possible to implement a Python interoperability
layer
written in Swift. It interoperates with the Python runtime, and project all
Python values into a single PythonObject type. It allows us to call into the
Dog class like this:
// import DogModule.Dog as Dog
let Dog = Python.import.call(with: "DogModule.Dog")
// dog = Dog("Brianna")
let dog = Dog.call(with: "Brianna")
// dog.add_trick("Roll over")
dog.add_trick.call(with: "Roll over")
// dog2 = Dog("Kaylee").add_trick("snore")
let dog2 = Dog.call(with: "Kaylee").add_trick.call(with: "snore")
This also works with arbitrary other APIs as well. Here is an example working
with the Python pickle API and the builtin Python function open. Note that
we choose to put builtin Python functions like import and open into a
Python namespace to avoid polluting the global namespace, but other designs
are possible:
// import pickle
let pickle = Python.import.call(with: "pickle")
// file = open(filename)
let file = Python.open.call(with: filename)
// blob = file.read()
let blob = file.read.call()
// result = pickle.loads(blob)
let result = pickle.loads.call(with: blob)
This capability works well, but the syntactic burden of having to use
foo.call(with: bar, baz) instead of foo(bar, baz) is significant. Beyond
the syntactic weight, it directly harms code clarity by making code hard to
read and understand, cutting against a core value of Swift.
The proposed #dynamicCallable attribute directly solves this problem.
With it, these examples become more natural and clear, effectively matching the
original Python code in expressiveness:
// import DogModule.Dog as Dog
let Dog = Python.import("DogModule.Dog")
// dog = Dog("Brianna")
let dog = Dog("Brianna")
// dog.add_trick("Roll over")
dog.add_trick("Roll over")
// dog2 = Dog("Kaylee").add_trick("snore")
let dog2 = Dog("Kaylee").add_trick("snore")
Python builtins:
// import pickle
let pickle = Python.import("pickle")
// file = open(filename)
let file = Python.open(filename)
// blob = file.read()
let blob = file.read()
// result = pickle.loads(blob)
let result = pickle.loads(blob)
This proposal merely introduces a syntactic sugar - it does not add any new
semantic model to Swift. We believe that interoperability with scripting
languages is an important and rising need in the Swift community, particularly
as Swift makes inroads into the server development and machine learning
communities. This feature is also precedented in other languages (e.g. Scala's
Dynamic trait), and
can be used for other purposes besides language interoperability (e.g.
implementing dynamic proxy objects).
Proposed solution
We propose introducing a new #dynamicCallable attribute to the Swift language
which may be applied to structs, classes, enums, and protocols. This follows
the precedent of
SE-0195.
Before this proposal, values of these types are not valid in a call expression:
the only existing callable values in Swift are those with function types
(functions, methods, closures, etc) and metatypes (which are initializer
expressions like String(42)). Thus, it is always an error to "call" an
instance of a nominal type (like a struct, for instance).
With this proposal, types with the #dynamicCallable attribute on their
primary type declaration become "callable". They are required to implement at
least one of the following two methods for handling the call behavior:
func dynamicallyCall(withArguments: <#Arguments#>) -> <#R1#>
// `<#Arguments#>` can be any type that conforms to `ExpressibleByArrayLiteral`.
// `<#Arguments#>.ArrayLiteralElement` and the result type `<#R1#>` can be arbitrary.
func dynamicallyCall(withKeywordArguments: <#KeywordArguments#>) -> <#R2#>
// `<#KeywordArguments#>` can be any type that conforms to `ExpressibleByDictionaryLiteral`.
// `<#KeywordArguments#>.Key` must be a type that conforms to `ExpressibleByStringLiteral`.
// `<#KeywordArguments#>.Value` and the result type `<#R2#>` can be arbitrary.
// Note: in these type signatures, bracketed types like <#Arguments#> and <#KeywordArguments#>
// are not actual types, but rather any actual type that meets the specified conditions.
As stated above, <#Arguments#> and <#KeywordArguments#> can be any types
that conform to the
ExpressibleByArrayLiteral
and
ExpressibleByDictionaryLiteral
protocols, respectively. The latter is inclusive of
KeyValuePairs,
which supports duplicate keys, unlike Dictionary.
Thus, using KeyValuePairs is recommended to support duplicate keywords and
positional arguments (because positional arguments are desugared as keyword
arguments with the empty string "" as the key).
If a type implements the withKeywordArguments: method, it may be dynamically
called with both positional and keyword arguments: positional arguments have
the empty string "" as the key. If a type only implements the
withArguments: method but is called with keyword arguments, a compile-time
error is emitted.
Since dynamic calls are syntactic sugar for direct calls to dynamicallyCall
methods, additional behavior of the dynamicallyCall methods is directly
forwarded. For example, if a dynamicallyCall method is marked with throws
or #discardableResult, then the corresponding sugared dynamic call will
forward that behavior.
Ambiguity resolution: most specific match
Since there are two #dynamicCallable methods, there may be multiple ways to
handle some dynamic calls. What happens if a type specifies both the
withArguments: and withKeywordArguments: methods?
We propose that the type checker resolve this ambiguity towards the tightest
match based on syntactic form of the expression. The exact rules are:
If a #dynamicCallable type implements the withArguments: method and it is
called with no keyword arguments, use the withArguments: method.
In all other cases, attempt to use the withKeywordArguments: method.
This includes the case where a #dynamicCallable type implements the
withKeywordArguments: method and it is called with at least one keyword
argument.
This also includes the case where a #dynamicCallable type implements only
the withKeywordArguments: method (not the withArguments: method) and
it is called with no keyword arguments.
If #dynamicCallable type does not implement the withKeywordArguments:
method but the call site has keyword arguments, an error is emitted.
Here are some toy illustrative examples:
#dynamicCallable
struct Callable {
func dynamicallyCall(withArguments args: [Int]) -> Int { return args.count }
}
let c1 = Callable()
c1() // desugars to `c1.dynamicallyCall(withArguments: [])`
c1(1, 2) // desugars to `c1.dynamicallyCall(withArguments: [1, 2])`
c1(a: 1, 2) // error: `Callable` does not define the 'withKeywordArguments:' method
#dynamicCallable
struct KeywordCallable {
func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Int {
return args.count
}
}
let c2 = KeywordCallable()
c2() // desugars to `c2.dynamicallyCall(withKeywordArguments: [:])`
c2(1, 2) // desugars to `c2.dynamicallyCall(withKeywordArguments: ["": 1, "": 2])`
c2(a: 1, 2) // desugars to `c2.dynamicallyCall(withKeywordArguments: ["a": 1, "": 2])`
#dynamicCallable
struct BothCallable {
func dynamicallyCall(withArguments args: [Int]) -> Int { return args.count }
func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Int {
return args.count
}
}
let c3 = BothCallable()
c3() // desugars to `c3.dynamicallyCall(withArguments: [])`
c3(1, 2) // desugars to `c3.dynamicallyCall(withArguments: [1, 2])`
c3(a: 1, 2) // desugars to `c3.dynamicallyCall(withKeywordArguments: ["a": 1, "": 2])`
This ambiguity resolution rule works out naturally given the behavior of the
Swift type checker, because it only resolves call expressions when the type
of the base expression is known. At that point, it knows whether the base is a
function type, metatype, or a valid #dynamicCallable type, and it knows the
syntactic form of the call.
This proposal does not require massive or invasive changes to the constraint
solver. Please look at the implementation for more details.
Example usage
Here, we sketch some example bindings to show how this could be used in
practice. Note that there are lots of design decisions that are orthogonal to
this proposal (e.g. how to handle exceptions) that we aren't going into here.
This is just to show how this feature provides an underlying facility that
language bindings authors can use to achieve their desired result. These
examples also show #dynamicMemberLookup to illustrate how they work together,
but elides other implementation details.
JavaScript supports callable objects but does not have keyword arguments.
Here is a sample JavaScript binding:
#dynamicCallable #dynamicMemberLookup
struct JSValue {
// JavaScript doesn't have keyword arguments.
#discardableResult
func dynamicallyCall(withArguments: [JSValue]) -> JSValue { ... }
// This is a `#dynamicMemberLookup` requirement.
subscript(dynamicMember member: JSValue) -> JSValue {...}
// ... other stuff ...
}
On the other hand, a common JavaScript pattern is to take a dictionary of
values as a stand-in for argument labels (called like
example({first: 1, second: 2, third: 3}) in JavaScript). A JavaScript bridge
in Swift could choose to implement keyword argument support to allow this to be
called as example(first: 1, second: 2, third: 3) from Swift code (kudos to
Ben Rimmington for this
observation).
Python does support keyword arguments. While a Python binding could implement
only the withKeywordArguments: method, it is be better to implement both the
non-keyword and keyword forms to make the non-keyword case slightly more
efficient (avoid allocating temporary storage) and to make direct calls with
positional arguments nicer (x.dynamicallyCall(withArguments: 1, 2) instead of
x.dynamicallyCall(withKeywordArguments: ["": 1, "": 2])).
Here is a sample Python binding:
#dynamicCallable #dynamicMemberLookup
struct PythonObject {
// Python supports arbitrary mixes of keyword arguments and non-keyword
// arguments.
#discardableResult
func dynamicallyCall(
withKeywordArguments: KeyValuePairs<String, PythonObject>
) -> PythonObject { ... }
// An implementation of a Python binding could choose to implement this
// method as well, avoiding allocation of a temporary array.
#discardableResult
func dynamicallyCall(withArguments: [PythonObject]) -> PythonObject { ... }
// This is a `#dynamicMemberLookup` requirement.
subscript(dynamicMember member: String) -> PythonObject {...}
// ... other stuff ...
}
Limitations
Following the precedent of SE-0195, this attribute must be placed on the
primary definition of a type, not on an extension.
This proposal does not introduce the ability to provide dynamically callable
static/class members. We don't believe this is important given the goal of
supporting dynamic languages like Python, but it could be explored if a use
case is discovered in the future. Such future work should keep in mind that
call syntax on metatypes is already meaningful, and that ambiguity would have
to be resolved somehow (e.g. through the most specific rule).
This proposal supports direct calls of values and methods, but subsets out
support for currying methods in Smalltalk family languages. This is just an
implementation limitation given the current state of currying in the Swift
compiler. Support can be added in the future if there is a specific need.
Source compatibility
This is a strictly additive proposal with no source breaking changes.
Effect on ABI stability
This is a strictly additive proposal with no ABI breaking changes.
Effect on API resilience
This has no impact on API resilience which is not already captured by other
language features.
Future directions
Dynamic member calling (for Smalltalk family languages)
In addition to supporting languages like Python and JavaScript, we would also
like to grow to support Smalltalk derived languages like Ruby and Squeak. These
languages resolve method calls using both the base name as well as the
keyword arguments at the same time. For example, consider this Ruby code:
time = Time.zone.parse(user_time)
The Time.zone reference is a member lookup, but zone.parse(user_time) is a
method call, and needs to be handled differently than a lookup of zone.parse
followed by a direct function call.
This can be handled by adding a new #dynamicMemberCallable attribute, which
acts similarly to #dynamicCallable but enables dynamic member calls (instead
of dynamic calls of self).
#dynamicMemberCallable would have the following requirements:
func dynamicallyCallMethod(named: S1, withArguments: [T5]) -> T6
func dynamicallyCallMethod(named: S2, withKeywordArguments: [S3 : T7]) -> T8
Here is a sample Ruby binding:
#dynamicMemberCallable #dynamicMemberLookup
struct RubyObject {
#discardableResult
func dynamicallyCallMethod(
named: String, withKeywordArguments: KeyValuePairs<String, RubyObject>
) -> RubyObject { ... }
// This is a `#dynamicMemberLookup` requirement.
subscript(dynamicMember member: String) -> RubyObject {...}
// ... other stuff ...
}
General callable behavior
This proposal is mainly directed at dynamic language interoperability. For this
use case, it makes sense for the dynamicallyCall method to take a
variable-sized list of arguments where each argument has the same type.
However, it may be useful to support general callable behavior (akin to
operator() in C++) where the desugared "callable" method can have a fixed
number of arguments and arguments of different types.
For example, consider something like:
struct BinaryFunction<T1, T2, U> {
func call(_ argument1: T1, _ argument1: T2) -> U { ... }
}
It is not unreasonable to look ahead to a day where sugaring such things is
supported, particularly when/if Swift gets variadic
generics.
This could allow typesafe n-ary smart function pointer types.
We feel that the approach outlined in this proposal supports this direction.
When/if a motivating use case for general callable behavior comes up, we can
simply add a new form to represent it and enhance the type checker to prefer
that during ambiguity resolution. If this is a likely direction, then it may be
better to name the attribute #callable instead of #dynamicCallable in
anticipation of that future growth.
We believe that general callable behavior and #dynamicCallable are orthogonal
features and should be evaluated separately.
Alternatives considered
Many alternatives were considered and discussed. Most of them are captured in
the "Alternatives Considered" section of
SE-0195.
Here are a few points raised in the discussion:
It was suggested that we use subscripts to represent the call
implementations instead of a function call, aligning with
#dynamicMemberLookup. We think that functions are a better fit here: the
reason #dynamicMemberLookup uses subscripts is to allow the members to be
l-values, but call results are not l-values.
It was requested that we design and implement the 'static callable' version
of this proposal in conjunction with the dynamic version proposed here. In
the author's opinion, it is important to consider static callable support as
a likely future direction to make sure that the two features sit well next
to each other and have a consistent design (something we believe this
proposal has done) but it doesn't make sense to join the two proposals. So
far, there have been no strong motivating use case presented for the static
callable version, and Swift lacks certain generics features (e.g. variadics)
that would be necessary to make static callables general. We feel that static
callable should stand alone on its own merits.
In JavaScript we have something like .toString which can convert the entire function object to string.
Do we have something similar on IOS?
For example, in JavaScript if we have function like this, after converting it with .toString and printing the value in console we see the entire function object.
function sum(a, b)
{
return a + b;
}
console.log(sum.toString());
// expected output:
// "function sum(a, b)
// {
//return a + b;
// }"
Can we do something similar for IOS? I tried String (describing :Function) in Swift but that didn't work and gave me output as (Function) but not the complete structure like we get in JavaScript .toString.
public func say_hello()
{
print("Hello, World!")
}
String(describing: say_hello))
//Output:(Function)
Despite the many comments explaining why that's not possible (nor feasible in many cases), I want to point out that you can use JavaScript code in your Swift app and thus use the serialization mechanism of that language. Have a look at JSContext for details. This of course won't make things simpler, but it does give extra flexibility with injecting/changing/extending functionality at runtime.
This is not possible from Swift/Objc
It seems that for some reason Swift have chosen to make coding in it less readable by forcing users to remove completion handler parameter labels. I have read the Swift discussion and still think it's a mistake. At least they could have made it optional.
When building using Xcode 8 - is there a way to force the compiler to use Swift 2.3 so I don't get these errors anymore?
I have updated the option to use legacy Swift (under build settings)
but I still seem to get this error:
Function types cannot have argument label 'isloggedIn'; use '_'
instead
How can I keep my labels in my completion handlers?
The Swift designers decided to prohibit argument labels for function types.
The reasoning is explained here: https://github.com/apple/swift-evolution/blob/master/proposals/0111-remove-arg-label-type-significance.md
This is a frustrating and questionable choice, as prohibiting argument labels makes it much easier to incorrectly invoke closures, which seems more important than simplifying the language's type system.
Usability > ideology.
A workaround to consider. You can't do:
func doStuff(completion: (foo: Int, bar: String) -> Void) {
...
completion(foo: 0, bar: "")
}
... but you can do:
func doStuff(completion: ((foo: Int, bar: String)) -> Void) {
...
completion((foo: 0, bar: ""))
}
i.e. have a single unnamed argument to your closure which is a tuple, in this case (foo: Int, bar: String).
It's ugly in its own way, but at least you retain the argument labels.
Based on the information above - it appears that the only way to really fix this and ensure that its performant is to raise a proposal to
Make argument labels optional with a view to :
improving the speed of development ( without argument labels it requires us to scroll up to the top of the method each time we put in the completion handler.
Reduce Errors : ( I have already had several errors caused due to incorrect completion handler entries especially with those that expect boolean values)
Make code more readable across team members. Not everyone has only one team member and thus being able to easily pick up other peoples code is a must have.
Lastly good programming practice means that the solution should look as much like the actual item being developed. completionhandler: (newvalues, nil) looks less like the item being managed than completionhandler(results: newValue, error:nil)
I would love for people reading this to share their feedback/ comments
on this below before I submit it so I can show there are others that
support this.
Edit:
I have submitted the pitch here :
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20161010/028083.html
which appears to have been agreed. It looks like its going to happen, however the discussion is whether this is submitted as a Swift 4 improvement ( highly probable)
You have to use _ to make your parameters unnamed, and that is unfortunate. Instead of tacking _ on to each parameter and then blindly calling your function I would suggest making a wrapper object.
Since losing named parameters for function types introduces more risk that you will call the function with the wrong values, I would suggest wrapping the parameters in a struct and having that be the one and only parameter to your function.
This way the fields of you struct are named, and there is only one type of value to pass into your function. It is more cumbersome than if we were able to name the parameters of the function, but we can't. At least this way you'll be safer and you'll feel less dirty.
struct LineNoteCellState {
var lineNoteText: String?
var printOnInvoice = false
var printOnLabel = false
}
Here is an example of it being used:
cell.configure(editCallback: { (_ state: LineNoteCellState) in
self.lineNoteText = state.lineNoteText
self.printOnInvoice = state.printOnInvoice
self.printOnLabel = state.printOnLabel
})
Semi-workaround, note the _
completion: (_ success: Bool) -> Void
I am having difficulty referring to parameterless functions in Fable.
With this example:
let f1 () =
1
let someRefTof1 = f1
I'd expect the generated js to look something like this:
function f1() {
return 1;
}
var someRefTof1 = f1;
but what I actually get is:
function f1() {
return 1;
}
var someRefTof1 = exports.someRefTof1 = function someRefTof1(arg00_) {
return f1(arg00_);
};
I'm unclear on the purpose of arg00_ or how to avoid it being generated?
(As a bit of background, I am struggling to call a function in an external js library which expects a function to be passed as a parameter)
Edit:
Background
The above is what i believe to be a minimal, verifiable, reproduction of my question but, after comments, I thought it may be useful to provide a touch more context on why this is causing issues. What I am actually trying to do is use angularjs from Fable.
So my example looks more like this:
let app = AngularFable.NgFable.angular.``module``("app",[||])
type TestCtrl() =
member this.Val1() = "boom";
app?controller("test", TestCtrl)
which gets compiled to:
var app = exports.app = angular.module("app", []);
var TestCtrl = exports.TestCtrl = function () {
function TestCtrl() {
_classCallCheck(this, TestCtrl);
}
TestCtrl.prototype.Val1 = function Val1() {
return "boom";
};
return TestCtrl;
}();
_fableCore.Util.setInterfaces(TestCtrl.prototype, [], "App.TestCtrl");
app.controller("test", function (unitVar) {
return new TestCtrl();
});
with unitVar being the problematic parameter introduced in this example. When I use this in my html with something like:
<div ng-app="app">
<div ng-controller="test as vm">
{{vm.Val1()}}
</div>
</div>
I run into an unknown provider error whereas if I simply change the compiled javascript to remove the unitVar parameter from the last line like this:
app.controller("test", function () {
return new TestCtrl();
});
then my example works as expected.
I'd really like to know if there is a way to avoid having the Fable compiler generate this parameter. I'm 99% sure this reduces to the same problem as in my original question but I've included this additional context to better explain why this is an issue
Thank you very much for your question and detailed explanations. There're two things here that are a bit tricky and are caused by optimisations both of the F# compiler and Fable.
In the AST provided by the F# compiler, methods (functions that are members of a type or module) are compiled as usual methods as in C#. This is for optimization.
However, when you create an anonymous lambda or make a reference to a method, the F# compiler will keep F# semantics, that is, all functions have a single argument (as John Palmer says, unit is an argument too) and can be curried.
Ok, this info is just to make clear why the F# compiler/Fable represent methods and lambdas differently. Let's go with the issue of argumentless functions: the obvious solution would be of course to remove the F# compiler generated argument for functions accepting unit (as it's already done for methods). In fact, I also had problems with libraries like Mocha because of this.
I did try to remove the unit argument at the beginning but I got fails in some scenarios because of this. TBH, I don't remember now exactly which tests were failing but because of the expectation that there'll be always an argument, in some cases function composition or inlining was failing when the unit argument was removed.
Other attempts to modify the semantics of F# functions in the JS runtime have always failed because they don't cover all scenarios. However, we can be more lenient with delegates (System.Func<>) as it's usually safe to assume these ones should behave more like functions in languages like C# or F#. I can try to remove the unit argument just for delegates and see what happens :)
For more info about sending F# functions to JS code you can check the documentation.
UPDATE: Scratch all that, please try fable-compiler#0.6.12 and fable-core#0.6.8. This version eliminates unit arguments, the solution was actually simpler than I thought and (hopefully) shouldn't create issues with existing projects. (The explanation about methods and lambdas compiled differently still applies.)
Look at the code:
let add_one = |&: x| { 1 + x };
I know x is the closure argument, but what is the meaning of &: in the closure?
This is an underdocumented (and obsolete, see comment) section of Rust right now. The best reference I know of is the blog post Purging proc:
Because the current inference scheme is limited, you will sometimes need to specify which of the three fn traits you want explicitly. (Some people also just prefer to do that.) The current syntax is to use a leading &:, &mut:, or :, kind of like an “anonymous parameter”:
// Explicitly create a `Fn` closure.
foo(|&:| { ... })
// Explicitly create a `FnMut` closure.
foo(|&mut:| { ... })
// Explicitly create a `FnOnce` closure.
foo(|:| { ... }) // (ERROR)
Caveat: It is still possible we’ll change the &:/&mut:/: syntax before 1.0; if we can improve inference enough, we might even get rid of it altogether.
And it looks like it was removed in #21843! Thanks for pointing that out, #swizard!