@@ -7807,44 +7807,50 @@ checkMetadataDependency(MetadataDependency dependency) {
7807
7807
void swift::blockOnMetadataDependency (MetadataDependency root,
7808
7808
MetadataDependency firstLink) {
7809
7809
std::vector<MetadataDependency> links;
7810
- auto checkNewLink = [&](MetadataDependency newLink) {
7811
- links.push_back (newLink);
7812
- for (auto i = links.begin (), e = links.end () - 1 ; i != e; ++i) {
7813
- if (i->Value == newLink.Value ) {
7814
- diagnoseMetadataDependencyCycle (
7815
- llvm::makeArrayRef (&*i, links.end () - i));
7816
- }
7817
- }
7818
- };
7819
-
7820
7810
links.push_back (root);
7821
7811
7822
7812
// Iteratively add each link, checking for a cycle, until we reach
7823
7813
// something without a known dependency.
7824
- checkNewLink (firstLink);
7825
- while (true ) {
7814
+
7815
+ // Start out with firstLink. The initial NewState value won't be
7816
+ // used, so just initialize it to an arbitrary value.
7817
+ MetadataStateWithDependency currentCheckResult{
7818
+ PrivateMetadataState::Allocating, firstLink};
7819
+
7820
+ // If there isn't a known dependency, we can't do any more checking.
7821
+ while (currentCheckResult.Dependency ) {
7822
+ // Add this dependency to our links.
7823
+ links.push_back (currentCheckResult.Dependency );
7824
+
7826
7825
// Try to get a dependency for the metadata in the last link we added.
7827
- auto checkResult = checkMetadataDependency (links.back ());
7828
-
7829
- // If there isn't a known dependency, we can't do any more checking.
7830
- if (!checkResult.Dependency ) {
7831
- // In the special case where it's the first link that doesn't have
7832
- // a known dependency and its current metadata state now satisfies
7833
- // the dependency leading to it, we can skip waiting.
7834
- if (links.size () == 2 &&
7835
- satisfies (checkResult.NewState , links.back ().Requirement ))
7836
- return ;
7837
-
7838
- // Otherwise, just make a blocking request for the first link in
7839
- // the chain.
7840
- auto request = MetadataRequest (firstLink.Requirement );
7841
- swift_checkMetadataState (request, firstLink.Value );
7842
- return ;
7843
- }
7826
+ currentCheckResult = checkMetadataDependency (links.back ());
7844
7827
7845
- // Check the new link.
7846
- checkNewLink (checkResult.Dependency );
7828
+ // Check the last link against the rest of the list.
7829
+ for (auto i = links.begin (), e = links.end () - 1 ; i != e; ++i) {
7830
+ if (i->Value == links.back ().Value ) {
7831
+ // If there's a cycle but the new link's current state is now satisfied,
7832
+ // then this is a stale dependency, not a cycle. This can happen when
7833
+ // threads race to build a type in a fulfillable cycle.
7834
+ if (!satisfies (currentCheckResult.NewState , links.back ().Requirement ))
7835
+ diagnoseMetadataDependencyCycle (
7836
+ llvm::makeArrayRef (&*i, links.end () - i));
7837
+ }
7838
+ }
7847
7839
}
7840
+
7841
+ // We didn't find any cycles. Make a blocking request if appropriate.
7842
+
7843
+ // In the special case where it's the first link that doesn't have
7844
+ // a known dependency and its current metadata state now satisfies
7845
+ // the dependency leading to it, we can skip waiting.
7846
+ if (links.size () == 2 &&
7847
+ satisfies (currentCheckResult.NewState , links.back ().Requirement ))
7848
+ return ;
7849
+
7850
+ // Otherwise, just make a blocking request for the first link in
7851
+ // the chain.
7852
+ auto request = MetadataRequest (firstLink.Requirement );
7853
+ swift_checkMetadataState (request, firstLink.Value );
7848
7854
}
7849
7855
7850
7856
/* **************************************************************************/
0 commit comments