Language integrated query comprehension is also duck-typed, so if you explicitly implemented Select and Where and friends to all return appropriately crafted structs, you could write full LINQ queries and enumerate them without heap allocations.
But you’re right that to use LINQ to objects you must have an IEnumerable because you rely on the type to bring in the extension methods.
Be interesting to imagine what c# language features would be needed to deliver a stack-allocatable LINQ...
My LinqFaster repo has some benchmarks showing time differences for some common operations in a fairly worst case scenario (where the work done in each iteration is small) https://github.com/jackmott/LinqFaster
It would just be nice if C# reliably compiled this abstraction down to efficient code, the way C++, Rust, and Java Streams do.