|
36 | 36 | using namespace swift;
|
37 | 37 | using namespace rewriting;
|
38 | 38 |
|
| 39 | +/// Hack for GenericSignatureBuilder compatibility. We might end up with a |
| 40 | +/// same-type requirement between type parameters where one of them has an |
| 41 | +/// implied concrete type requirement. In this case, split it up into two |
| 42 | +/// concrete type requirements. |
| 43 | +static bool shouldSplitConcreteEquivalenceClass(Requirement req, |
| 44 | + GenericSignature sig) { |
| 45 | + return (req.getKind() == RequirementKind::SameType && |
| 46 | + req.getSecondType()->isTypeParameter() && |
| 47 | + sig->isConcreteType(req.getSecondType())); |
| 48 | +} |
| 49 | + |
| 50 | +/// Returns true if this generic signature contains abstract same-type |
| 51 | +/// requirements between concrete type parameters. In this case, we split |
| 52 | +/// the abstract same-type requirements into pairs of concrete type |
| 53 | +/// requirements, and minimize the signature again. |
| 54 | +static bool shouldSplitConcreteEquivalenceClasses(GenericSignature sig) { |
| 55 | + for (auto req : sig.getRequirements()) { |
| 56 | + if (shouldSplitConcreteEquivalenceClass(req, sig)) |
| 57 | + return true; |
| 58 | + } |
| 59 | + |
| 60 | + return false; |
| 61 | +} |
| 62 | + |
| 63 | +/// Replace each same-type requirement 'T == U' where 'T' (and therefore 'U') |
| 64 | +/// is known to equal a concrete type 'C' with a pair of requirements |
| 65 | +/// 'T == C' and 'U == C'. We build the signature again in this case, since |
| 66 | +/// one of the two requirements will be redundant, but we don't know which |
| 67 | +/// ahead of time. |
| 68 | +static void splitConcreteEquivalenceClasses( |
| 69 | + ASTContext &ctx, |
| 70 | + GenericSignature sig, |
| 71 | + SmallVectorImpl<StructuralRequirement> &requirements, |
| 72 | + unsigned &attempt) { |
| 73 | + unsigned maxAttempts = |
| 74 | + ctx.LangOpts.RequirementMachineMaxSplitConcreteEquivClassAttempts; |
| 75 | + |
| 76 | + ++attempt; |
| 77 | + if (attempt >= maxAttempts) { |
| 78 | + llvm::errs() << "Splitting concrete equivalence classes did not " |
| 79 | + << "reach fixed point after " << attempt << " attempts.\n"; |
| 80 | + llvm::errs() << "Last result: " << sig << "\n"; |
| 81 | + abort(); |
| 82 | + } |
| 83 | + |
| 84 | + requirements.clear(); |
| 85 | + |
| 86 | + for (auto req : sig.getRequirements()) { |
| 87 | + if (shouldSplitConcreteEquivalenceClass(req, sig)) { |
| 88 | + auto canType = sig->getSugaredType( |
| 89 | + sig.getCanonicalTypeInContext( |
| 90 | + req.getSecondType())); |
| 91 | + |
| 92 | + Requirement firstReq(RequirementKind::SameType, |
| 93 | + req.getFirstType(), canType); |
| 94 | + Requirement secondReq(RequirementKind::SameType, |
| 95 | + req.getSecondType(), canType); |
| 96 | + requirements.push_back({firstReq, SourceLoc(), /*inferred=*/false}); |
| 97 | + requirements.push_back({secondReq, SourceLoc(), /*inferred=*/false}); |
| 98 | + continue; |
| 99 | + } |
| 100 | + |
| 101 | + requirements.push_back({req, SourceLoc(), /*inferred=*/false}); |
| 102 | + } |
| 103 | +} |
| 104 | + |
39 | 105 | /// Builds the requirement signatures for each protocol in this strongly
|
40 | 106 | /// connected component.
|
41 | 107 | llvm::DenseMap<const ProtocolDecl *, RequirementSignature>
|
@@ -243,72 +309,6 @@ static bool isCanonicalRequest(GenericSignature baseSignature,
|
243 | 309 | return true;
|
244 | 310 | }
|
245 | 311 |
|
246 |
| -/// Hack for GenericSignatureBuilder compatibility. We might end up with a |
247 |
| -/// same-type requirement between type parameters where one of them has an |
248 |
| -/// implied concrete type requirement. In this case, split it up into two |
249 |
| -/// concrete type requirements. |
250 |
| -static bool shouldSplitConcreteEquivalenceClass(Requirement req, |
251 |
| - GenericSignature sig) { |
252 |
| - return (req.getKind() == RequirementKind::SameType && |
253 |
| - req.getSecondType()->isTypeParameter() && |
254 |
| - sig->isConcreteType(req.getSecondType())); |
255 |
| -} |
256 |
| - |
257 |
| -/// Returns true if this generic signature contains abstract same-type |
258 |
| -/// requirements between concrete type parameters. In this case, we split |
259 |
| -/// the abstract same-type requirements into pairs of concrete type |
260 |
| -/// requirements, and minimize the signature again. |
261 |
| -static bool shouldSplitConcreteEquivalenceClasses(GenericSignature sig) { |
262 |
| - for (auto req : sig.getRequirements()) { |
263 |
| - if (shouldSplitConcreteEquivalenceClass(req, sig)) |
264 |
| - return true; |
265 |
| - } |
266 |
| - |
267 |
| - return false; |
268 |
| -} |
269 |
| - |
270 |
| -/// Replace each same-type requirement 'T == U' where 'T' (and therefore 'U') |
271 |
| -/// is known to equal a concrete type 'C' with a pair of requirements |
272 |
| -/// 'T == C' and 'U == C'. We build the signature again in this case, since |
273 |
| -/// one of the two requirements will be redundant, but we don't know which |
274 |
| -/// ahead of time. |
275 |
| -static void splitConcreteEquivalenceClasses( |
276 |
| - ASTContext &ctx, |
277 |
| - GenericSignature sig, |
278 |
| - SmallVectorImpl<StructuralRequirement> &requirements, |
279 |
| - unsigned &attempt) { |
280 |
| - unsigned maxAttempts = |
281 |
| - ctx.LangOpts.RequirementMachineMaxSplitConcreteEquivClassAttempts; |
282 |
| - |
283 |
| - ++attempt; |
284 |
| - if (attempt >= maxAttempts) { |
285 |
| - llvm::errs() << "Splitting concrete equivalence classes did not " |
286 |
| - << "reach fixed point after " << attempt << " attempts.\n"; |
287 |
| - llvm::errs() << "Last result: " << sig << "\n"; |
288 |
| - abort(); |
289 |
| - } |
290 |
| - |
291 |
| - requirements.clear(); |
292 |
| - |
293 |
| - for (auto req : sig.getRequirements()) { |
294 |
| - if (shouldSplitConcreteEquivalenceClass(req, sig)) { |
295 |
| - auto canType = sig->getSugaredType( |
296 |
| - sig.getCanonicalTypeInContext( |
297 |
| - req.getSecondType())); |
298 |
| - |
299 |
| - Requirement firstReq(RequirementKind::SameType, |
300 |
| - req.getFirstType(), canType); |
301 |
| - Requirement secondReq(RequirementKind::SameType, |
302 |
| - req.getSecondType(), canType); |
303 |
| - requirements.push_back({firstReq, SourceLoc(), /*inferred=*/false}); |
304 |
| - requirements.push_back({secondReq, SourceLoc(), /*inferred=*/false}); |
305 |
| - continue; |
306 |
| - } |
307 |
| - |
308 |
| - requirements.push_back({req, SourceLoc(), /*inferred=*/false}); |
309 |
| - } |
310 |
| -} |
311 |
| - |
312 | 312 | GenericSignatureWithError
|
313 | 313 | AbstractGenericSignatureRequestRQM::evaluate(
|
314 | 314 | Evaluator &evaluator,
|
|
0 commit comments