|
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