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

Fix Issue 12100 - __GENTYPE to generate ever different types #5633

Closed
wants to merge 1 commit into from

Conversation

Biotronic
Copy link
Contributor

This PR fixes https://issues.dlang.org/show_bug.cgi?id=12100 by adding the construct GENSYM, which creates a unique string intended for use with template default parameters for e.g. Typedef:

struct Typedef(T, string cookie = \_\_GENSYM\_\_) {
    T payload;
    alias payload this;
}

alias T1 = Typedef!(int);
alias T2 = Typedef!(int);
static assert(!is(T1 == T2));

@dlang-bot
Copy link
Contributor

Fix Bugzilla Description
12100 __GENTYPE to generate ever different types



/***********************************************************
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use existing comment style.

@Biotronic
Copy link
Contributor Author

Thanks @9rnsr.

@9rnsr
Copy link
Contributor

9rnsr commented Apr 6, 2016

You need to add test cases to check the new feature behavior.

@Biotronic Biotronic force-pushed the gensym branch 2 times, most recently from cd7ac2e to 03fbac3 Compare April 6, 2016 05:26
@WalterBright
Copy link
Member

It might be much simpler, and more flexible, to have COUNTER. COUNTER could then be used to generate unique types, unique identifiers, unique symbols, as required.

@yebblies
Copy link
Member

yebblies commented Apr 6, 2016

The idea ends up horribly broken with separate compilation. Depending on the order of analysis, the 'same' declaration will be passed different numbers. If it's entirely internal then it will work, but with inlining and templates that's hard to guarantee.

My preferred way is to use a struct, since these have stable but unique names. The downside is that you need to declare the struct yourself to get a unique name.

@Biotronic
Copy link
Contributor Author

@yebblies that's the exact reason I decided to use the mangled name of the instantiation scope instead of COUNTER. Do you have an example of where separate compilation will break this?

@9rnsr
Copy link
Contributor

9rnsr commented Apr 6, 2016

@Biotronic In old days, the name of function literal and delegate literal (FuncExp) had used global unique counter, and it had horribly broken. Now, it's uniquely named by using scope local numbers in FuncExp.genIdent.

@Biotronic
Copy link
Contributor Author

@9rnsr That sounds a whole lot like what I'm doing here. Some examples of what to expect:

module bar;
struct Ham(string gensym = __GENSYM__) {
    enum s = gensym;
}
module foo;
import bar;

struct S {
    static assert(__GENSYM__ == "G3foo1S1");
    static assert(__GENSYM__ == "G3foo1S2");
}

void baz() {
    static assert(__GENSYM__ == "G_D3foo3bazFZv1");
    static assert(__GENSYM__ == "G_D3foo3bazFZv2");
}

static assert(__GENSYM__ == "G3foo1");
static assert(__GENSYM__ == "G3foo2");

void main() {
    static assert(__GENSYM__ == "G_Dmain1");
    static assert(__GENSYM__ == "G_Dmain2");
    static assert(Ham!().s == "G_Dmain3");
    static assert(Ham!().s == "G_Dmain4");
}

@WalterBright
Copy link
Member

I'm wondering if this could be done using a library function and CTFE rather than building it into the core language.

@Biotronic
Copy link
Contributor Author

Currently, no. That would require storing some information between calls to ctfeGensym().

The closest you get currently is the use of MODULE and LINE. That fails for at least these cases:

auto ctfeGensym(string mod = __MODULE__, int line = __LINE__)() {
    import std.conv;
    pragma(msg, mod ~ line.to!string);
    return mod ~ line.to!string;
}

enum a = ctfeGensym(); enum b = ctfeGensym();
static assert(a != b); // Fails.

enum s= "enum c = ctfeGensym();
enum d = ctfeGensym();";

mixin(s);
enum e = ctfeGensym();
static assert(e != d); // Fails.

The last example incidentally also shows a case where adding COLUMN wouldn't help.

Without a way to transmit information between calls to ctfeGensym, I don't think this problem can be solved in a library.

@WalterBright
Copy link
Member

Yeah, I forgot about CTFE not allowing any global state. Lemme think about this some more.

@AndrejMitrovic
Copy link
Contributor

It seems that the entire benefit of implementing this unique compile-time string generation is to enable the hack workaround to make Typedefs behave as expected. Is that the only use-case? Because if so we should think about solving the Typedef problem in some other way..

@MetaLang
Copy link
Member

MetaLang commented May 7, 2016

@AndrejMitrovic It's useful for any auto-generated types that need to be unique. See this thread, for example: http://forum.dlang.org/post/yfeavyrdsqdchexmggih@forum.dlang.org

@AndrejMitrovic
Copy link
Contributor

Cool, thanks! So it seems there's precedent from other languages (lisp), that's good.

@AndrejMitrovic
Copy link
Contributor

@yebblies @WalterBright are we not allowed to use D hashmaps in the front-end? And actually I'm pretty sure there's a hashmap implementation somewhere in the source files as an alternative. It would simplify the code quite a bit here.

@AndrejMitrovic
Copy link
Contributor

Otherwise we shouldn't use an array for the lookup (slow lookups), there's a mix of int and size_t used in the code, and using %d for printing an unsigned integer is unsafe.

@maxhaton
Copy link
Member

@RazvanN7 we should probably close this for now

@ljmf00
Copy link
Member

ljmf00 commented Mar 13, 2022

@RazvanN7 we should probably close this for now

Is there any alternative to produce this/similar behavior?

@dkorpel dkorpel added the Review:Phantom Zone Has value/information for future work, but closed for now label Jun 18, 2023
@dkorpel dkorpel closed this Jun 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.