It seems like this could be a way to make const functions much more powerful. I've seen elsewhere that arbitrary loops aren't allowed in const functions, but I believe in principle the iterator HOFs should be much less likely to do bad things (e.g. map, fold, etc).
An example of what would be ideal to have as const, and in my view, there should be a way to make this const (if I am wrong, please correct me).
This may be predicated on whether or not it will be possible for Rust to tell if a particular Iterator is proven to be finite or not. I'm not sure if there's a way to do that currently.
Those can all be legally overridden to do arbitrarily-silly things, so long as they're safe (and meet the type signatures). There's certainly never a good reason to override map (since it just constructs an adapter), but it's still possible. So the problem of calling arbitrary code in traits still remains.
(Which is the real problem here -- as bluss mentioned, loops are already allowed.)
I don't think that's an issue. If the iterator is infinite then compilation can fail after a timeout, and I think that's ok.
The issue of overriding map and fold to do weird things can be addressed by "blessing" the built-in implementations in a way that custom impls cannot do. Then the "only" remaining thing is to require that all mapping and folding functions are const too. Whether or not that is practical to do is another matter!
It's the iterator impl itself that's the problem. Iterator::next() cannot be const because it takes &mut self. Some "weird" override of map could return an iterator, WeirdMap<I, F>, that breaks assumptions that the compiler needs to make about map.
That's an interesting idea, though as it still breaks referential transparency, it isn't really pure, I think.
Perhaps an alternative is to keep the standard iterators as they are, define non-mutative operations on non-stateful collections (such as Vecs and arrays). I'm afraid, being fairly new to Rust, I don't know enough to know how to do this generically yet, and I probably won't try looking into it right away as I still have a lot on my list to read to that end.
I know that the initial RFC for const functions was specifically about free functions (and methods it seems) but I don't see why an RFC couldn't be created for trait const functions.
(I even have some ideas, maybe I should start a new thread)
Yes, I really think the lack of trait const fns hurts: for instance, it isn't even possible to perform a clone() in a const fn currently (though it is possible to dereference in some cases).
const fn-s were allowed to assign fields through &mut references
const fn-s were allowed to take &mut references to local variables
Wouldn't this bring Rust closer to being able to use iterators in const fn-s?
"Top level" `const` expressions would still be unable to produce `&mut`. Therefore the only `&mut`-s around would be to data on stack. So these `&mut` seem no more dangerous than `mut` local bindings which are already allowed.
Of course this conflicts with heap allocations ever becoming allowed in const contexts. But heap allocations are already a problem. Some mechanism would be needed to prevent them from escaping const fn-s. And the same mechanism could then potentially solve the conflict with &mut.
I'm still a bit unnerved by the idea of const fn allowing &mut arguments, but it is a good point. Perhaps a different demarcation is worthwhile here, though I'm not sure of a good term. Let's call it mutconst for the three allowances you listed. Then, although mutconst function itself is not const, a function could still be const if it calls a mutconst function, which I believe opens up a range of possibilities. For instance, if the Iterator functions were mutconst, then although they couldn't directly be used in a const context (since the might be mutating things outside function scope), they could still be used when they consume/drop the mutated variable, such as in the original function example I listed:
You should really look into what the const-eval working group is looking into, because I'm pretty sure they are in the process of solving these issues already.
Actually.. is it at all possible to call this meaningfully from a const expression?
Wouldn't creating a non-empty Vec require heap allocation which is presently not supported in const?