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

Sema: Check 'where' clause requirements on type witnesses #33493

Merged

Conversation

slavapestov
Copy link
Contributor

@slavapestov slavapestov commented Aug 14, 2020

In the included test case, conformance checking of Wrapper : B would
pick up typealias Foo as a witness for the associated type B.Foo.

However, this typealias Foo is defined in a constrained extension where
T : A, and the underlying type references the associated type A.Foo
on T.

The resulting substitution is invalid when the conformance Wrapper : B
is used in a context where T does not conform to A.

Instead, we should ignore this typealias entirely, since it appears
in an unusable constrained extension.

Fixes rdar://problem/60219705, https://bugs.swift.org/browse/SR-12327,
https://bugs.swift.org/browse/SR-12663.

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

Copy link
Contributor

@jckarter jckarter left a comment

Choose a reason for hiding this comment

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

Thanks for hunting this down!

@AnthonyLatsis
Copy link
Collaborator

Is this related to #31259?

@slavapestov slavapestov force-pushed the type-witness-where-clause-check branch from 013f1bb to 1755c42 Compare August 15, 2020 00:16
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test macOS

@slavapestov
Copy link
Contributor Author

@AnthonyLatsis yeah, and unfortunately I see the same problem with SwiftUI:

/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/x86_64-apple-macos.swiftinterface:2842:1: error: type 'ModifiedContent<Content, Modifier>' does not conform to protocol '_WidgetModifier'
extension ModifiedContent : SwiftUI._WidgetModifier where Content : SwiftUI._WidgetModifier, Modifier : SwiftUI._WidgetModifier {
^
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/x86_64-apple-macos.swiftinterface:2803:18: note: protocol requires nested type 'WidgetBody'; do you want to add it?
  associatedtype WidgetBody : SwiftUI._Widget
                 ^
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/x86_64-apple-macos.swiftinterface:9848:1: error: type 'Optional<Wrapped>' does not conform to protocol 'Gesture'
extension Optional : SwiftUI.Gesture where Wrapped : SwiftUI.Gesture {
^
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/x86_64-apple-macos.swiftinterface:7121:18: note: protocol requires nested type 'Body'; do you want to add it?
  associatedtype Body : SwiftUI.Gesture

@slavapestov slavapestov force-pushed the type-witness-where-clause-check branch from 1755c42 to ad35000 Compare August 15, 2020 01:56
@slavapestov
Copy link
Contributor Author

slavapestov commented Aug 15, 2020

@AnthonyLatsis I added a hack to preserve backward compatibility with the SwiftUI generated interface. We skip the 'where' clause check if the typealias's underlying type is Never.

We could fix this with a new language mode one day, but we'd still have to typecheck and parse the old interface with -swift-version 5.

@AnthonyLatsis
Copy link
Collaborator

Just so I understand – the reason we must resort to a hack is because SwiftUI ships with Apple OSes, and must therefore preserve binary compatibility?

@slavapestov slavapestov force-pushed the type-witness-where-clause-check branch from ad35000 to 467ef9f Compare August 15, 2020 03:31
typealias A = Int
}

extension S3 : P where T == Int {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you change one of the cases or add a new one for a suitable witness where two extensions are constrained differently? For example, T: Equatable (type witness context) and T == Int (conformance context).

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 tried that, but we diagnose the second typealias as a re-declaration even if the requirements in the where clause were mutually exclusive. We might not want to change this behavior.

I also tried putting the typealias in a constrained protocol extension, but that hits a circularity via the GSB. I'll investigate this issue later.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry for the confusion, what I meant is ~

protocol P { associatedtype A }

struct Foo<T> {}

extension Foo where T: Equatable {
  typealias A = ...
}
extension Foo : P where T == Int {} // OK

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, thanks for the explanation. I’ll add this in a follow-up commit since I have a few more changes coming in this area.

@slavapestov
Copy link
Contributor Author

@AnthonyLatsis Type aliases are not part of the ABI. The problem is with the SwiftUI.swiftinterface file that ships in the SDK in Xcode. We have to be able to type check all the declarations in this file with the new compiler, so we have to accept the conformance as if the Body typealias is defined in an unconstrained extension.

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend -emit-ir -o %t.ll %s
// RUN: not %target-swift-frontend -emit-ir %s
Copy link
Contributor Author

Choose a reason for hiding this comment

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

FWIW This was actually an invalid test case that we used to accept (and presumably we used to crash in the even more distant past). Since we now correctly reject it, I changed the expectation here.

In the included test case, conformance checking of Wrapper : B would
pick up typealias Foo as a witness for the associated type B.Foo.

However, this typealias Foo is defined in a constrained extension where
T : A, and the underlying type references the associated type A.Foo
on T.

The resulting substitution is invalid when the conformance Wrapper : B
is used in a context where T does not conform to A.

Instead, we should ignore this typealias entirely, since it appears
in an unusable constrained extension.

Fixes <rdar://problem/60219705>, <https://bugs.swift.org/browse/SR-12327>,
<https://bugs.swift.org/browse/SR-12663>.
@slavapestov slavapestov force-pushed the type-witness-where-clause-check branch from 467ef9f to 6d84c18 Compare August 15, 2020 05:43
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

1 similar comment
@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

@slavapestov
Copy link
Contributor Author

@swift-ci Please smoke test

@slavapestov
Copy link
Contributor Author

@swift-ci Please test source compatibility

@AnthonyLatsis
Copy link
Collaborator

Type aliases are not part of the ABI. The problem is with the SwiftUI.swiftinterface file that ships in the SDK in Xcode. We have to be able to type check all the declarations in this file with the new compiler

If we can move the type alias under correct constraints without breaking the ABI, and both language release versions and the SwiftUI.swiftinterface ship with Xcode, why would we have to keep the hack behind a language mode anyway if a coordinated fix is possible to organize eventually for a subsequent Xcode release?

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.

None yet

3 participants