@@ -246,7 +246,9 @@ int Requirement::compare(const Requirement &other) const {
246246 return compareProtos;
247247}
248248
249- CheckRequirementsResult swift::checkRequirements (ArrayRef<Requirement> requirements) {
249+ static std::optional<CheckRequirementsResult>
250+ checkRequirementsImpl (ArrayRef<Requirement> requirements,
251+ bool allowTypeParameters) {
250252 SmallVector<Requirement, 4 > worklist (requirements.begin (), requirements.end ());
251253
252254 bool hadSubstFailure = false ;
@@ -258,12 +260,20 @@ CheckRequirementsResult swift::checkRequirements(ArrayRef<Requirement> requireme
258260#ifndef NDEBUG
259261 {
260262 auto firstType = req.getFirstType ();
261- assert (!firstType->hasTypeParameter ());
263+ assert ((allowTypeParameters || !firstType->hasTypeParameter ())
264+ && " must take a contextual type. if you really are ok with an "
265+ " indefinite answer (and usually YOU ARE NOT), then consider whether "
266+ " you really, definitely are ok with an indefinite answer, and "
267+ " use `checkRequirementsWithoutContext` instead" );
262268 assert (!firstType->hasTypeVariable ());
263269
264270 if (req.getKind () != RequirementKind::Layout) {
265271 auto secondType = req.getSecondType ();
266- assert (!secondType->hasTypeParameter ());
272+ assert ((allowTypeParameters || !secondType->hasTypeParameter ())
273+ && " must take a contextual type. if you really are ok with an "
274+ " indefinite answer (and usually YOU ARE NOT), then consider whether "
275+ " you really, definitely are ok with an indefinite answer, and "
276+ " use `checkRequirementsWithoutContext` instead" );
267277 assert (!secondType->hasTypeVariable ());
268278 }
269279 }
@@ -276,6 +286,12 @@ CheckRequirementsResult swift::checkRequirements(ArrayRef<Requirement> requireme
276286 break ;
277287
278288 case CheckRequirementResult::RequirementFailure:
289+ // If a requirement failure was caused by a context-free type parameter,
290+ // then we can't definitely know whether it would have satisfied the
291+ // requirement without context.
292+ if (req.getFirstType ()->isTypeParameter ()) {
293+ return std::nullopt ;
294+ }
279295 return CheckRequirementsResult::RequirementFailure;
280296
281297 case CheckRequirementResult::SubstitutionFailure:
@@ -290,6 +306,19 @@ CheckRequirementsResult swift::checkRequirements(ArrayRef<Requirement> requireme
290306 return CheckRequirementsResult::Success;
291307}
292308
309+ CheckRequirementsResult
310+ swift::checkRequirements (ArrayRef<Requirement> requirements) {
311+ // This entry point requires that there are no type parameters in any of the
312+ // requirements, so the underlying check should always produce a result.
313+ return checkRequirementsImpl (requirements, /* allow type parameters*/ false )
314+ .value ();
315+ }
316+
317+ std::optional<CheckRequirementsResult>
318+ swift::checkRequirementsWithoutContext (ArrayRef<Requirement> requirements) {
319+ return checkRequirementsImpl (requirements, /* allow type parameters*/ true );
320+ }
321+
293322CheckRequirementsResult swift::checkRequirements (
294323 ModuleDecl *module , ArrayRef<Requirement> requirements,
295324 TypeSubstitutionFn substitutions, SubstOptions options) {
@@ -332,4 +361,4 @@ void InverseRequirement::expandDefaults(
332361 SourceLoc ()});
333362 }
334363 }
335- }
364+ }
0 commit comments