mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
We've had a load-bearing optimization that avoids rebuilding
the generic signature of the protocol extension to avoid a
cycle involving a typealias in the extension that's mentioned
as a requirement in the protocol, for example:
```
public protocol P3 {
associatedtype A
}
public protocol P4: P3 where A == B {}
extension P4 {
public typealias B = String
}
```
What was happening is that we're inside a
StructuralRequirementsRequest, so we're performing TypeResolution
in the Structural stage. When we encounter this typealias that's
within a protocol extension, we'd end up accidentally requesting
the interface type of that alias through
`TypeChecker::substMemberTypeWithBase`
(via `aliasDecl->getUnderlyingType()`).
What we should do instead is call `aliasDecl->getStructuralType()`
and skip the substitution during that stage.
There happened to already be code doing this, but it was only
kicking in if the DeclContext `isa<ProtocolDecl>`, which excludes
extensions of a protocol. I see no reason why extensions of a
protocol should be excluded, so I assume it was unintentional.
Thus, the fix boils down to using `DeclContext::getSelfProtocolDecl`
which does include extensions of protocols. With this fix, the
optimization is no longer load-bearing on the example above.
See the history of this hack in f747121080
or rdar://problem/129540617
37 lines
1.1 KiB
Swift
37 lines
1.1 KiB
Swift
// RUN: %target-typecheck-verify-swift %s
|
|
|
|
protocol P<T> {
|
|
associatedtype T
|
|
}
|
|
|
|
extension P {
|
|
typealias A = Int
|
|
// expected-note@-1 3{{consider moving 'A' into the definition of protocol 'P'}}
|
|
}
|
|
|
|
protocol Q {
|
|
associatedtype T: P
|
|
associatedtype U: P<T.A>
|
|
// expected-error@-1 {{'A' was defined in extension of protocol 'P' and cannot be referenced from a associated type inheritance clause}}
|
|
}
|
|
|
|
struct S<T: P, U: P<T.A>> {
|
|
// expected-error@-1 {{'A' was defined in extension of protocol 'P' and cannot be referenced from a generic parameter inheritance clause}}
|
|
|
|
func f<V>(_: V) where V == T.A {}
|
|
// expected-error@-1 {{'A' was defined in extension of protocol 'P' and cannot be referenced from a 'where' clause}}
|
|
}
|
|
|
|
public protocol K3: ~Copyable {
|
|
associatedtype A
|
|
}
|
|
|
|
// This shouldn't work because the extension defining B is implicitly constrained to K4's where Self: Copyable
|
|
public protocol K4: K3
|
|
where A == B, // expected-error {{type 'Self' does not conform to protocol 'Copyable'}}
|
|
Self: ~Copyable {}
|
|
|
|
extension K4 {
|
|
public typealias B = String
|
|
}
|