If you hadn’t written the ref pattern, then it would consume y by-value when you match it against a pattern – then written just “Some(x)” – which would mean it can only happen once, hence the closure would be onlyFnOnce.
So maybe the code you share here is slightly different than the “Some(ref x)” pattern you’re sharing here.
Or maybe you’re getting confused by closure traits… every Fn-closure is in fact also implementing FnOnce, so if you written something like this, you might be drawing wrong conclusions. (Always test the expected compilation errors, too ^^)
A last idea on what could be going on: maybe possibly some IDE functionality may tell you about closure properties / types, and if that’s based on over-simplified heuristics that ignore ref-patterns, it may tell you a difference where actually no relevant difference exists.
Edit: It’s also possible to make an Fn closure look like it’s onlyFnOnce by passing it through some abstraction. E.g. pass it to a function that expects impl FnOnce(…) -> …, and inside that function you can’t use it like an Fn anymore. Or return it from a function with an opaque impl FnOnce(…) -> … return type, then the caller can only use it as an FnOnce, either. Similarly, if converted to a Box<dyn FnOnce(…) -> …>, of course.
Of course, you’ll simply have to share your full test case for us to really figure out what happened
Inside a function, that's similar to how you can't copy something if you only have a Clone bound, even if what was passed in does actually implement Copy.
But directly passing to a function that expects impl FnOnce(...) actually has further implications than other traits. The same "closure inference override" that we rely on to fix closures that take and return any lifetime inhibits the compiler from attempting to implement FnMut(...) or Fn(...) at all.
Yes for some reason it picks a more restrictive trait than it should. This PR was the one that added closures inlay hints. There are tests (in this file) that seem to show it should provide the correct closure type.
I couldn't find an issue related to this.
Maybe not "more restrictive". I extended the text area and saw more of the type hint. It says impl FnOnce() -> bool = move(y) for first case, and impl Fn() -> bool = move(&y) for second case. Seems like it "moves" different things.