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

Issue 6169 - [CTFE] pure functions cannot compute constants using functions not marked as pure #652

Merged
merged 1 commit into from May 4, 2013

Conversation

yebblies
Copy link
Member

When running semantic on an expression used anywhere that forces compile time evaluation, use a scope flag to prevent purity and safety checks on function calls.
This allows more functions to be inferred @safe/pure.

http://d.puremagic.com/issues/show_bug.cgi?id=6169

@donc
Copy link
Collaborator

donc commented Feb 6, 2012

There's a huge similarity between this bug, and the gagging that occurs in speculative template instantiation (bug 4269, for example, which I'm currently working on). In both cases, semantic is run in a different mode, and a certain subset of errors need to be suppressed/ignored. I think they can both be treated in the same way.

@yebblies
Copy link
Member Author

yebblies commented Feb 6, 2012

Yeah, this is a new type of gagging (eek) but as it can't leak outside expressions there hopefully won't be too many problems with it. The only ways I could think of for solving 4269 is to make semantic completely reversible for declarations or to suspend gagging when evaulating non-speculative declarations. The first options requires lots of work and has hundreds of corner cases, and the second doesn't work inside speculative declarations... I'll be interested to see your solution.

@donc
Copy link
Collaborator

donc commented Feb 6, 2012

I'm taking the second approach: ungag if non-speculative, when semantic is called from a speculative context.

@yebblies
Copy link
Member Author

yebblies commented Feb 6, 2012

Ok, but I don't know how this will work for declarations that must be evaluated speculatively - basically anything can be inside a template declaration, and unless semantic can be re-run how can the errors be detected later?
eg

template Templ(T)
{
    static assert(is(T == int));
    int fun() {}
}
static assert(!__traits(compiles, Templ!(long).fun()));
enum x = Templ!(long).fun(); // semantic has already failed

The issue here isn't that semantic is being run gagged when it shouldn't be, it's that to generate the correct errors semantic has to be run again.

@donc
Copy link
Collaborator

donc commented Feb 6, 2012

Yeah, I dealt with that in a previous pull request. TemplateInstance has a member for speculative errors. If an error occurs, that counter gets updated. But it currently only applies to errors inside function bodies. It needs to be extended to work on other declarations.

@yebblies
Copy link
Member Author

yebblies commented Feb 6, 2012

Won't that result in a generic 'errors instantiating' message rather than the specifics? I guess it would change this bug from accepts-invalid to a massive diagnostic problem.

@donc
Copy link
Collaborator

donc commented Feb 6, 2012

No. If there are semantic speculative errors, and a non-speculative instantiation is requested, the existing instantiation is discarded.
Code from TemplateInstance::semantic()

   // If both this and the previous instantiation were speculative,
    // use the number of errors that happened last time.
    if (inst->speculative && global.gag)
    {
        global.errors += inst->errors;
        global.gaggedErrors += inst->errors;
    }

    // If the first instantiation was speculative, but this is not:
    if (inst->speculative && !global.gag)
    {
        // If the first instantiation had failed, re-run semantic,
        // so that error messages are shown.
        if (inst->errors)
            goto L1;
        // It had succeeded, mark it is a non-speculative instantiation,
        // and reuse it.
        inst->speculative = 0;
    }

@yebblies
Copy link
Member Author

Updated to match Don's recent ctfeInterpret changes.

There is one change: Runtime values in case statements are no longer allowed.

@donc
Copy link
Collaborator

donc commented Jul 17, 2012

There is one change: Runtime values in case statements are no longer allowed.

Please undo that. Although I would love for that to happen, it's a language change so it needs to be in its own pull request.

@yebblies
Copy link
Member Author

Ok, I'll leave the original behavior for case variables.

@yebblies
Copy link
Member Author

Done.

@andralex
Copy link
Member

OK to assign @donc to this? Please advise. I'm uneasy about two things: (a) inferring pure for regular functions makes for a big difference when compiling things separately vs. not. Not sure how bad that is. (b) disallowing runtime values for switch breaks code. This is a big one. Thoughts?

@ghost ghost assigned donc Sep 25, 2012
@donc
Copy link
Collaborator

donc commented Sep 25, 2012

The "disallowing runtime values" was removed from the pull request as part of the "restore case variables" commit.
The "inferring pure" part doesn't make a difference for separate compilation, it's simply the fact that whenever any compile-time constant is used, it is never impure, even if it was created by CTFE. If you know an expression is a compile-time literal, you don't need to analyze it further.

@yebblies
Copy link
Member Author

@andralex
a) This allows more functions to be inferred as pure by excluding ctfe expressions from checks, as nothing run at compile time can break run-time purity and safety. It does not change the circumstances is which a function has purity inference run on it.
b) While I hate case variables with a passion, they are no longer removed by this pull request. I've updated the description to reflect that.

braddr pushed a commit to braddr/dmd that referenced this pull request Oct 22, 2012
Issue 8310 - writeln of Range of fixed size array
@yebblies
Copy link
Member Author

Updated.

@yebblies
Copy link
Member Author

Updated again.

… functions not marked as pure

When running semantic on an expression used anywhere that forces compile time evaluation, use a scope flag to prevent purity and safety checks on function calls.
This allows better purity/safety inferrence as well.
donc pushed a commit that referenced this pull request May 4, 2013
Issue 6169 - [CTFE] pure functions cannot compute constants using functions not marked as pure
@donc donc merged commit 15a5783 into dlang:master May 4, 2013
@yebblies yebblies deleted the issue6169 branch November 22, 2013 08:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants