-
-
Notifications
You must be signed in to change notification settings - Fork 606
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
[REG2.068.0] Issue 15726 - forward reference error for circular classes, RefCounted #5500
Conversation
5034590
to
89213a9
Compare
Ready to review. |
Please do refactorings as separate PRs. |
I've been repeating this point many times over the last few months, so I wrote this: |
b51aeaf
to
44e7f88
Compare
Now this PR contains only core changes for issue 15726. |
f192bd9
to
bf191c7
Compare
n *= (cast(TypeSArray)tv).dim.toUInteger(); | ||
tv = tv.nextOf().toBasetype(); | ||
} | ||
if (n == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have a small helper function for that in TypeSArray.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not bad, but today it will be used only at two places.
2c417dd
to
a48df86
Compare
if (v.storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest | STCctfe | STCtemplateparameter)) | ||
return 0; | ||
if (!v.isField() || v.sem < SemanticDone) | ||
return 1; // unresolvable forward referernce |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reference
spelling
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix.
structsize = 0; | ||
alignsize = 0; | ||
|
||
assert(type == Type.terror); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
type.ty == Terror
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will fix.
BTW, GitHub has now improved the commit viewer in pull requests. Now, there are prev/next buttons, so that pull requests can contain logically self-contained changes split up in commits, and reviewing can be done piecewise by looking at individual commits. This makes it easy to ignore refactoring / whitespace changes when reviewing PRs, so maybe that rule is not as necessary any more? |
http://wiki.dlang.org/Starting_as_a_Contributor#Characteristics_of_a_Good_Pull_Request I really don't understand the resistance to having small, one topic, focused PRs, especially when they are complex. Even this one was unnecessarily difficult because a lot of the diff lines were still refactorings unrelated to the purpose of the PR, and the github diff view still displayed them. I still wound up looking at 10 line blocks wondering "is this a refactoring, or is it substantive?" A good PR should do one thing, for darn good reasons. It's analogous to not liking spaghetti code, and unencapsulated data structures. We certainly have plenty of regressions from PRs. It's not like there aren't bugs in the refactorings. There is a history of them. |
Well, I'm asking because I don't understand the resistance against it. In particular...
Well, that's what looking at individual commits is supposed to solve, isn't it?
Could you please explain how splitting changes into logically separate PRs is different from splitting changes into logically separate commits?
I don't see how that analogy holds, because the changes are encapsulated, but in commits, not PRs. As for the arguments for this, well, if you need to refactor something to fix something else, then the refactoring is blocking your other work, which I can understand to be frustrating - by the time your refactoring PR has been reviewed and merged, you're elsewhere, and have to back up to submit the actual fix. That's my understanding of the situation, and I'm mainly asking out of curiosity anyway. |
Looking at the commits one-by-one is harder, because you still need to load the full thing into your head. Quite often it's not obvious which commits depend on which other commits, or at which points in the middle the code still works. Sometimes code is added in one commit and removed in another. With multiple PRs there is no question. The PR author already knows all this information, and they can split into multiple PRs in much less time than it would take me to reconstruct this in my head. Especially if I'm doing it in 10 minute chunks here and there when I have time to read PRs. I assume others are in a similar situation.
I've never found that to be a significant problem in practice. Rebasing, pushing only some commits from a branch, etc are usually pretty easy. |
In dlang#5500, issue 14666 has been properly fixed by adding mechanism of deferred semantic2 running for imported modules. Now, the workaround in `todt.c` is not necessary anymore.
In dlang#5500, issue 14666 has been properly fixed by adding mechanism of deferred semantic2 running for imported modules. Now, the workaround for issue 9057 in `todt.c` is unnecessary anymore.
In dlang#5500, issue 14666 has been properly fixed by adding mechanism of deferred semantic2 running for imported modules. Now, the workaround for issue 9057 in `todt.c` is unnecessary anymore.
In dlang#5500, issue 14666 has been properly fixed by adding mechanism of deferred semantic2 running for imported modules. Now, the workaround for issue 9057 in `todt.c` is unnecessary anymore.
This pull request introduced a regression: |
More specifically both regressions are caused by the 2nd commit of this PR 75b5b69. |
…sted - Since dlang#5500 buildPostblit/Dtor/OpAssign are run before the struct size is finalized, thereby now making structs nested that previously were not. - Not sure if the old behavior was an intended feature. If not we might want to deprecate it.
…sted - Since dlang#5500 buildPostblit/Dtor/OpAssign are run before the struct size is finalized, thereby now making structs nested that previously were not. - Not sure if the old behavior was an intended feature. If not we might want to deprecate it.
…sted - Since dlang#5500 buildPostblit/Dtor/OpAssign are run before the struct size is finalized, thereby now making structs nested that previously were not. - Not sure if the old behavior was an intended feature. If not we might want to deprecate it.
…sted - Since dlang/dmd#5500 buildPostblit/Dtor/OpAssign are run before the struct size is finalized, thereby now making structs nested that previously were not. - Not sure if the old behavior was an intended feature. If not we might want to deprecate it.
And another regression where |
Specifically, this commit, which adds recursive protection. 80d1398 |
This pull request introduced a regression: |
This pull request introduced a regression: |
This pull request may have introduced a regression: |
Defer aggregate instance size finalization until semantic2 at maximum
From long ago, an instance size finalization had been done during
semantic()
stage, but it had had a known problem. When an aggregate 'A' tries to build its dtor or postblit, they should know each types of instance fields. But the field type analysis could recursively reach to A'ssematnic()
(especially withRefCounted
,Variant
, etc) and it had caused forward reference issues.Against that, we've tried many ways to detect/break the problematic recursive analysis. So far it has been mostly finished to monitoring
sizeok
field, though it has been still fragile.Finally I found an essential solution. During the dtor or postblit building, we don't have to finalize instance size. Instead we just need to know the complete list of instance fields at that time.
From the view, I divide instance size determination process into two stages.
The first is
determineFields()
, it collects all instance fields then pushes intoAggregateDeclaration.fields
. It's called in aggregate'ssemantic()
and makes preparations forbuildDtor()
andbuildPostBlit()
.The second is
determineSize()
, it requests finalizing each type sizes of instance fields and determine the field offsets. If no declarations'semantic()
depend on the instance size,determineSize()
could be deferred untilsemantic2()
stage at maximum.Finally, a failure of
determineSize()
can mean an existence of unresolvable forward references (circular dependency, use of opaque struct, etc).This PR is intentionally based on master branch, because this change is too big as a regression fix.