Skip to content

A handful of independent changes from #27695 #27696

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3220,6 +3220,14 @@ static inline bool isRawPointerKind(PointerTypeKind PTK) {
llvm_unreachable("Unhandled PointerTypeKind in switch.");
}

// Kinds of buffer pointer types.
enum BufferPointerTypeKind : unsigned {
BPTK_UnsafeMutableRawBufferPointer,
BPTK_UnsafeRawBufferPointer,
BPTK_UnsafeMutableBufferPointer,
BPTK_UnsafeBufferPointer,
};

enum KeyPathTypeKind : unsigned char {
KPTK_AnyKeyPath,
KPTK_PartialKeyPath,
Expand Down
5 changes: 5 additions & 0 deletions include/swift/AST/KnownStdlibTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ KNOWN_STDLIB_TYPE_DECL(UnsafePointer, NominalTypeDecl, 1)
KNOWN_STDLIB_TYPE_DECL(OpaquePointer, NominalTypeDecl, 0)
KNOWN_STDLIB_TYPE_DECL(AutoreleasingUnsafeMutablePointer, NominalTypeDecl, 1)

KNOWN_STDLIB_TYPE_DECL(UnsafeBufferPointer, NominalTypeDecl, 1)
KNOWN_STDLIB_TYPE_DECL(UnsafeMutableBufferPointer, NominalTypeDecl, 1)
KNOWN_STDLIB_TYPE_DECL(UnsafeRawBufferPointer, NominalTypeDecl, 0)
KNOWN_STDLIB_TYPE_DECL(UnsafeMutableRawBufferPointer, NominalTypeDecl, 0)

KNOWN_STDLIB_TYPE_DECL(Unmanaged, NominalTypeDecl, 1)

KNOWN_STDLIB_TYPE_DECL(Never, NominalTypeDecl, 0)
Expand Down
12 changes: 12 additions & 0 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ enum class AllocationArena;
class ArchetypeType;
class AssociatedTypeDecl;
class ASTContext;
enum BufferPointerTypeKind : unsigned;
class ClassDecl;
class DependentMemberType;
class GenericTypeParamDecl;
Expand Down Expand Up @@ -713,6 +714,14 @@ class alignas(1 << TypeAlignInBits) TypeBase {
/// current type.
Type wrapInPointer(PointerTypeKind kind);

/// Determines the element type of a known Unsafe[Mutable][Raw]BufferPointer
/// variant, or returns null if the type is not a buffer pointer.
Type getAnyBufferPointerElementType(BufferPointerTypeKind &BPTK);
Type getAnyBufferPointerElementType() {
BufferPointerTypeKind Ignore;
return getAnyBufferPointerElementType(Ignore);
}

/// Determine whether the given type is "specialized", meaning that
/// it involves generic types for which generic arguments have been provided.
/// For example, the types Vector<Int> and Vector<Int>.Element are both
Expand Down Expand Up @@ -1058,6 +1067,9 @@ class alignas(1 << TypeAlignInBits) TypeBase {
// otherwise, return the null type.
Type getSwiftNewtypeUnderlyingType();

/// Return the type T after looking through at most one optional type.
Type lookThroughSingleOptionalType();

/// Return the type T after looking through all of the optional
/// types.
Type lookThroughAllOptionalTypes();
Expand Down
4 changes: 4 additions & 0 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1384,6 +1384,10 @@ bool ASTContext::hasPointerArgumentIntrinsics() const {
&& getUnsafeMutablePointerDecl()
&& getUnsafePointerDecl()
&& (!LangOpts.EnableObjCInterop || getAutoreleasingUnsafeMutablePointerDecl())
&& getUnsafeBufferPointerDecl()
&& getUnsafeMutableBufferPointerDecl()
&& getUnsafeRawBufferPointerDecl()
&& getUnsafeMutableRawBufferPointerDecl()
&& getConvertPointerToPointerArgument()
&& getConvertMutableArrayToPointerArgument()
&& getConvertConstArrayToPointerArgument()
Expand Down
31 changes: 31 additions & 0 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,37 @@ Type TypeBase::wrapInPointer(PointerTypeKind kind) {
return BoundGenericType::get(pointerDecl, /*parent*/nullptr, Type(this));
}

Type TypeBase::getAnyBufferPointerElementType(BufferPointerTypeKind &BPTK) {
auto &C = getASTContext();
if (auto nominalTy = getAs<NominalType>()) {
if (nominalTy->getDecl() == C.getUnsafeMutableRawBufferPointerDecl()) {
BPTK = BPTK_UnsafeMutableRawBufferPointer;
} else if (nominalTy->getDecl() == C.getUnsafeRawBufferPointerDecl()) {
BPTK = BPTK_UnsafeRawBufferPointer;
} else {
return Type();
}
return C.TheEmptyTupleType;
}
if (auto boundTy = getAs<BoundGenericType>()) {
if (boundTy->getDecl() == C.getUnsafeMutableBufferPointerDecl()) {
BPTK = BPTK_UnsafeMutableBufferPointer;
} else if (boundTy->getDecl() == C.getUnsafeBufferPointerDecl()) {
BPTK = BPTK_UnsafeBufferPointer;
} else {
return Type();
}
return boundTy->getGenericArgs()[0];
}
return Type();
}

Type TypeBase::lookThroughSingleOptionalType() {
Type type(this);
if (auto objType = type->getOptionalObjectType())
type = objType;
return type;
}

Type TypeBase::lookThroughAllOptionalTypes() {
Type type(this);
Expand Down
9 changes: 5 additions & 4 deletions lib/Sema/CSFix.h
Original file line number Diff line number Diff line change
Expand Up @@ -487,8 +487,8 @@ class ContextualMismatch : public ConstraintFix {
: ConstraintFix(cs, FixKind::ContextualMismatch, locator), LHS(lhs),
RHS(rhs) {}
ContextualMismatch(ConstraintSystem &cs, FixKind kind, Type lhs, Type rhs,
ConstraintLocator *locator)
: ConstraintFix(cs, kind, locator), LHS(lhs), RHS(rhs) {}
ConstraintLocator *locator, bool warning = false)
: ConstraintFix(cs, kind, locator, warning), LHS(lhs), RHS(rhs) {}

public:
std::string getName() const override { return "fix contextual mismatch"; }
Expand Down Expand Up @@ -1347,8 +1347,9 @@ class AllowArgumentMismatch : public ContextualMismatch {
paramType, locator) {}

AllowArgumentMismatch(ConstraintSystem &cs, FixKind kind, Type argType,
Type paramType, ConstraintLocator *locator)
: ContextualMismatch(cs, kind, argType, paramType, locator) {}
Type paramType, ConstraintLocator *locator,
bool warning = false)
: ContextualMismatch(cs, kind, argType, paramType, locator, warning) {}

public:
std::string getName() const override {
Expand Down
46 changes: 36 additions & 10 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3718,18 +3718,22 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
if (!isAutoClosureArgument) {
auto inoutBaseType = inoutType1->getInOutObjectType();

Type simplifiedInoutBaseType = getFixedTypeRecursive(
inoutBaseType, /*wantRValue=*/true);
auto baseIsArray = isArrayType(
getFixedTypeRecursive(inoutBaseType, /*wantRValue=*/true));

// FIXME: If the base is still a type variable, we can't tell
// what to do here. Might have to try \c ArrayToPointer and make
// it more robust.
if (isArrayType(simplifiedInoutBaseType)) {
if (baseIsArray)
conversionsOrFixes.push_back(
ConversionRestrictionKind::ArrayToPointer);
}
conversionsOrFixes.push_back(
ConversionRestrictionKind::InoutToPointer);

// Only try an inout-to-pointer conversion if we know it's not
// an array being converted to a raw pointer type. Such
// conversions can only use array-to-pointer.
if (!baseIsArray || !isRawPointerKind(pointerKind))
conversionsOrFixes.push_back(
ConversionRestrictionKind::InoutToPointer);
}
}

Expand Down Expand Up @@ -7241,10 +7245,8 @@ ConstraintSystem::simplifyDynamicCallableApplicableFnConstraint(
}

static Type getBaseTypeForPointer(ConstraintSystem &cs, TypeBase *type) {
if (Type unwrapped = type->getOptionalObjectType())
type = unwrapped.getPointer();

auto pointeeTy = type->getAnyPointerElementType();
auto pointeeTy = type->lookThroughSingleOptionalType()
->getAnyPointerElementType();
assert(pointeeTy);
return pointeeTy;
}
Expand Down Expand Up @@ -8155,6 +8157,30 @@ Type ConstraintSystem::addJoinConstraint(
return resultTy;
}

void ConstraintSystem::addFixConstraint(ConstraintFix *fix, ConstraintKind kind,
Type first, Type second,
ConstraintLocatorBuilder locator,
bool isFavored) {
TypeMatchOptions subflags = TMF_GenerateConstraints;
switch (simplifyFixConstraint(fix, first, second, kind, subflags, locator)) {
case SolutionKind::Error:
// Add a failing constraint, if needed.
if (shouldAddNewFailingConstraint()) {
auto c = Constraint::createFixed(*this, kind, fix, first, second,
getConstraintLocator(locator));
if (isFavored) c->setFavored();
addNewFailingConstraint(c);
}
return;

case SolutionKind::Unsolved:
llvm_unreachable("should have generated constraints");

case SolutionKind::Solved:
return;
}
}

void ConstraintSystem::addExplicitConversionConstraint(
Type fromType, Type toType,
bool allowFixes,
Expand Down
48 changes: 48 additions & 0 deletions lib/Sema/ConstraintLocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,54 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, Expr *anchor,
}
}

unsigned LocatorPathElt::getNewSummaryFlags() const {
switch (getKind()) {
case ConstraintLocator::ApplyArgument:
case ConstraintLocator::ApplyFunction:
case ConstraintLocator::ApplyArgToParam:
case ConstraintLocator::SequenceElementType:
case ConstraintLocator::ClosureResult:
case ConstraintLocator::ConstructorMember:
case ConstraintLocator::InstanceType:
case ConstraintLocator::AutoclosureResult:
case ConstraintLocator::OptionalPayload:
case ConstraintLocator::Member:
case ConstraintLocator::MemberRefBase:
case ConstraintLocator::UnresolvedMember:
case ConstraintLocator::ParentType:
case ConstraintLocator::ExistentialSuperclassType:
case ConstraintLocator::LValueConversion:
case ConstraintLocator::RValueAdjustment:
case ConstraintLocator::SubscriptMember:
case ConstraintLocator::OpenedGeneric:
case ConstraintLocator::GenericParameter:
case ConstraintLocator::GenericArgument:
case ConstraintLocator::NamedTupleElement:
case ConstraintLocator::TupleElement:
case ConstraintLocator::ProtocolRequirement:
case ConstraintLocator::Witness:
case ConstraintLocator::KeyPathComponent:
case ConstraintLocator::ConditionalRequirement:
case ConstraintLocator::TypeParameterRequirement:
case ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice:
case ConstraintLocator::DynamicLookupResult:
case ConstraintLocator::ContextualType:
case ConstraintLocator::SynthesizedArgument:
case ConstraintLocator::KeyPathDynamicMember:
case ConstraintLocator::KeyPathType:
case ConstraintLocator::KeyPathRoot:
case ConstraintLocator::KeyPathValue:
case ConstraintLocator::KeyPathComponentResult:
return 0;

case ConstraintLocator::FunctionArgument:
case ConstraintLocator::FunctionResult:
return IsFunctionConversion;
}

llvm_unreachable("Unhandled PathElementKind in switch.");
}

bool LocatorPathElt::isResultOfSingleExprFunction() const {
if (auto elt = getAs<ContextualType>())
return elt->isForSingleExprFunction();
Expand Down
52 changes: 1 addition & 51 deletions lib/Sema/ConstraintLocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,54 +124,6 @@ class ConstraintLocator : public llvm::FoldingSetNode {
IsFunctionConversion = 0x1,
};

static unsigned getSummaryFlagsForPathElement(PathElementKind kind) {
switch (kind) {
case ApplyArgument:
case ApplyFunction:
case ApplyArgToParam:
case SequenceElementType:
case ClosureResult:
case ConstructorMember:
case InstanceType:
case AutoclosureResult:
case OptionalPayload:
case Member:
case MemberRefBase:
case UnresolvedMember:
case ParentType:
case ExistentialSuperclassType:
case LValueConversion:
case RValueAdjustment:
case SubscriptMember:
case OpenedGeneric:
case GenericParameter:
case GenericArgument:
case NamedTupleElement:
case TupleElement:
case ProtocolRequirement:
case Witness:
case KeyPathComponent:
case ConditionalRequirement:
case TypeParameterRequirement:
case ImplicitlyUnwrappedDisjunctionChoice:
case DynamicLookupResult:
case ContextualType:
case SynthesizedArgument:
case KeyPathDynamicMember:
case KeyPathType:
case KeyPathRoot:
case KeyPathValue:
case KeyPathComponentResult:
return 0;

case FunctionArgument:
case FunctionResult:
return IsFunctionConversion;
}

llvm_unreachable("Unhandled PathElementKind in switch.");
}

/// One element in the path of a locator, which can include both
/// a kind (PathElementKind) and a value used to describe specific
/// kinds further (e.g., the position of a tuple element).
Expand Down Expand Up @@ -329,9 +281,7 @@ class ConstraintLocator : public llvm::FoldingSetNode {
bool is() const { return isa<T>(this); }

/// Return the summary flags for this particular element.
unsigned getNewSummaryFlags() const {
return getSummaryFlagsForPathElement(getKind());
}
unsigned getNewSummaryFlags() const;

bool isConditionalRequirement() const {
return getKind() == PathElementKind::ConditionalRequirement;
Expand Down
6 changes: 6 additions & 0 deletions lib/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -2151,6 +2151,12 @@ class ConstraintSystem {
Type addJoinConstraint(ConstraintLocator *locator,
ArrayRef<std::pair<Type, ConstraintLocator *>> inputs);

/// Add a constraint to the constraint system with an associated fix.
void addFixConstraint(ConstraintFix *fix, ConstraintKind kind,
Type first, Type second,
ConstraintLocatorBuilder locator,
bool isFavored = false);

/// Add a key path application constraint to the constraint system.
void addKeyPathApplicationConstraint(Type keypath, Type root, Type value,
ConstraintLocatorBuilder locator,
Expand Down