|
22 | 22 | #include "swift/AST/Module.h"
|
23 | 23 | #include "swift/AST/NameLookup.h"
|
24 | 24 | #include "swift/AST/ProtocolConformance.h"
|
| 25 | +#include "swift/AST/Requirement.h" |
25 | 26 | #include "swift/AST/SourceFile.h"
|
26 | 27 | #include "swift/AST/Types.h"
|
27 | 28 | #include "swift/Sema/IDETypeChecking.h"
|
@@ -169,13 +170,13 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
169 | 170 | bool Unmergable;
|
170 | 171 | unsigned InheritsCount;
|
171 | 172 | std::set<Requirement> Requirements;
|
172 |
| - void addRequirement(GenericSignature GenericSig, |
173 |
| - Type First, Type Second, RequirementKind Kind) { |
174 |
| - CanType CanFirst = GenericSig->getCanonicalTypeInContext(First); |
175 |
| - CanType CanSecond; |
176 |
| - if (Second) CanSecond = GenericSig->getCanonicalTypeInContext(Second); |
| 173 | + void addRequirement(GenericSignature GenericSig, swift::Requirement Req) { |
| 174 | + auto First = Req.getFirstType(); |
| 175 | + auto CanFirst = GenericSig->getCanonicalTypeInContext(First); |
| 176 | + auto Second = Req.getSecondType(); |
| 177 | + auto CanSecond = GenericSig->getCanonicalTypeInContext(Second); |
177 | 178 |
|
178 |
| - Requirements.insert({First, Second, Kind, CanFirst, CanSecond}); |
| 179 | + Requirements.insert({First, Second, Req.getKind(), CanFirst, CanSecond}); |
179 | 180 | }
|
180 | 181 | bool operator== (const ExtensionMergeInfo& Another) const {
|
181 | 182 | // Trivially unmergeable.
|
@@ -289,84 +290,53 @@ struct SynthesizedExtensionAnalyzer::Implementation {
|
289 | 290 | ProtocolDecl *BaseProto = OwningExt->getInnermostDeclContext()
|
290 | 291 | ->getSelfProtocolDecl();
|
291 | 292 | for (auto Req : Reqs) {
|
292 |
| - auto Kind = Req.getKind(); |
293 |
| - |
294 |
| - // FIXME: Could do something here |
295 |
| - if (Kind == RequirementKind::Layout) |
| 293 | + // FIXME: Don't skip layout requirements. |
| 294 | + if (Req.getKind() == RequirementKind::Layout) |
296 | 295 | continue;
|
297 | 296 |
|
298 |
| - Type First = Req.getFirstType(); |
299 |
| - Type Second = Req.getSecondType(); |
300 |
| - |
301 | 297 | // Skip protocol's Self : <Protocol> requirement.
|
302 | 298 | if (BaseProto &&
|
303 | 299 | Req.getKind() == RequirementKind::Conformance &&
|
304 |
| - First->isEqual(BaseProto->getSelfInterfaceType()) && |
305 |
| - Second->getAnyNominal() == BaseProto) |
| 300 | + Req.getFirstType()->isEqual(BaseProto->getSelfInterfaceType()) && |
| 301 | + Req.getProtocolDecl() == BaseProto) |
306 | 302 | continue;
|
307 | 303 |
|
308 | 304 | if (!BaseType->isExistentialType()) {
|
309 | 305 | // Apply any substitutions we need to map the requirements from a
|
310 | 306 | // a protocol extension to an extension on the conforming type.
|
311 |
| - First = First.subst(subMap); |
312 |
| - Second = Second.subst(subMap); |
313 |
| - |
314 |
| - if (First->hasError() || Second->hasError()) { |
| 307 | + auto SubstReq = Req.subst(subMap); |
| 308 | + if (!SubstReq) { |
315 | 309 | // Substitution with interface type bases can only fail
|
316 | 310 | // if a concrete type fails to conform to a protocol.
|
317 | 311 | // In this case, just give up on the extension altogether.
|
318 | 312 | return true;
|
319 | 313 | }
|
320 |
| - } |
321 | 314 |
|
322 |
| - assert(!First->hasArchetype() && !Second->hasArchetype()); |
323 |
| - switch (Kind) { |
324 |
| - case RequirementKind::Conformance: { |
325 |
| - auto *M = DC->getParentModule(); |
326 |
| - auto *Proto = Second->castTo<ProtocolType>()->getDecl(); |
327 |
| - if (!First->isTypeParameter() && |
328 |
| - M->conformsToProtocol(First, Proto).isInvalid()) |
329 |
| - return true; |
330 |
| - if (M->conformsToProtocol(First, Proto).isInvalid()) |
331 |
| - MergeInfo.addRequirement(GenericSig, First, Second, Kind); |
332 |
| - break; |
| 315 | + Req = *SubstReq; |
333 | 316 | }
|
334 | 317 |
|
335 |
| - case RequirementKind::Superclass: |
336 |
| - // If the subject type of the requirement is still a type parameter, |
337 |
| - // we need to check if the contextual type could possibly be bound to |
338 |
| - // the superclass. If not, this extension isn't applicable. |
339 |
| - if (First->isTypeParameter()) { |
340 |
| - if (!Target->mapTypeIntoContext(First)->isBindableTo( |
341 |
| - Target->mapTypeIntoContext(Second))) { |
342 |
| - return true; |
343 |
| - } |
344 |
| - MergeInfo.addRequirement(GenericSig, First, Second, Kind); |
345 |
| - break; |
346 |
| - } |
347 |
| - |
348 |
| - // If we've substituted in a concrete type for the subject, we can |
349 |
| - // check for an exact superclass match, and disregard the extension if |
350 |
| - // it missed. |
351 |
| - // FIXME: What if it ends being something like `C<U> : C<Int>`? |
352 |
| - // Arguably we should allow that to be mirrored with a U == Int |
353 |
| - // constraint. |
354 |
| - if (!Second->isExactSuperclassOf(First)) |
355 |
| - return true; |
356 |
| - |
357 |
| - break; |
358 |
| - |
359 |
| - case RequirementKind::SameType: |
360 |
| - if (!First->isBindableTo(Second) && |
361 |
| - !Second->isBindableTo(First)) { |
| 318 | + assert(!Req.getFirstType()->hasArchetype()); |
| 319 | + assert(!Req.getSecondType()->hasArchetype()); |
| 320 | + |
| 321 | + auto *M = DC->getParentModule(); |
| 322 | + auto SubstReq = Req.subst( |
| 323 | + [&](Type type) -> Type { |
| 324 | + if (type->isTypeParameter()) |
| 325 | + return Target->mapTypeIntoContext(type); |
| 326 | + |
| 327 | + return type; |
| 328 | + }, |
| 329 | + LookUpConformanceInModule(M)); |
| 330 | + if (!SubstReq) |
| 331 | + return true; |
| 332 | + |
| 333 | + // FIXME: Need to handle conditional requirements here! |
| 334 | + ArrayRef<Requirement> conditionalRequirements; |
| 335 | + if (!SubstReq->isSatisfied(conditionalRequirements)) { |
| 336 | + if (!SubstReq->canBeSatisfied()) |
362 | 337 | return true;
|
363 |
| - } else if (!First->isEqual(Second)) { |
364 |
| - MergeInfo.addRequirement(GenericSig, First, Second, Kind); |
365 |
| - } |
366 |
| - break; |
367 | 338 |
|
368 |
| - case RequirementKind::Layout: |
369 |
| - llvm_unreachable("Handled above"); |
| 339 | + MergeInfo.addRequirement(GenericSig, Req); |
370 | 340 | }
|
371 | 341 | }
|
372 | 342 | return false;
|
|
0 commit comments