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 14875 & 14876 - improve deprecation message diagnostic #4865

Merged
merged 3 commits into from Aug 8, 2015

Conversation

9rnsr
Copy link
Contributor

@9rnsr 9rnsr commented Aug 6, 2015

Issue 14875 - A template instance with deprecated symbol/type needlessly repeats "Deprecation:" messages
Issue 14876 - Deprecation message is sometimes duplicated

And, 14875 is the root problem of issue 13738 (its fix is added by #4147). After the fix, we can remove the RTInfo specific code.

@9rnsr 9rnsr force-pushed the fix_deprecation branch 4 times, most recently from c1fe306 to 84c3642 Compare August 7, 2015 01:12
@@ -3980,6 +3980,8 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
}
else
{
if ((*pt)->ty != Terror)
next = *pt; // prevent re-running semantic() on 'next'
Copy link
Member

Choose a reason for hiding this comment

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

This is a bit hackish. It relies on the presumption that TypeSArray::resolve() is only called with next as the this pointer, making the logic very hard to follow.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure what's the hackish.

If a part of a type (eg. TypeSArray::next) is determined to be valid (== semantic analysis is succeeded),
to store back it again in the part of whole expression (eg. TypeSArray) is completely valid.

In Type(SArray|Darray|AArray|Pointer|Delegate)::semantic(), same logic is actually used.

Type *TypeSArray::semantic(Loc loc, Scope *sc)
{
    ...
    Type *tn = next->semantic(loc, sc);
    if (tn->ty == Terror)
        return terror;

    ...
    this->next = tn;
    ...
    t = this->addMod(tn->mod);
    return t->merge();
}

On the other hand, if next->deco is alredy set, next->resolve(.., &t, ..) must return the next itself to t.
It's guaranteed by the Type::merge()logic, so it's definitely reliable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Perhaps you're worried the case that the resolve() call happens with error gagging?
That's not a problem. As you see, if *pt is Terror, it won't be stored back to next, then the error object won't leak out of the gagged scope.

Copy link
Member

Choose a reason for hiding this comment

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

I'll look at it again and see if I can figure out a better way.

Copy link
Member

Choose a reason for hiding this comment

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

What I'm concerned about is much more meta. There doesn't seem to be a clear separation and encapsulation of processing in the compiler. It's become a mass of ad-hoc patches with no discernible organization. The symptom of this is the parade of regressions introduced by bug fixes. I'm afraid of it becoming completely intractable. We need to adopt a more principled approach. (The switch to ddmd will help a lot with this.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed this change looks hacky - but this change follows current compiler design.

Currently (Expression|Type|Dsymbol)::semantic() step will cause two side effects at least - the deprecation and information warning message. They don't affect the code meaning. Then, if semantic() step is invoked twice on same AST entity, they would make duplicated console outputs. To avoid the issue, we should cache the valid semantic result in each steps. After that, the repeated semantic analysis on the cached AST entity will be stopped by the previous flagging, that is (setting Expression::type to non-null | merge Type objects and set Type::deco to non-null | the increment of Dsymbol::semanticRun value).

In here, if the semantic result in *pt is valid type, it is cached into this->next to prevent rerunning semantic and messaging side effects. From that reason, this change is clean fix to me.

And, it's free that you think the better dmd internal design. Most of my bugfix work in several years was to fill holes in the well designed but rough implemented compiler internals. Honestly, I cannot say I'm genious architect programmer to design enough clean & efficient compiler process. Better design is welcome.

Copy link
Member

Choose a reason for hiding this comment

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

Unfortunately, I'm going to have to concede the point here.

@WalterBright
Copy link
Member

The fix for 14876 seems to be completely independent of the rest.

@9rnsr
Copy link
Contributor Author

9rnsr commented Aug 7, 2015

Not directly related with, but necessary to test the diagnostic message in the rest fix.

@WalterBright
Copy link
Member

Auto-merge toggled on

WalterBright added a commit that referenced this pull request Aug 8, 2015
Issue 14875 & 14876 - improve deprecation message diagnostic
@WalterBright WalterBright merged commit 9c8a260 into dlang:master Aug 8, 2015
@9rnsr
Copy link
Contributor Author

9rnsr commented Aug 8, 2015

Thanks.

@9rnsr 9rnsr deleted the fix_deprecation branch August 8, 2015 08:44
9rnsr pushed a commit to 9rnsr/dmd that referenced this pull request Aug 10, 2015
Issue 14875 & 14876 - improve deprecation message diagnostic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants