Commit Graph

11 Commits

Author SHA1 Message Date
Holly Borla
9ba481ad53 [Diagnostics] Clarify the wording of error_in_future_swift_version. 2024-03-01 12:05:51 -08:00
Slava Pestov
dac8d666ee Stop passing -requirement-machine-{abstract,inferred,protocol}-signatures flags in tests
These flags are now no-ops.
2022-05-10 12:56:17 -04:00
Slava Pestov
305a1e42b6 RequirementMachine: Update some tests to pass with -requirement-machine-inferred-signatures=verify 2022-03-14 12:33:18 -04:00
Slava Pestov
599bb79933 Sema: Generalize the 'invariant Self requirement' check to handle a related case
There are three kinds of invariant 'Self' uses here:

- 'Self' appears as the left hand side of a same-type requirement between type parameters
- 'Self' appears as a structural component of the right hand side of a concrete type requirement
- 'Self' appears as a structural component of the right hand side of a superclass requirement

My previous fix only handled the first case. Generalize it to handle all three.

Fixes rdar://problem/74944514.
2022-03-09 18:50:14 -05:00
Slava Pestov
8e09ba8b45 RequirementMachine: Introduce 'concrete contraction' pre-processing pass before building rewrite system
See the comment at the top of ConcreteContraction.cpp for a detailed explanation.

This can be turned off with the -disable-requirement-machine-concrete-contraction
pass, mostly meant for testing. A few tests now run with this pass both enabled
and disabled, to exercise code paths which are otherwise trivially avoided by
concrete contraction.

Fixes rdar://problem/88135912.
2022-02-25 11:48:38 -05:00
Slava Pestov
aa210d29ae RequirementMachine: Prefer to eliminate concrete type requirements over superclass requirements again
If you have something like this:

    protocol P {
      associatedtype A : Q where Self == Self.A.B
    }

    protocol Q {
      associatedtype B
    }

    class C : P {
      typealias A = D
    }

    class D : P {
      typealias B = C
    }

The GSB would minimize the generic signature <T where T : P, T : C>
to <T where T == C>, because of the same-type requirement in
protocol P.

However in reality, the conformance 'C : P' is unsound, because it
is no longer covariant. I added a warning in commit d831eff74879cb.

Because the upcoming 'concrete contraction' pass eliminates 'T : P'
before homotopy reduction gets a chance to run, I'm changing the
Requirement Machine to produce a different minimization from the
GSB. This is technically an ABI break, but it should not impact any
real code in practice. If it does, I'll need to come up with a
different workaround in concrete contraction.
2022-02-25 11:48:38 -05:00
Slava Pestov
c98ddb99e2 Sema: Warn about non-final classes conforming to protocols with a same-type requirement on 'Self'
This is unsound because it breaks covariance of protocol conformances
on classes. See the test case and changelog entry for details.
2022-02-24 14:23:00 -05:00
Slava Pestov
966620bbaa RequirementMachine: Swap reduction order of ConcreteType and Superclass symbols
This ensures we produce the same minimal signature as the GSB
in a couple of really silly examples where a superclass requirement
and a concrete type requirement imply each other.
2022-02-17 19:40:58 -05:00
Slava Pestov
e4115a286c GSB: New way of handling concrete same-type requirements when rebuilding a signature
After we drop redundant conformance requirements, the left hand side
of a concrete same-type requirement might become unresolvable:

    protocol P {
      associatedtype T where T == Self
    }

    struct S : P {}

    extension P where T == S {}

Here, we begin with <Self where Self : P, Self.T == S>, and then we
drop (Self : P). However, <Self where Self.T == S> is no longer a
valid generic signature.

We can canonicalize Self.T down to Self before we build the new
signature, but we must only do this for concrete same-type requirements,
since canonicalizing the subject type of an abstract same-type
requirement might lose information produce a trivial requirement of
the form 'T == T'.

This is really unprincipled, and no doubt other counter-examples
exist. The entire procedure for rebuilding a generic signature needs
to be re-designed from first principles.

Fixes rdar://problem/80503090.
2021-07-28 12:17:40 -04:00
Slava Pestov
106decbb66 GSB: Try harder to handle a combination of a superclass and conformance requirement
A protocol conformance requirement together with a superclass requirement
can collapse down to a same-type requirement if the protocol itself has
a 'where' clause:

    protocol P {
      associatedtype T where T == Self
    }

    class C : P {}

    extension P where T : C {}

(Self : P) and (Self.T : C) imply that (Self == C), because protocol P
says that Self.T == Self, and the witness of P.T in C is C, so when we
substitute that in we get Self == C.

Part of rdar://problem/80503090.
2021-07-28 12:17:40 -04:00
Slava Pestov
4dc76578d2 GSB: Canonicalize subject type in isValidDerivationPath()
Generally we say that a conformance requirement in a generic signature
is redundant if there is some other way to derive this conformance by
starting from another conformance requirement in the same signature,
and possibly following one or more conformance requirements on nested
types defined in protocols.

The notion of a 'valid derivation path' comes into play when you have
something like this:

    protocol P {
      associatedtype A
    }

    protocol Q {
      associatedtype B : P
    }

    <T where T : P, T.A : P, T.A.B == T>

Here, we don't want to conclude that (T : P) can be derived from
(T.A : P)(Self.B : P), because if we drop (T : P) from the signature,
we end up with

    <T where T.A : P, T.A.B == T>

Now in order to recover the witness table for T : P, we need to start
from T.A : P, which requires the type metadata for T.A, which can
only be recovered from the witness table for T : P, etc. We're stuck.

What we want to do is say that T : P is not redundant, because we
cannot derive it from T.A : P, because T.A depends on T : P.

However, this check was also too strict. Consider this example:

    protocol P {
      associatedtype T where T == Self
    }

    protocol Q : P {}

    <T where T : P, T.T : Q>

The naive algorithm would conclude that T : P is redundant because
it can be derived as (T.T : Q)(Self.T == Self). However, the valid
derivation path check would fail since T.T is derived from (T : P).

The problem is that since T.T is equivalent to T via (Self.T == T),
we would end up with this minimized signature:

    <T where T : P, T : Q>

The derivation path check should canonicalize the type first.

I'm still not 100% convinced this logic is correct, but at least,
we have another test case and maybe it's _more_ correct now.

Fixes part of rdar://problem/80503090.
2021-07-28 12:17:39 -04:00