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

[AST] Start using conformance access paths in SubstitutionMap #8521

Merged

Conversation

DougGregor
Copy link
Member

@DougGregor DougGregor commented Apr 4, 2017

Reimplement SubstitutionMap::lookupConformance() in terms of the ConformanceAccessPath, eliminating the ugly "parent map" hack and ensuring that all stages of substitutions are depending on the same core abstractions (GenericSignature, ConformanceAccessPath.

While here, remove the error blocking the use of associated type where clauses SE-0142, because we should be able to start experimenting with them in earnest now regardless of language mode.

Fixes rdar://problem/31041997 and rdar://problem/31309863.

@DougGregor DougGregor force-pushed the substitutionmap-conformance-access-path branch from 48112e8 to f524135 Compare April 4, 2017 05:41
SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
// If we have an archetype, map out of the context so we can compute a
// conformance access path.
GenericEnvironment *genericEnv = nullptr;;
Copy link
Contributor

Choose a reason for hiding this comment

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

Double ;.

Copy link
Member Author

Choose a reason for hiding this comment

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

Got it, thanks

protocol P1 {}
protocol P2 { associatedtype T }
protocol P3 { associatedtype U }
protocol P4: P3 where U: P2, U.T: P1 {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, isn't this isomorphic to the NestedConforms test above? @slavapestov's targeted fix #8428 that made that work includes a "rip this out once conformance access paths are plumbed through" comment, can that be executed now?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, you're right. Well then! I'll see if I can rip out the hack in #8428 now; it might require better handling of concrete types in GenericSignature.

@DougGregor DougGregor changed the title [WIP] [AST] Start using conformance access paths in SubstitutionMap [AST] Start using conformance access paths in SubstitutionMap Apr 4, 2017
@DougGregor
Copy link
Member Author

@swift-ci please smoke test and merge

@DougGregor DougGregor force-pushed the substitutionmap-conformance-access-path branch 2 times, most recently from 011a016 to ac94585 Compare April 4, 2017 17:55
@DougGregor
Copy link
Member Author

@swift-ci please smoke test and merge

@DougGregor DougGregor force-pushed the substitutionmap-conformance-access-path branch from ac94585 to adbed0a Compare April 4, 2017 17:56
@DougGregor
Copy link
Member Author

@swift-ci please smoke test and merge

1 similar comment
@DougGregor
Copy link
Member Author

@swift-ci please smoke test and merge

Substitution maps are effectively tied to a particular generic
signature or environment; keep track of that signature/environment so
that we can (eventually) use it to find conformances.
…kup.

When we are checking the conformance of a nominal type to a particular
protocol, we check each of the requirements in the requirement
signature, substituting in our Self type and (by extension) type
witnesses. However, when we're trying to fulfill requirements for
associated types (which might be mapped to concrete types), perform
the conformance lookup in the module of the conformance itself---not
the SubstitutionMap, which can't possibly have them at this point.

Fixes rdar://problem/31041997.
When looking up a particular conformance in a SubstitutionMap, use the
associated generic signature to determine how to find that conformance
(via a conformance access path). Follow that conformance access path
to retrieve the desired conformance.

FIXME: There is still one failure, here

  Constraints/generic_overload.swift

which appears to be because we either have the wrong generic signature
for the override case or we are looking in the wrong map.
…rmances.

When looking for a conformance for an archetype, map it out of context
to compute the conformance access path, then do the actual lookups
based on mapping the starting type back into the context. Eliminate
the parent map and "walk the conformances" functionality.
When asking a substitution map for a conformance, it's okay if the
conformance isn't there---just detect this case and return None.

Also, collapse a redundant testcase Huon noted.
We're ready to start experimenting with and rolling out this feature
in earnest.
@DougGregor
Copy link
Member Author

@swift-ci please smoke test Linux

1 similar comment
@DougGregor
Copy link
Member Author

@swift-ci please smoke test Linux

This would cause spurious idempotency failures with generic signature canonicalization.
@DougGregor DougGregor force-pushed the substitutionmap-conformance-access-path branch from adbed0a to ba10723 Compare April 4, 2017 21:08
@DougGregor
Copy link
Member Author

@swift-ci please smoke test and merge

1 similar comment
@DougGregor
Copy link
Member Author

@swift-ci please smoke test and merge

[&](Type type, ProtocolDecl *proto) -> Optional<ProtocolConformanceRef> {
// We're working relative to a generic environment, map into that
// context before looking into the conformance map.
if (genericEnv)
Copy link
Member

Choose a reason for hiding this comment

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

It seems silly to map the type out of context only to map it back in again. What do you think of always using interface types as keys in the conformance map, even for generic environment-derived substitutions?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it's a great idea. What I'd like to do is turn the conformance map into a flat array, arranged according to the protocol requirements in the GenericSignature, the way we do with NormalProtocolConformance and its "signature conformances".

});
}
auto canonType = genericSig->getCanonicalTypeInContext(type, mod);
auto accessPath =
Copy link
Member

Choose a reason for hiding this comment

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

It seems expensive to go through the canonical GSB to do getCanonicalTypeInContext(), and then feed the result back into the GSB for getConformanceAccessPath(). Can getConformanceAccessPath() instead do the right thing with non-canonical types?

Copy link
Member Author

Choose a reason for hiding this comment

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

Actually, getConformanceAccessPath() can work on non-canonical types, because it implicitly canonicalizes when looking up the potential archetype. I think the canonicalization you refer to is unnecessary.

return recordOrReturn(conformance.getInherited(proto));
// If we've hit an abstract conformance, everything from here on out is
// abstract.
// FIXME: This may not always be true, but it holds for now.
Copy link
Member

Choose a reason for hiding this comment

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

This is of course the infamous SR-3500

@slavapestov
Copy link
Member

Looks cool! I'm mostly concerned with making lookupConformance() cheaper. Anything we can do to eliminate redundant canonicalization steps or to memoize more stuff would be good.

…formance.

Fixes a regression introduced when we switched SubstitutionMap::lookupConformance() to conformance access paths.
@DougGregor
Copy link
Member Author

@swift-ci please smoke test and merge

1 similar comment
@DougGregor
Copy link
Member Author

@swift-ci please smoke test and merge

@DougGregor
Copy link
Member Author

That last commit should address the corelibs Foundation failure.

@swiftix
Copy link
Contributor

swiftix commented Apr 5, 2017

@DougGregor Have you tried to perform a build with these changes and enabling the SpecializeGenericSubstitutions in Generics.cpp? It may result in exposing more edge cases which are not addressed by this PR yet.

@swift-ci swift-ci merged commit 3ec9219 into apple:master Apr 5, 2017
@DougGregor DougGregor deleted the substitutionmap-conformance-access-path branch April 5, 2017 04:20
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

5 participants