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
This is similar to SuppressedAssociatedTypes, but infers
default requirements when primary associated types of
protocols are suppressed. This defaulting for the primary
associated types happens in extensions of the protocol,
along with generic parameters, whenever a source-written
requirement states a conformance requirement for the protocol.
Thus, the current scheme for this defaulting is a simplistic,
driven by source-written requirements, rather than facts
that are inferred while building generic signatures.
Defaults are not expanded for infinitely many associated types.
rdar://135168163
Support pack expansion types in term rewriting, maintaining shape invariants and not
throwing assertions unnecessarily.
Additional tests added for an inifinite case and a concrete case.
The "iterate until fixed point" would cause an infinite loop where we
wrap type parameter packs in a PackElementType and increase the level
forever otherwise.
This was a regression from commit 103428fe80.
Fixes rdar://160804717.
This adds the -verify-ignore-unrelated flag. When -verify is used without -verify-ignore-unrelated, diagnostics emitted in buffers other than the main file and those passed with -verify-additional-file (except diagnostics emitted at <unknown>:0) will now result in an error. They were previously ignored. The old behaviour is still available as opt-in using -verify-ignore-unrelated, but by being strict by default it should make it harder to accidentally miss diagnostics.
To avoid unnecessary performance overhead, -verify-additional-file is still required to parse the expected-* directives in files other than the main file.
Matching existential types could introduce `InstanceType` element
at the end of the locator path, it's okay to look through them to
diagnose the underlying issue.
Filter out any duplicate notes to help cut down on the noise for
request cycle diagnostics. Some of the note locations here still aren't
great, but this at least stops us from repeating them for each
intermediate request.
These are tests that fail in the next commit without this flag. This
does not add -verify-ignore-unrelated to all tests with -verify, only
the ones that would fail without it. This is NFC since this flag is
currently a no-op.
If we failed to construct a rewrite system for a protocol, either because
the Knuth-Bendix algorithm failed or because of a request cycle while
resolving requirements, we would end up in a situation where the resulting
rewrite system didn't include all conformance requirements and associated
types, so name lookup would find declarations whose interface types are
not valid type parameters.
Fix this by propagating failure better and just doing nothing in
getReducedTypeParameter().
Fixes rdar://147277543.
Move the logic from `FailureDiagnostic::resolveType` into
`Solution::simplifyType` to allow completion to use it too. While
here, also handle cases where the placeholder is from a different
member of the equivalence class to the generic parameter.
We would crash in some cases, or produce a slightly misleading
diagnostic about same-element requirements, which are related but
not quite the same.
In the fullness of time, we should figure out this corner of the
language. Until then, add a new diagnostic since this is really
about same-type requirements between concrete types and packs.
Fixes rdar://159790557.
Commit b70f8a82b1 introduced a usage of
ReplaceOpaqueTypesWithUnderlyingTypes in Sema. Previously this was only
called from SILGen.
The problem was that ReplaceOpaqueTypesWithUnderlyingTypes would call
getUniqueUnderlyingTypeSubstitutions(), which triggers a request to
type check the body of the referenced function.
While this didn't result in unnecessary type checking work, because
UniqueUnderlyingTypeSubstitutionsRequest::evaluate() would skip bodies
in secondary files, it did change declaration checking order.
The specific issue we saw was a bad interaction with associated type
inference and unqualified lookup in a WMO build, and a complete test
case is hard to reduce here.
However, no behavior change is intended with this change, modulo bugs
elsewhere related to declaration checking order, so I feel OK not adding
a test case.
I'll hopefully address the unqualified lookup issue exposed in the
radar soon; it has a reproducer independent of opaque return types.
Fixes rdar://157329046.
Now look through other opaque return types that appear in the
underlying type. This catches various forms of recursion that
otherwise would cause a SILGen or SILOptimizer crash.
- Fixes rdar://82992151.
The implementation of Knuth-Bendix completion has had a subtle
bookkeeping bug since I first wrote the code in 2021.
It is possible for two rules to overlap in more than one position,
but the ResolvedOverlaps set was a set of pairs (i, j), where
i and j are the index of the two rules. So overlaps other than
the first were not considered. Fix this by changing ResolvedOverlaps
to a set of triples (i, j, k), where k is the position in the
left-hand side of the first rule.
The end result is that we would incorrectly accept the protocol M3
shown in the test case. I'm pretty sure the monoid that M3 encodes
does not have a complete presentation over any alphabet, so of
course it should not be accepted here.
The concrete nesting limit, which defaults to 30, catches
things like A == G<A>. However, with something like
A == (A, A), you end up with an exponential problem size
before you hit the limit.
Add two new limits.
The first is the total size of the concrete type, counting
all leaves, which defaults to 4000. It can be set with the
-requirement-machine-max-concrete-size= frontend flag.
The second avoids an assertion in addTypeDifference() which
can be hit if a certain counter overflows before any other
limit is breached. This also defaults to 4000 and can be set
with the -requirement-machine-max-type-differences= frontend flag.
This can return ErrorType if the AST is invalid.
A handful of callers handle the ErrorType result, but most don't,
blindly assuming the result is always a nominal type. This resulted
in a crash in at least one test case.
Lift the burden from callers by always returning a nominal type here.
The proposal states that this should work, but this was never
implemented:
protocol P<A> {
associatedtype A
}
struct S: P<Int> {}
- Fixes https://github.com/swiftlang/swift/issues/62906.
- Fixes rdar://91842338.
getContextSubstitutionMap() didn't handle the case where getAnyNominal()
returns a ProtocolDecl. This should not take the "fast path", which is
only suitable for concrete nominals.
This manifested as a crash-on-invalid -- the user probably meant to write
"T.Value: Collection" rather than "T.Value == Collection".
Fixes rdar://151479861.
Enhance the logic in `applyInverses` to also take into account same-type constraints spelled in
the generic signature, so that same-type-constraining a type parameter to a type that is itself
not `Copyable` or `Escapable` suppresses the default application of those constraints on the
type parameter. Fixes rdar://147757973.
`extension G<Int>` introduces a same-type requirement, and
this isn't supported for variadic generic types yet.
Make sure we pass a valid source location here to diagnose
instead of dropping the error.
- Fixes https://github.com/apple/swift/issues/70432
- Fixes rdar://119613080
In the below, 'Self.A.A' is not a type parameter; rather, since
'Self.A' is concretely known to be 'S', we resolve it as 'S.A',
which performs a name lookup and finds the concrete type alias 'A':
public struct S {
public typealias A = Int
}
public protocol P {
typealias A = S
}
public struct G<T> {}
public protocol Q: P {
typealias B = G<Self.A.A>
}
This is fine, but such a type alias should not participate in
the rewrite system. Let's exclude them like any other invalid
requirement.
The type alias itself is not an error; however, it is an error
to use it from a 'where' clause requirement. This is not
diagnosed yet, though.
Fixes rdar://136686001.