Skip to content

DI fixes for resilience #12386

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

Merged
merged 13 commits into from
Oct 14, 2017
Merged

Conversation

slavapestov
Copy link
Contributor

@slavapestov slavapestov commented Oct 11, 2017

Fixes https://bugs.swift.org/browse/SR-5649, rdar://problem/33767516, rdar://problem/33137910.

Copy link
Contributor

@gottesmm gottesmm left a comment

Choose a reason for hiding this comment

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

Metacomment: Please do not commit the less specific error messages (I realize this is WIP).

for (auto UI : MUI->getUses()) {
void DelegatingInitElementUseCollector::collectValueTypeInitSelfUses(
SILInstruction *I) {
for (auto UI : I->getResults()[0]->getUses()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please do not do this! If you truly want a SingleValueInstruction, dyn_cast to it. That being said, here you should be handling multiple results.

@slavapestov
Copy link
Contributor Author

Thanks for the suggestion, I'll definitely fix up the multiple values usages. And of course the PR will get proper commit messages and a lot of cleanup before I merge.

@gottesmm gottesmm dismissed their stale review October 11, 2017 21:15

Ok. I want to review this when you are done.

@slavapestov
Copy link
Contributor Author

Still needs tests, and I have more diagnostics improvements pending.

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

1 similar comment
@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov slavapestov changed the title DI WIP DI fixes for resilience Oct 13, 2017
@slavapestov
Copy link
Contributor Author

Hey @jrose-apple @gottesmm this is ready for review.

There is a regression in diagnostics where sometimes we now point to the end location of a function instead of the 'return' in question when you return without initializing self. Technically this isn't a new problem, it was there all along, because the old logic was only happening with root initializers. Now that more initializers are delegating it's happening more.

Do you mind if I fix it in a follow-up PR? @jrose-apple needs the changes here for some resilience work he's doing.

@slavapestov
Copy link
Contributor Author

@swift-ci Please test

2 similar comments
@slavapestov
Copy link
Contributor Author

@swift-ci Please test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

@slavapestov
Copy link
Contributor Author

@swift-ci Please test Linux

Copy link
Contributor

@jrose-apple jrose-apple left a comment

Choose a reason for hiding this comment

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

Thanks, Slava!

I'd like someone more familiar with DI to review the DI changes. I'm also unhappy with the bad diagnostics not being put in the file; we should put them in in their bad state and change them later.

ERROR(self_before_selfinit,none,
"'self' used before 'self.init' call", ())
ERROR(self_before_selfinit_value_type,none,
"'self' used before 'self.init' call or assignment to 'self'", ())
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: why have three separate messages here, when it's still a choice above?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because the choice was keyed purely on whether its a delegating init or not, but I also want to distinguish the value type case so that diagnostics say that an assignment to self is OK too. I'll probably rework the other diagnostics when I do the fix for the return location analysis.

If you think they should still be a single diagnostic with a %select, I don't mind doing that. It seemed a bit silly to define a new enum that's only used in one place, but if I see other diagnostics get too repetitive I can do it.

@@ -1,6 +1,11 @@
// RUN: %target-run-simple-swift | %FileCheck %s
// RUN: %target-run-simple-swift
Copy link
Contributor

Choose a reason for hiding this comment

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

Once upon a time these were deliberately minimal tests, where if something broke in StdlibUnittest it wouldn't automatically break in these tests. Maybe that's not so relevant now, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I understand the reasoning here, but I find StdlibUnittest easier to work with when a test fails, and also CHECK: lines are not totally reliable because it's easy to accidentally match the wrong thing. At one point Dmitri told me that new executable tests should use StdlibUnittest so I've been slowly converting them when I touch them.

self.w = ww
self.h = hh
self.h = hh // expected-error {{}}
Copy link
Contributor

Choose a reason for hiding this comment

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

What message do we get at the moment? It's worth including just so we can see when it changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We now get a Sema error saying that 'self.h' is a let property. The initializer is now delegating since it's inlinable, so we don't even get as far as DI here, instead we hit the restriction that delegating inits cannot assign to let properties at all.

This isn't the "bad diagnostic" case I was talking about; that's in the DI tests (look at the patch that makes all enum constructors delegating).

Copy link
Contributor

Choose a reason for hiding this comment

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

That should still be included, though. We can fix it later.

Copy link
Contributor

Choose a reason for hiding this comment

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

The enum thing does seem like something we can fix in a follow-up PR. We just need to not ship it!

@slavapestov slavapestov force-pushed the most-definitely-self branch 2 times, most recently from c021c14 to 79e7fcb Compare October 14, 2017 03:21
…ice versa

This allows, for example, an initializer to conditionally assign
to self or call self.init, along different control flow paths.

It also means that it is legal to call self.init() multiple times
in a value type initializer, but this... is fine. The old 'self'
is destroyed.

Fixes <rdar://problem/33137910>.
Previously protocol extension initializers which called 'self.init' were
considered 'delegating', and ones that assign to 'self' were considered
'root'.

Both have the same SIL lowering so the distinction is not useful, and
removing it simplifies some code.
Again, since there's no distinction between an enum initializer that
delegates to 'self.init' from one that assigns to 'self', we can remove
the special handling of enum initializers in the 'root self' case.

Now, 'root self' is only used for designated initializers in classes
with no superclass, and struct initializers that perform memberwise
initialization of stored properties.

This regresses some diagnostics, because the logic for delegating
init diagnostics is missing some heuristics present in the root self
case. I will fix this in a subsequent patch.
Initializers for non-fixed-layout structs that are inlinable or
are defined in a different module are treated as delegating
initializers.

Previously, only initializers containing a 'self.init' call were
delegating; initializers that assigned to 'self' were not, which
resulted in DI treating them as a root initializer where the
stored 'self' value was exploded into a series of stores to each
stored property member.

They were not resilient as a result.

Fixes <https://bugs.swift.org/browse/SR-5649>,
<rdar://problem/33767516>.
@slavapestov
Copy link
Contributor Author

@swift-ci Please test

1 similar comment
@slavapestov
Copy link
Contributor Author

@swift-ci Please test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

1 similar comment
@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants