@@ -87,11 +87,7 @@ class CheckTypeWitnessResult {
8787
8888 // / Type witness does not satisfy a layout requirement on
8989 // / the associated type.
90- Layout,
91-
92- // / Type witness of a tuple conformance does not have the form
93- // / (repeat (each Element).A).
94- Tuple
90+ Layout
9591 } kind;
9692
9793private:
@@ -125,25 +121,36 @@ class CheckTypeWitnessResult {
125121 return CheckTypeWitnessResult (Layout, reqt);
126122 }
127123
128- static CheckTypeWitnessResult forTuple (Type reqt) {
129- return CheckTypeWitnessResult (Tuple, reqt);
130- }
131-
132124 Kind getKind () const { return kind; }
133125 Type getRequirement () const { return reqt; }
134126
135127 explicit operator bool () const { return kind != Success; }
136128};
137129
130+ // / Checks a potential witness for an associated type A against the "local"
131+ // / requirements of the type parameter Self.[P]A. We call this to check
132+ // / type witnesses found by name lookup, as well as candidate witnesses during
133+ // / inference.
134+ // /
135+ // / This does not completely check the witness; we check the entire requirement
136+ // / signature at the end. However, rejecting witnesses that are definitely
137+ // / invalid here can cut down the search space.
138138static CheckTypeWitnessResult
139139checkTypeWitness (Type type, AssociatedTypeDecl *assocType,
140140 const NormalProtocolConformance *Conf,
141141 SubstOptions options) {
142+ assert (!type->hasTypeParameter ());
143+
142144 auto &ctx = assocType->getASTContext ();
143145
144146 if (type->hasError ())
145147 return CheckTypeWitnessResult::forError ();
146148
149+ // If the type witness is equivalent to some other unresolved witness,
150+ // we cannot check anything, so accept the witness.
151+ if (type->is <DependentMemberType>())
152+ return CheckTypeWitnessResult::forSuccess ();
153+
147154 const auto proto = Conf->getProtocol ();
148155 const auto dc = Conf->getDeclContext ();
149156 const auto sig = proto->getGenericSignature ();
@@ -167,53 +174,43 @@ checkTypeWitness(Type type, AssociatedTypeDecl *assocType,
167174 const auto depTy = DependentMemberType::get (proto->getSelfInterfaceType (),
168175 assocType);
169176
170- Type contextType = type->hasTypeParameter () ? dc->mapTypeIntoContext (type)
171- : type;
172-
173177 if (auto superclass = sig->getSuperclassBound (depTy)) {
174- if (superclass->hasTypeParameter ()) {
175- // Replace type parameters with other known or tentative type witnesses.
176- superclass = superclass.subst (
177- [&](SubstitutableType *type) {
178- if (type->isEqual (proto->getSelfInterfaceType ()))
179- return Conf->getType ();
180-
181- return Type ();
182- },
183- LookUpConformanceInModule (dc->getParentModule ()), options);
184-
185- if (superclass->hasTypeParameter ())
186- superclass = dc->mapTypeIntoContext (superclass);
178+ // We only check that the type's superclass declaration is correct.
179+ // If the superclass bound is generic, we may not have resolved all of
180+ // the type witnesses that appear in generic arguments yet, and doing so
181+ // here might run into a request cycle.
182+ auto superclassDecl = superclass->getClassOrBoundGenericClass ();
183+ assert (superclassDecl);
184+
185+ // Fish a class declaration out of the type witness.
186+ auto classDecl = type->getClassOrBoundGenericClass ();
187+ if (!classDecl) {
188+ if (auto archetype = type->getAs <ArchetypeType>()) {
189+ if (auto superclassType = archetype->getSuperclass ())
190+ classDecl = superclassType->getClassOrBoundGenericClass ();
191+ }
187192 }
188- if (!superclass->isExactSuperclassOf (contextType))
193+
194+ if (!classDecl || !superclassDecl->isSuperclassOf (classDecl))
189195 return CheckTypeWitnessResult::forSuperclass (superclass);
190196 }
191197
192198 auto *module = dc->getParentModule ();
193199
194- // Check protocol conformances.
200+ // Check protocol conformances. We don't check conditional requirements here.
195201 for (const auto reqProto : sig->getRequiredProtocols (depTy)) {
196202 if (module ->lookupConformance (
197- contextType , reqProto,
203+ type , reqProto,
198204 /* allowMissing=*/ reqProto->isSpecificProtocol (
199205 KnownProtocolKind::Sendable))
200206 .isInvalid ())
201207 return CheckTypeWitnessResult::forConformance (reqProto);
202208 }
203209
210+ // We can completely check an AnyObject layout constraint.
204211 if (sig->requiresClass (depTy) &&
205- !contextType->satisfiesClassConstraint ()) {
206- return CheckTypeWitnessResult::forLayout (
207- module ->getASTContext ().getAnyObjectType ());
208- }
209-
210- // Tuple conformances can only witness associated types by projecting them
211- // element-wise.
212- if (isa<BuiltinTupleDecl>(dc->getSelfNominalTypeDecl ())) {
213- auto expectedTy = getTupleConformanceTypeWitness (dc, assocType);
214- if (!expectedTy->isEqual (type)) {
215- return CheckTypeWitnessResult::forTuple (expectedTy);
216- }
212+ !type->satisfiesClassConstraint ()) {
213+ return CheckTypeWitnessResult::forLayout (ctx.getAnyObjectType ());
217214 }
218215
219216 // Success!
@@ -222,10 +219,21 @@ checkTypeWitness(Type type, AssociatedTypeDecl *assocType,
222219
223220}
224221
222+ static bool containsConcreteDependentMemberType (Type ty) {
223+ return ty.findIf ([](Type t) -> bool {
224+ if (auto *dmt = t->getAs <DependentMemberType>())
225+ return !dmt->isTypeParameter ();
226+
227+ return false ;
228+ });
229+ }
230+
225231static void recordTypeWitness (NormalProtocolConformance *conformance,
226232 AssociatedTypeDecl *assocType,
227233 Type type,
228234 TypeDecl *typeDecl) {
235+ assert (!containsConcreteDependentMemberType (type));
236+
229237 // If we already recoded this type witness, there's nothing to do.
230238 if (conformance->hasTypeWitness (assocType)) {
231239 assert (conformance->getTypeWitnessUncached (assocType)
@@ -473,9 +481,12 @@ static ResolveWitnessResult resolveTypeWitnessViaLookup(
473481 if (!viableTypes.insert (memberType->getCanonicalType ()).second )
474482 continue ;
475483
484+ auto memberTypeInContext = dc->mapTypeIntoContext (memberType);
485+
476486 // Check this type against the protocol requirements.
477487 if (auto checkResult =
478- checkTypeWitness (memberType, assocType, conformance, llvm::None)) {
488+ checkTypeWitness (memberTypeInContext, assocType,
489+ conformance, llvm::None)) {
479490 nonViable.push_back ({typeDecl, checkResult});
480491 } else {
481492 viable.push_back ({typeDecl, memberType, nullptr });
@@ -551,14 +562,6 @@ static ResolveWitnessResult resolveTypeWitnessViaLookup(
551562 candidate.first ->getDeclaredInterfaceType (),
552563 candidate.second .getRequirement ());
553564 break ;
554-
555- case CheckTypeWitnessResult::Tuple:
556- diags.diagnose (
557- candidate.first ,
558- diag::protocol_type_witness_tuple,
559- candidate.first ->getDeclaredInterfaceType (),
560- candidate.second .getRequirement ());
561- break ;
562565 }
563566 }
564567 });
@@ -1353,7 +1356,6 @@ enum class InferenceCandidateKind {
13531356
13541357static InferenceCandidateKind checkInferenceCandidate (
13551358 std::pair<AssociatedTypeDecl *, Type> *result,
1356- bool *canInferFromOtherAssociatedType,
13571359 NormalProtocolConformance *conformance,
13581360 ValueDecl *witness) {
13591361 auto isTautological = [&](Type t) -> bool {
@@ -1418,7 +1420,6 @@ static InferenceCandidateKind checkInferenceCandidate(
14181420 return otherDMT;
14191421 return t;
14201422 });
1421- *canInferFromOtherAssociatedType = true ;
14221423 LLVM_DEBUG (llvm::dbgs () << " ++ we can same-type to:\n " ;
14231424 result->second ->dump (llvm::dbgs ()));
14241425 return InferenceCandidateKind::Good;
@@ -1543,11 +1544,7 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
15431544 // Filter out circular possibilities, e.g. that
15441545 // AssocType == S.AssocType or
15451546 // AssocType == Foo<S.AssocType>.
1546- bool canInferFromOtherAssociatedType = false ;
1547-
1548- switch (checkInferenceCandidate (&result,
1549- &canInferFromOtherAssociatedType,
1550- conformance, witness)) {
1547+ switch (checkInferenceCandidate (&result, conformance, witness)) {
15511548 case InferenceCandidateKind::Good:
15521549 // Continued below.
15531550 break ;
@@ -1588,23 +1585,19 @@ AssociatedTypeInference::getPotentialTypeWitnessesFromRequirement(
15881585 }
15891586 }
15901587
1591- // If we same-typed to another unresolved associated type, we won't
1592- // be able to check conformances yet.
1593- if (!canInferFromOtherAssociatedType) {
1594- // Check that the type witness meets the
1595- // requirements on the associated type.
1596- if (auto failed =
1597- checkTypeWitness (result.second , result.first , conformance,
1598- llvm::None)) {
1599- witnessResult.NonViable .push_back (
1600- std::make_tuple (result.first ,result.second ,failed));
1601- LLVM_DEBUG (llvm::dbgs () << " -- doesn't fulfill requirements\n " );
1602-
1603- // By adding an element to NonViable we ensure the witness is rejected
1604- // below, so we continue to consider other bindings to generate better
1605- // diagnostics later.
1606- REJECT;
1607- }
1588+ // Check that the type witness meets the requirements on the
1589+ // associated type.
1590+ if (auto failed =
1591+ checkTypeWitness (result.second , result.first , conformance,
1592+ llvm::None)) {
1593+ witnessResult.NonViable .push_back (
1594+ std::make_tuple (result.first ,result.second ,failed));
1595+ LLVM_DEBUG (llvm::dbgs () << " -- doesn't fulfill requirements\n " );
1596+
1597+ // By adding an element to NonViable we ensure the witness is rejected
1598+ // below, so we continue to consider other bindings to generate better
1599+ // diagnostics later.
1600+ REJECT;
16081601 }
16091602
16101603 LLVM_DEBUG (llvm::dbgs () << " ++ seems legit\n " );
@@ -2286,6 +2279,8 @@ AssociatedTypeInference::computeDerivedTypeWitness(
22862279 if (!result.first )
22872280 return std::make_pair (Type (), nullptr );
22882281
2282+ assert (!containsConcreteDependentMemberType (result.first ));
2283+
22892284 // Make sure that the derived type satisfies requirements.
22902285 if (checkTypeWitness (result.first , assocType, conformance, llvm::None)) {
22912286 // / FIXME: Diagnose based on this.
@@ -2649,15 +2644,6 @@ bool AssociatedTypeInference::checkConstrainedExtension(ExtensionDecl *ext) {
26492644 llvm_unreachable (" unhandled result" );
26502645}
26512646
2652- static bool containsConcreteDependentMemberType (Type ty) {
2653- return ty.findIf ([](Type t) -> bool {
2654- if (auto *dmt = t->getAs <DependentMemberType>())
2655- return !dmt->isTypeParameter ();
2656-
2657- return false ;
2658- });
2659- }
2660-
26612647AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses (
26622648 ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes, unsigned reqDepth) {
26632649 if (unresolvedAssocTypes.empty ()) {
@@ -3560,16 +3546,6 @@ bool AssociatedTypeInference::diagnoseNoSolutions(
35603546 proto->getDeclaredInterfaceType (),
35613547 failedDefaultedResult.getRequirement ());
35623548 break ;
3563-
3564- case CheckTypeWitnessResult::Tuple:
3565- diags.diagnose (
3566- failedDefaultedAssocType,
3567- diag::default_associated_type_tuple,
3568- failedDefaultedWitness,
3569- failedDefaultedAssocType,
3570- proto->getDeclaredInterfaceType (),
3571- failedDefaultedResult.getRequirement ());
3572- break ;
35733549 }
35743550 });
35753551
@@ -3675,14 +3651,6 @@ bool AssociatedTypeInference::diagnoseNoSolutions(
36753651 assocType, failed.TypeWitness ,
36763652 failed.Result .getRequirement ());
36773653 break ;
3678-
3679- case CheckTypeWitnessResult::Tuple:
3680- diags.diagnose (
3681- failed.Witness ,
3682- diag::associated_type_deduction_tuple,
3683- assocType, failed.TypeWitness ,
3684- failed.Result .getRequirement ());
3685- break ;
36863654 }
36873655 }
36883656 });
0 commit comments