Files
swift-mirror/lib/Sema/CSFix.cpp
Pavel Yaskevich 74a8ee177e [Diagnostics] Diagnose missing members via fixes
Try to fix constraint system in a way where member
reference is going to be defined in terms of its use,
which makes it seem like parameters match arguments
exactly. Such helps to produce solutions and diagnose
failures related to missing members precisely.

These changes would be further extended to diagnose use
of unavailable members and other structural member failures.

Resolves: rdar://problem/34583132
Resolves: rdar://problem/36989788
Resolved: rdar://problem/39586166
Resolves: rdar://problem/40537782
Resolves: rdar://problem/46211109
2019-01-09 17:29:49 -08:00

261 lines
9.9 KiB
C++

//===--- 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/AST/Types.h"
#include "swift/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
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<Identifier> correctLabels,
ConstraintLocator *locator) {
unsigned size = totalSizeToAlloc<Identifier>(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);
}
bool AutoClosureForwarding::diagnose(Expr *root, bool asNote) const {
auto failure =
AutoClosureForwardingFailure(getConstraintSystem(), getLocator());
return failure.diagnose(asNote);
}
AutoClosureForwarding *AutoClosureForwarding::create(ConstraintSystem &cs,
ConstraintLocator *locator) {
return new (cs.getAllocator()) AutoClosureForwarding(cs, locator);
}
bool RemoveUnwrap::diagnose(Expr *root, bool asNote) const {
auto failure = NonOptionalUnwrapFailure(root, getConstraintSystem(), BaseType,
getLocator());
return failure.diagnose(asNote);
}
RemoveUnwrap *RemoveUnwrap::create(ConstraintSystem &cs, Type baseType,
ConstraintLocator *locator) {
return new (cs.getAllocator()) RemoveUnwrap(cs, baseType, locator);
}
bool InsertExplicitCall::diagnose(Expr *root, bool asNote) const {
auto failure = MissingCallFailure(root, getConstraintSystem(), getLocator());
return failure.diagnose(asNote);
}
InsertExplicitCall *InsertExplicitCall::create(ConstraintSystem &cs,
ConstraintLocator *locator) {
return new (cs.getAllocator()) InsertExplicitCall(cs, locator);
}
bool UseSubscriptOperator::diagnose(Expr *root, bool asNote) const {
auto failure = SubscriptMisuseFailure(root, getConstraintSystem(), getLocator());
return failure.diagnose(asNote);
}
UseSubscriptOperator *UseSubscriptOperator::create(ConstraintSystem &cs,
ConstraintLocator *locator) {
return new (cs.getAllocator()) UseSubscriptOperator(cs, locator);
}
bool DefineMemberBasedOnUse::diagnose(Expr *root, bool asNote) const {
auto failure = MissingMemberFailure(root, getConstraintSystem(), BaseType,
Name, getLocator());
return failure.diagnose(asNote);
}
DefineMemberBasedOnUse *
DefineMemberBasedOnUse::create(ConstraintSystem &cs, Type baseType,
DeclName member, ConstraintLocator *locator) {
return new (cs.getAllocator())
DefineMemberBasedOnUse(cs, baseType, member, locator);
}