Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different static variables for different instances of a generic function #2130

Closed
hajifkd opened this Issue Aug 27, 2017 · 7 comments

Comments

Projects
None yet
6 participants
@hajifkd
Copy link

hajifkd commented Aug 27, 2017

Currently, different instances of a generic function have an identical static variable.

For example, the following code

fn foo<T>() {
    use std::sync::{Once, ONCE_INIT};

    static INIT: Once = ONCE_INIT;

    INIT.call_once(|| {
        // run initialization here
        println!("Called");
    });
}

fn main() {
    foo::<i64>();
    foo::<i64>();
    foo::<isize>();
}

calls println! just once. This is because the entities of the static variable INIT are the same for each different instance of the generic function foo.
(Well, actually I have asked this in stackoverflow, but I only got a workaround to use HashMap essentially. Using dynamical way to dispatch static code sounds a bit uncomfortable. )

I feel this behavior of generic functions and static variables is counter-intuitive since each instances of generic functions have different name in assembly and thus they are different function.
Of course, I agree that changing it loses compatibility and may not be good, so I would like to ask whether there is any room to add a new syntax or something to allow for different instances of a generic function to have different static variables. I feel this is important especially when we "translate" some C++ template code into Rust.

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Aug 27, 2017

FWIW the Rust semantics are "if you can write outside a function, putting it inside a block expression will only change where you can refer to it by name and nothing else".

So you can embed entire modules in an expression - not only in functions but also array lengths, and they behave the same as outside, except name resolution can get a bit confusing in some cases.

@burdges

This comment has been minimized.

Copy link

burdges commented Aug 27, 2017

I'd imagine you want polymorphic/generic statics for this :

    ...
    struct OnceAndPhandom<T>(Once,PhandomData<T>);
    static INIT: OnceAndPhandom<T> = (ONCE_INIT,PhandomData);
    INIT.0.call_once(|| {
        ...

Also, the polymorphic/generic consts proposed in #1945 look useful too, ala

pub const OK<E>: Result<(),E> = Ok(());

I wonder if this could be merged with #1945 but even if not that might give you ideas about what the RFC should look like.

@hajifkd

This comment has been minimized.

Copy link
Author

hajifkd commented Aug 27, 2017

@eddyb Okay, I agree that if we treat T as just like a argument or a variable, then as you said this result is consistent.
But, considering assembly and that different instances of a generic function have different name, the above code looks similar to something like

fn foo1() {
    static A: i64 = 1i64;
    println!("{}", A);
}

fn foo2() {
    static A: i64 = 2i64;
    println!("{}", A);
}

, where two As are completely independent. Anyway, I believe some kind of static dispatch system is useful.

@burdges Generic statics indeed seems to solve my problem as you wrote although I have no idea what should happen in the following example:

fn foo<T, S>() {
    ...
    struct OnceAndPhandom<T>(Once,PhandomData<T>);
    static INIT: OnceAndPhandom<T> = (ONCE_INIT,PhandomData);
    INIT.0.call_once(|| {
        ...
}

fn main() {
    foo<i64, usize>();
    foo<i64, f64>();
}
@SimonSapin

This comment has been minimized.

Copy link
Contributor

SimonSapin commented Aug 27, 2017

@eddyb

This comment has been minimized.

Copy link
Member

eddyb commented Aug 27, 2017

Okay, I agree that if we treat T as just like a argument or a variable, then as you said this result is consistent.

All you have to do for consistency is to move anything that can be written outside a function, outside.

@sanmai-NL

This comment has been minimized.

Copy link

sanmai-NL commented Oct 16, 2017

@hajifkd: Can this issue be closed now?

@hajifkd

This comment has been minimized.

Copy link
Author

hajifkd commented Oct 18, 2017

Okay. I'm sorry to bother you.

@hajifkd hajifkd closed this Oct 18, 2017

@Centril Centril added the T-lang label Feb 23, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.