@@ -182,7 +182,8 @@ class ConcreteContraction {
182182
183183 bool performConcreteContraction (
184184 ArrayRef<StructuralRequirement> requirements,
185- SmallVectorImpl<StructuralRequirement> &result);
185+ SmallVectorImpl<StructuralRequirement> &result,
186+ SmallVectorImpl<RequirementError> &errors);
186187};
187188
188189} // end namespace
@@ -380,6 +381,13 @@ ConcreteContraction::substRequirement(const Requirement &req) const {
380381
381382 case RequirementKind::Layout: {
382383 auto substFirstType = substTypeParameter (firstType);
384+ if (!substFirstType->isTypeParameter () &&
385+ !substFirstType->satisfiesClassConstraint () &&
386+ req.getLayoutConstraint ()->isClass ()) {
387+ // If the concrete type doesn't satisfy the layout constraint,
388+ // leave it unsubstituted so that we produce a better diagnostic.
389+ return req;
390+ }
383391
384392 return Requirement (req.getKind (),
385393 substFirstType,
@@ -464,7 +472,8 @@ bool ConcreteContraction::preserveSameTypeRequirement(
464472// / original \p requirements.
465473bool ConcreteContraction::performConcreteContraction (
466474 ArrayRef<StructuralRequirement> requirements,
467- SmallVectorImpl<StructuralRequirement> &result) {
475+ SmallVectorImpl<StructuralRequirement> &result,
476+ SmallVectorImpl<RequirementError> &errors) {
468477
469478 // Phase 1 - collect concrete type and superclass requirements where the
470479 // subject type is a generic parameter.
@@ -577,47 +586,25 @@ bool ConcreteContraction::performConcreteContraction(
577586 llvm::dbgs () << " \n " ;
578587 }
579588
580- if (preserveSameTypeRequirement (req.req )) {
581- if (Debug) {
582- llvm::dbgs () << " @ Preserving original requirement: " ;
583- req.req .dump (llvm::dbgs ());
584- llvm::dbgs () << " \n " ;
585- }
586-
587- // Make the duplicated requirement 'inferred' so that we don't diagnose
588- // it as redundant.
589- result.push_back ({req.req , SourceLoc (), /* inferred=*/ true });
590- }
591-
592589 // Substitute the requirement.
593- Optional<Requirement> substReq = substRequirement (req.req );
594-
595- // If substitution failed, we have a conflict; bail out here so that we can
596- // diagnose the conflict later.
597- if (!substReq) {
598- if (Debug) {
599- llvm::dbgs () << " @ Concrete contraction cannot proceed; requirement " ;
600- llvm::dbgs () << " substitution failed:\n " ;
601- req.req .dump (llvm::dbgs ());
602- llvm::dbgs () << " \n " ;
603- }
604-
605- continue ;
606- }
590+ auto substReq = substRequirement (req.req );
607591
608592 if (Debug) {
609593 llvm::dbgs () << " @ Substituted requirement: " ;
610- substReq-> dump (llvm::dbgs ());
594+ substReq. dump (llvm::dbgs ());
611595 llvm::dbgs () << " \n " ;
612596 }
613597
614598 // Otherwise, desugar the requirement again, since we might now have a
615599 // requirement where the left hand side is not a type parameter.
616- //
617- // FIXME: Do we need to check for errors? Right now they're just ignored.
618600 SmallVector<Requirement, 4 > reqs;
619- SmallVector<RequirementError, 1 > errors;
620- desugarRequirement (*substReq, reqs, errors);
601+ if (req.inferred ) {
602+ SmallVector<RequirementError, 4 > discardErrors;
603+ desugarRequirement (substReq, SourceLoc (), reqs, discardErrors);
604+ } else {
605+ desugarRequirement (substReq, req.loc , reqs, errors);
606+ }
607+
621608 for (auto desugaredReq : reqs) {
622609 if (Debug) {
623610 llvm::dbgs () << " @@ Desugared requirement: " ;
@@ -626,6 +613,20 @@ bool ConcreteContraction::performConcreteContraction(
626613 }
627614 result.push_back ({desugaredReq, req.loc , req.inferred });
628615 }
616+
617+ if (preserveSameTypeRequirement (req.req ) &&
618+ (!req.req .getFirstType ()->isEqual (substReq.getFirstType ()) ||
619+ !req.req .getSecondType ()->isEqual (substReq.getSecondType ()))) {
620+ if (Debug) {
621+ llvm::dbgs () << " @ Preserving original requirement: " ;
622+ req.req .dump (llvm::dbgs ());
623+ llvm::dbgs () << " \n " ;
624+ }
625+
626+ // Make the duplicated requirement 'inferred' so that we don't diagnose
627+ // it as redundant.
628+ result.push_back ({req.req , SourceLoc (), /* inferred=*/ true });
629+ }
629630 }
630631
631632 if (Debug) {
@@ -647,7 +648,9 @@ bool ConcreteContraction::performConcreteContraction(
647648bool swift::rewriting::performConcreteContraction (
648649 ArrayRef<StructuralRequirement> requirements,
649650 SmallVectorImpl<StructuralRequirement> &result,
651+ SmallVectorImpl<RequirementError> &errors,
650652 bool debug) {
651653 ConcreteContraction concreteContraction (debug);
652- return concreteContraction.performConcreteContraction (requirements, result);
654+ return concreteContraction.performConcreteContraction (
655+ requirements, result, errors);
653656}
0 commit comments