-
Notifications
You must be signed in to change notification settings - Fork 3.1k
More conservative optimization for unnecessary outer ref checks #4974
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
Conversation
/cc @adriaanm |
Sorry, I'm really deep in INDY Sammy land. Will emerge before I fly to Old Country land (Wed) with feedback. |
// if there's an outer accessor, otherwise the condition becomes `true` -- TODO: can we improve needsOuterTest so there's always an outerAccessor? | ||
val outer = expectedTp.typeSymbol.newMethod(vpmName.outer, newFlags = SYNTHETIC | ARTIFACT) setInfo expectedTp.prefix | ||
|
||
(Select(codegen._asInstanceOf(testedBinder, expectedTp), outer)) OBJ_EQ expectedOuter |
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.
Are there well-typed matches where a statically known expected type could never match (and thus the test is constant false
instead of true
). I can't think of any, but it's worth exploring.
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.
I can't think of any, either, and I think there should not be any in principle. Such a match could never succeed, so if we can detect it at compile-time, it should fail to compile in the first place.
Added the test case that @lrytz ran into yesterday |
6113021
to
a0a100e
Compare
Squashed and cleaned up. This should be good to go. |
The old algorithm omitted necessary outer ref checks in some places. This new one is more conservative. It only omits outer ref checks when the expected type and the scrutinee type match up, or when the expected type is defined in a static location. For this specific purpose the top level of a method or other code block (which is not a trait or class definition) is also considered static because it does not have a prefix. This change comes with a spec update to clarify the prefix rule for type patterns. The new wording makes it clear that the presence of a prefix is to be interpreted in a *semantic* way, i.e. the existence of a prefix determines the necessity for an outer ref check, no matter if the prefix is actually spelled out *syntactically*. Note that the old outer ref check implementation did not use the alternative interpretation of requiring prefixes to be given syntactically. It never created an outer ref check for a local class `C`, no matter if the pattern was `_: C` or `_: this.C`, thus violating both interpretations of the spec. There is now explicit support for unchecked matches (like `case _: (T @unchecked) =>`) to suppress warnings for unchecked outer refs. `@unchecked` worked before and was used for this purpose in `neg/t7721` but never actually existed as a feature. It was a result of a bug that prevented an outer ref check from being generated in the first place if *any* annotation was used on an expected type in a type pattern. This new version will still generate the outer ref check if an outer ref is available but suppress the warning otherwise. Other annotations on type patterns are ignored. New tests are in `neg/outer-ref-checks`. The expected results of tests `neg/t7171` and `neg/t7171b` have changed because the compiler now tries to generate additional outer ref checks that were not present before (which was a bug).
a0a100e
to
e7e1c77
Compare
LGTM -- good stuff, @szeiger |
More conservative optimization for unnecessary outer ref checks
Outer ref checks in pattern matches are elided if the tested prefix is the same as the expected prefix or the expected type is defined in a "static" location (i.e. directly in a package or inside a chain of nested objects).
The
@unchecked
annotation can be used to suppress the warning when an outer ref check is required but no outer ref is available (like for nested final classes).Includes a spec update to clarify the use of prefixes in type patterns.
For review only. This needs to be squashed before merging.