Get rid of the "rust-call" hack

4ac7378
Opened by Adolfo Ochagavía at 2020-04-18 12:38:12

Based on https://github.com/rust-lang/rfcs/pull/1921#issuecomment-282164515

Currently, we fake variadics by defining functions with the rust-call ABI. These functions receive a tuple as parameter (of arbitrary arity and types), but in their ABI the tuple is expanded. It would be great to get rid of this hack and in the process pave the way for the eventual feature of variadic generics.

  1. @eddyb would you be willing to mentor me on this issue?

    Adolfo Ochagavía at 2017-04-04 12:15:23

  2. @aochagavia Sure thing, poke me on IRC.

    Eduard-Mihai Burtescu at 2017-04-06 18:22:14

  3. One way to start would be to modify https://github.com/rust-lang/rust/blob/44855a4cef3e83c76c386fdcf034447a8ee128e4/src/librustc/ty/context.rs#L1407 to replace RustCall with Rust by expanding the last argument in-place, if it's a concrete tuple (not a parameter). However, that might not be the only place that you'd need to modify to get that working. But if you get it to consistently do that, then trans should be able to expect RustCall to never exist.

    Eduard-Mihai Burtescu at 2017-04-06 19:20:44

  4. I think I am missing some context. Just to make things clear for myself, this issue is about implementing variadic generics in rustc without changing the syntax, right? In my understanding, variadic generics provide the ability to create traits where functions accept arbitrary arguments, specified by the implementor. Something like the code below:

    trait VariadicTrait<Args> {
        fn variadic_fn(&self, args: Args);
    }
    
    impl VariadicTrait<(&'static str,)> for () {
        fn variadic_fn(&self, (s,): (&'static str,)) {
            println!("{}", s)
        }
    }
    
    fn main() {
        ().variadic_fn(("hi",))
    }
    

    Previous code compiles perfectly in stable Rust, though it looks ugly. From my perspective, this looks like we already have variadic generics. However, this can't be true, so what am I missing?

    Also, one of the problems with the code above is that the tuple is not expanded in the ABI, which is bad for performance (IIRC). Is this the problem we are trying to solve here? Would it be enough to infer whether a tuple parameter needs to be expanded? That way we wouldn't need "rust-call" anymore.

    Adolfo Ochagavía at 2017-04-10 08:04:35

  5. @aochagavia The problem is that you can't write this:

    trait VariadicTrait<Args> {
        fn variadic_fn(&self, ...Args);
    }
    

    That is, true variadic functions, that for Args being a given tuple they become regular functions (e.g. fn(&self, A, B) for Args = (A, B)).

    Removing "rust-call" from the source would more or less require VG to be implemented, at that's ways off - what we can do now, however, is desugar "rust-call" into an internal VG-like form, or at least expand it into regular functions as early as possible - so that it doesn't have to be manually handled by backends.

    Eduard-Mihai Burtescu at 2017-04-10 09:23:39

  6. Triage: no changes I'm aware of.

    Steve Klabnik at 2018-09-24 16:14:57

  7. I started a branch of this but had to lower priority on it.

    Eduard-Mihai Burtescu at 2018-09-24 17:53:41