//===--- CSFix.cpp - Constraint Fixes -------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file implements the \c ConstraintFix class and its related types, // which is used by constraint solver to attempt to fix constraints to be // able to produce a solution which is easily diagnosable. // //===----------------------------------------------------------------------===// #include "CSFix.h" #include "CSDiagnostics.h" #include "ConstraintLocator.h" #include "ConstraintSystem.h" #include "swift/AST/Expr.h" #include "swift/AST/Type.h" #include "swift/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/raw_ostream.h" #include using namespace swift; using namespace constraints; ConstraintFix::~ConstraintFix() {} Expr *ConstraintFix::getAnchor() const { return getLocator()->getAnchor(); } void ConstraintFix::print(llvm::raw_ostream &Out) const { Out << "[fix: "; Out << getName(); Out << ']'; Out << " @ "; getLocator()->dump(&CS.getASTContext().SourceMgr, Out); } void ConstraintFix::dump() const {print(llvm::errs()); } std::string ForceDowncast::getName() const { llvm::SmallString<16> name; name += "force downcast (as! "; name += DowncastTo->getString(); name += ")"; return name.c_str(); } bool ForceDowncast::diagnose(Expr *expr, bool asNote) const { MissingExplicitConversionFailure failure(expr, getConstraintSystem(), getLocator(), DowncastTo); return failure.diagnose(asNote); } ForceDowncast *ForceDowncast::create(ConstraintSystem &cs, Type toType, ConstraintLocator *locator) { return new (cs.getAllocator()) ForceDowncast(cs, toType, locator); } bool ForceOptional::diagnose(Expr *root, bool asNote) const { MissingOptionalUnwrapFailure failure(root, getConstraintSystem(), getLocator()); return failure.diagnose(asNote); } ForceOptional *ForceOptional::create(ConstraintSystem &cs, ConstraintLocator *locator) { return new (cs.getAllocator()) ForceOptional(cs, locator); } bool UnwrapOptionalBase::diagnose(Expr *root, bool asNote) const { bool resultIsOptional = getKind() == FixKind::UnwrapOptionalBaseWithOptionalResult; MemberAccessOnOptionalBaseFailure failure( root, getConstraintSystem(), getLocator(), MemberName, resultIsOptional); return failure.diagnose(asNote); } UnwrapOptionalBase *UnwrapOptionalBase::create(ConstraintSystem &cs, DeclName member, ConstraintLocator *locator) { return new (cs.getAllocator()) UnwrapOptionalBase(cs, FixKind::UnwrapOptionalBase, member, locator); } UnwrapOptionalBase *UnwrapOptionalBase::createWithOptionalResult( ConstraintSystem &cs, DeclName member, ConstraintLocator *locator) { return new (cs.getAllocator()) UnwrapOptionalBase( cs, FixKind::UnwrapOptionalBaseWithOptionalResult, member, locator); } bool AddAddressOf::diagnose(Expr *root, bool asNote) const { MissingAddressOfFailure failure(root, getConstraintSystem(), getLocator()); return failure.diagnose(asNote); } AddAddressOf *AddAddressOf::create(ConstraintSystem &cs, ConstraintLocator *locator) { return new (cs.getAllocator()) AddAddressOf(cs, locator); } bool TreatRValueAsLValue::diagnose(Expr *root, bool asNote) const { RValueTreatedAsLValueFailure failure(getConstraintSystem(), getLocator()); return failure.diagnose(asNote); } TreatRValueAsLValue *TreatRValueAsLValue::create(ConstraintSystem &cs, ConstraintLocator *locator) { return new (cs.getAllocator()) TreatRValueAsLValue(cs, locator); } bool CoerceToCheckedCast::diagnose(Expr *root, bool asNote) const { MissingForcedDowncastFailure failure(root, getConstraintSystem(), getLocator()); return failure.diagnose(asNote); } CoerceToCheckedCast *CoerceToCheckedCast::create(ConstraintSystem &cs, ConstraintLocator *locator) { return new (cs.getAllocator()) CoerceToCheckedCast(cs, locator); } bool MarkExplicitlyEscaping::diagnose(Expr *root, bool asNote) const { NoEscapeFuncToTypeConversionFailure failure(root, getConstraintSystem(), getLocator(), ConvertTo); return failure.diagnose(asNote); } MarkExplicitlyEscaping * MarkExplicitlyEscaping::create(ConstraintSystem &cs, ConstraintLocator *locator, Type convertingTo) { return new (cs.getAllocator()) MarkExplicitlyEscaping(cs, locator, convertingTo); } bool RelabelArguments::diagnose(Expr *root, bool asNote) const { LabelingFailure failure(getConstraintSystem(), getLocator(), getLabels()); return failure.diagnose(asNote); } RelabelArguments * RelabelArguments::create(ConstraintSystem &cs, llvm::ArrayRef correctLabels, ConstraintLocator *locator) { unsigned size = totalSizeToAlloc(correctLabels.size()); void *mem = cs.getAllocator().Allocate(size, alignof(RelabelArguments)); return new (mem) RelabelArguments(cs, correctLabels, locator); } bool MissingConformance::diagnose(Expr *root, bool asNote) const { MissingConformanceFailure failure(root, getConstraintSystem(), getLocator(), {NonConformingType, Protocol}); return failure.diagnose(asNote); } MissingConformance *MissingConformance::create(ConstraintSystem &cs, Type type, ProtocolDecl *protocol, ConstraintLocator *locator) { return new (cs.getAllocator()) MissingConformance(cs, type, protocol, locator); } bool SkipSameTypeRequirement::diagnose(Expr *root, bool asNote) const { SameTypeRequirementFailure failure(root, getConstraintSystem(), LHS, RHS, getLocator()); return failure.diagnose(asNote); } SkipSameTypeRequirement * SkipSameTypeRequirement::create(ConstraintSystem &cs, Type lhs, Type rhs, ConstraintLocator *locator) { return new (cs.getAllocator()) SkipSameTypeRequirement(cs, lhs, rhs, locator); } bool SkipSuperclassRequirement::diagnose(Expr *root, bool asNote) const { SuperclassRequirementFailure failure(root, getConstraintSystem(), LHS, RHS, getLocator()); return failure.diagnose(asNote); } SkipSuperclassRequirement * SkipSuperclassRequirement::create(ConstraintSystem &cs, Type lhs, Type rhs, ConstraintLocator *locator) { return new (cs.getAllocator()) SkipSuperclassRequirement(cs, lhs, rhs, locator); } bool ContextualMismatch::diagnose(Expr *root, bool asNote) const { auto failure = ContextualFailure(root, getConstraintSystem(), getFromType(), getToType(), getLocator()); return failure.diagnose(asNote); } ContextualMismatch *ContextualMismatch::create(ConstraintSystem &cs, Type lhs, Type rhs, ConstraintLocator *locator) { return new (cs.getAllocator()) ContextualMismatch(cs, lhs, rhs, locator); }