Skip to content

Commit

Permalink
Merge pull request #932 from swiftwasm/release/5.3
Browse files Browse the repository at this point in the history
[pull] swiftwasm-release/5.3 from release/5.3
  • Loading branch information
pull[bot] authored May 9, 2020
2 parents d8d7602 + f1c0874 commit 8750a0e
Show file tree
Hide file tree
Showing 17 changed files with 189 additions and 65 deletions.
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,8 @@ ERROR(expr_keypath_root_type_mismatch, none,
(Type, Type))
ERROR(expr_swift_keypath_anyobject_root,none,
"the root type of a Swift key path cannot be 'AnyObject'", ())
ERROR(expr_keypath_multiparam_func_conversion, none,
"cannot convert key path into a multi-argument function type %0", (Type))
WARNING(expr_deprecated_writable_keypath,none,
"forming a writable keypath to property %0 that is read-only in this context "
"is deprecated and will be removed in a future release",(DeclName))
Expand Down
3 changes: 1 addition & 2 deletions lib/AST/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2697,7 +2697,7 @@ SourceFile::getConfiguredReferencedNameTracker() const {
}

ArrayRef<OpaqueTypeDecl *> SourceFile::getOpaqueReturnTypeDecls() {
for (auto *vd : UnvalidatedDeclsWithOpaqueReturnTypes) {
for (auto *vd : UnvalidatedDeclsWithOpaqueReturnTypes.takeVector()) {
if (auto opaqueDecl = vd->getOpaqueResultTypeDecl()) {
auto inserted = ValidatedOpaqueReturnTypes.insert(
{opaqueDecl->getOpaqueReturnTypeIdentifier().str(),
Expand All @@ -2708,7 +2708,6 @@ ArrayRef<OpaqueTypeDecl *> SourceFile::getOpaqueReturnTypeDecls() {
}
}

UnvalidatedDeclsWithOpaqueReturnTypes.clear();
return OpaqueReturnTypes;
}

Expand Down
7 changes: 7 additions & 0 deletions lib/Sema/CSDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6266,3 +6266,10 @@ bool KeyPathRootTypeMismatchFailure::diagnoseAsError() {
rootType, baseType);
return true;
}

bool MultiArgFuncKeyPathFailure::diagnoseAsError() {
// Diagnose use a keypath where a function with multiple arguments is expected
emitDiagnostic(diag::expr_keypath_multiparam_func_conversion,
resolveType(functionType));
return true;
}
16 changes: 16 additions & 0 deletions lib/Sema/CSDiagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -2044,6 +2044,22 @@ class KeyPathRootTypeMismatchFailure final : public ContextualFailure {
bool diagnoseAsError() override;
};

/// Diagnose an attempt to use a KeyPath where a multi-argument function is expected
///
/// ```swift
/// [Item].sorted(\Item.name)
/// ```
class MultiArgFuncKeyPathFailure final : public FailureDiagnostic {
Type functionType;
public:
MultiArgFuncKeyPathFailure(const Solution &solution, Type functionType,
ConstraintLocator *locator)
: FailureDiagnostic(solution, locator),
functionType(functionType) {}

bool diagnoseAsError() override;
};

} // end namespace constraints
} // end namespace swift

Expand Down
13 changes: 13 additions & 0 deletions lib/Sema/CSFix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,19 @@ AllowAnyObjectKeyPathRoot::create(ConstraintSystem &cs,
return new (cs.getAllocator()) AllowAnyObjectKeyPathRoot(cs, locator);
}

bool AllowMultiArgFuncKeyPathMismatch::diagnose(const Solution &solution,
bool asNote) const {
MultiArgFuncKeyPathFailure failure(solution, functionType, getLocator());
return failure.diagnose(asNote);
}

AllowMultiArgFuncKeyPathMismatch *
AllowMultiArgFuncKeyPathMismatch::create(ConstraintSystem &cs, Type fnType,
ConstraintLocator *locator) {
return new (cs.getAllocator())
AllowMultiArgFuncKeyPathMismatch(cs, fnType, locator);
}

bool TreatKeyPathSubscriptIndexAsHashable::diagnose(const Solution &solution,
bool asNote) const {
KeyPathSubscriptIndexHashableFailure failure(solution, NonConformingType,
Expand Down
23 changes: 23 additions & 0 deletions lib/Sema/CSFix.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ enum class FixKind : uint8_t {
/// Allow key path root type mismatch when applying a key path that has a
/// root type not convertible to the type of the base instance.
AllowKeyPathRootTypeMismatch,

/// Allow key path to be bound to a function type with more than 1 argument
AllowMultiArgFuncKeyPathMismatch
};

class ConstraintFix {
Expand Down Expand Up @@ -1264,6 +1267,26 @@ class AllowAnyObjectKeyPathRoot final : public ConstraintFix {
ConstraintLocator *locator);
};

class AllowMultiArgFuncKeyPathMismatch final : public ConstraintFix {
Type functionType;

AllowMultiArgFuncKeyPathMismatch(ConstraintSystem &cs, Type fnType,
ConstraintLocator *locator)
: ConstraintFix(cs, FixKind::AllowMultiArgFuncKeyPathMismatch, locator),
functionType(fnType) {}

public:
std::string getName() const override {
return "allow conversion of a keypath type to a multi-argument function";
}

bool diagnose(const Solution &solution, bool asNote = false) const override;

static AllowMultiArgFuncKeyPathMismatch *create(ConstraintSystem &cs,
Type fnType,
ConstraintLocator *locator);
};

class TreatKeyPathSubscriptIndexAsHashable final : public ConstraintFix {
Type NonConformingType;

Expand Down
24 changes: 19 additions & 5 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
//===----------------------------------------------------------------------===//

#include "CSFix.h"
#include "CSDiagnostics.h"
#include "ConstraintSystem.h"
#include "swift/AST/ExistentialLayout.h"
#include "swift/AST/GenericEnvironment.h"
Expand Down Expand Up @@ -7615,10 +7616,10 @@ ConstraintSystem::simplifyKeyPathConstraint(
auto subflags = getDefaultDecompositionOptions(flags);
// The constraint ought to have been anchored on a KeyPathExpr.
auto keyPath = cast<KeyPathExpr>(locator.getBaseLocator()->getAnchor());

keyPathTy = getFixedTypeRecursive(keyPathTy, /*want rvalue*/ true);
bool definitelyFunctionType = false;
bool definitelyKeyPathType = false;
bool resolveAsMultiArgFuncFix = false;

auto tryMatchRootAndValueFromType = [&](Type type,
bool allowPartial = true) -> bool {
Expand All @@ -7643,10 +7644,18 @@ ConstraintSystem::simplifyKeyPathConstraint(
}

if (auto fnTy = type->getAs<FunctionType>()) {
definitelyFunctionType = true;
if (fnTy->getParams().size() != 1) {
if (!shouldAttemptFixes())
return false;

if (fnTy->getParams().size() != 1)
return false;
resolveAsMultiArgFuncFix = true;
auto *fix = AllowMultiArgFuncKeyPathMismatch::create(
*this, fnTy, locator.getBaseLocator());
// Pretend the keypath type got resolved and move on.
return !recordFix(fix);
}

definitelyFunctionType = true;

// Match up the root and value types to the function's param and return
// types. Note that we're using the type of the parameter as referenced
Expand Down Expand Up @@ -7681,6 +7690,10 @@ ConstraintSystem::simplifyKeyPathConstraint(
return SolutionKind::Error;
}

// If we fix this keypath as `AllowMultiArgFuncKeyPathMismatch`, just proceed
if (resolveAsMultiArgFuncFix)
return SolutionKind::Solved;

// See if we resolved overloads for all the components involved.
enum {
ReadOnly,
Expand Down Expand Up @@ -7845,7 +7858,7 @@ ConstraintSystem::simplifyKeyPathConstraint(
} else if (!anyComponentsUnresolved ||
(definitelyKeyPathType && capability == ReadOnly)) {
auto resolvedKPTy =
BoundGenericType::get(kpDecl, nullptr, {rootTy, valueTy});
BoundGenericType::get(kpDecl, nullptr, {rootTy, valueTy});
return matchTypes(keyPathTy, resolvedKPTy, ConstraintKind::Bind, subflags,
loc);
} else {
Expand Down Expand Up @@ -9562,6 +9575,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
case FixKind::AllowClosureParameterDestructuring:
case FixKind::AllowInaccessibleMember:
case FixKind::AllowAnyObjectKeyPathRoot:
case FixKind::AllowMultiArgFuncKeyPathMismatch:
case FixKind::TreatKeyPathSubscriptIndexAsHashable:
case FixKind::AllowInvalidRefInKeyPath:
case FixKind::DefaultGenericArgument:
Expand Down
6 changes: 6 additions & 0 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3508,6 +3508,12 @@ void constraints::simplifyLocator(Expr *&anchor,
continue;
}

case ConstraintLocator::KeyPathDynamicMember: {
// Key path dynamic member lookup should be completely transparent.
path = path.slice(1);
continue;
}

default:
// FIXME: Lots of other cases to handle.
break;
Expand Down
60 changes: 29 additions & 31 deletions lib/SymbolGraphGen/DeclarationFragmentPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,38 +148,36 @@ void DeclarationFragmentPrinter::printText(StringRef Text) {
Spelling.append(Text);
}

void DeclarationFragmentPrinter::printAbridgedType(const GenericTypeDecl *TD) {
// Subheadings for types are abridged, omitting generics and inheritance.
openFragment(DeclarationFragmentPrinter::FragmentKind::Keyword);
switch (TD->getKind()) {
case DeclKind::Struct:
printText(getTokenText(tok::kw_struct));
break;
case DeclKind::Enum:
printText(getTokenText(tok::kw_enum));
break;
case DeclKind::Protocol:
printText(getTokenText(tok::kw_protocol));
break;
case DeclKind::Class:
printText(getTokenText(tok::kw_class));
break;
case DeclKind::TypeAlias:
printText(getTokenText(tok::kw_typealias));
break;
case DeclKind::OpaqueType:
llvm_unreachable("OpaqueType should not be in symbol graphs!");
default:
llvm_unreachable("GenericTypeDecl kind not handled in DeclarationFragmentPrinter!");
void DeclarationFragmentPrinter::printAbridgedType(const GenericTypeDecl *TD,
bool PrintKeyword) {
if (PrintKeyword) {
openFragment(DeclarationFragmentPrinter::FragmentKind::Keyword);
switch (TD->getKind()) {
case DeclKind::Struct:
printText(getTokenText(tok::kw_struct));
break;
case DeclKind::Enum:
printText(getTokenText(tok::kw_enum));
break;
case DeclKind::Protocol:
printText(getTokenText(tok::kw_protocol));
break;
case DeclKind::Class:
printText(getTokenText(tok::kw_class));
break;
case DeclKind::TypeAlias:
printText(getTokenText(tok::kw_typealias));
break;
case DeclKind::OpaqueType:
llvm_unreachable("OpaqueType should not be in symbol graphs!");
default:
llvm_unreachable("GenericTypeDecl kind not handled in DeclarationFragmentPrinter!");
}

openFragment(DeclarationFragmentPrinter::FragmentKind::Text);
printText(" ");
}

openFragment(DeclarationFragmentPrinter::FragmentKind::Text);
printText(" ");

openFragment(DeclarationFragmentPrinter::FragmentKind::TypeIdentifier);
openFragment(DeclarationFragmentPrinter::FragmentKind::Identifier);
printText(TD->getNameStr());

USR.clear();
llvm::raw_svector_ostream USROS(USR);
ide::printDeclUSR(TD, USROS);
}
5 changes: 4 additions & 1 deletion lib/SymbolGraphGen/DeclarationFragmentPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ class DeclarationFragmentPrinter : public ASTPrinter {
///
/// Subheadings for types don't include the complete declaration line
/// including generics and inheritance.
void printAbridgedType(const GenericTypeDecl *TD);
///
/// \param TD The type declaration to print.
/// \param PrintKeyword Print the corresponding keyword introducer if `true`.
void printAbridgedType(const GenericTypeDecl *TD, bool PrintKeyword);

void printDeclLoc(const Decl *D) override;

Expand Down
17 changes: 8 additions & 9 deletions lib/SymbolGraphGen/SymbolGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,15 +522,14 @@ SymbolGraph::serializeNavigatorDeclarationFragments(StringRef Key,
DeclarationFragmentPrinter Printer(OS, Key);

if (const auto *TD = dyn_cast<GenericTypeDecl>(S.getSymbolDecl())) {
Printer.printTypeRef(TD->getInterfaceType(), TD, TD->getName(),
PrintNameContext::Normal);
return;
}
auto Options = getSubHeadingDeclarationFragmentsPrintOptions();
if (S.getSynthesizedBaseType()) {
Options.setBaseType(S.getSynthesizedBaseType());
Printer.printAbridgedType(TD, /*PrintKeyword=*/false);
} else {
auto Options = getSubHeadingDeclarationFragmentsPrintOptions();
if (S.getSynthesizedBaseType()) {
Options.setBaseType(S.getSynthesizedBaseType());
}
S.getSymbolDecl()->print(Printer, Options);
}
S.getSymbolDecl()->print(Printer, Options);
}

void
Expand All @@ -540,7 +539,7 @@ SymbolGraph::serializeSubheadingDeclarationFragments(StringRef Key,
DeclarationFragmentPrinter Printer(OS, Key);

if (const auto *TD = dyn_cast<GenericTypeDecl>(S.getSymbolDecl())) {
Printer.printAbridgedType(TD);
Printer.printAbridgedType(TD, /*PrintKeyword=*/true);
} else {
auto Options = getSubHeadingDeclarationFragmentsPrintOptions();
if (S.getSynthesizedBaseType()) {
Expand Down
21 changes: 21 additions & 0 deletions test/Constraints/diagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1483,3 +1483,24 @@ func rdar62428353<T>(_ t: inout T) {
let v = t // expected-note {{change 'let' to 'var' to make it mutable}} {{3-6=var}}
rdar62428353(v) // expected-error {{cannot pass immutable value as inout argument: 'v' is a 'let' constant}}
}

func rdar62989214() {
struct Flag {
var isTrue: Bool
}

@propertyWrapper @dynamicMemberLookup
struct Wrapper<Value> {
var wrappedValue: Value

subscript<Subject>(
dynamicMember keyPath: WritableKeyPath<Value, Subject>
) -> Wrapper<Subject> {
get { fatalError() }
}
}

func test(arr: Wrapper<[Flag]>, flag: Flag) {
arr[flag].isTrue // expected-error {{cannot convert value of type 'Flag' to expected argument type 'Int'}}
}
}
10 changes: 10 additions & 0 deletions test/Constraints/keypath_closure_conv_mismatch.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %target-swift-frontend -typecheck -verify -primary-file %s

// rdar://problem/57930643
struct School {
var name: String
}
func testKeyPathClosureLiteralError() -> [School] {
let slist = [School(name:"AHS"), School(name:"BHS")]
return slist.sorted(by: \School.name) // expected-error {{cannot convert key path into a multi-argument function type '(School, School) throws -> Bool'}}
}
9 changes: 9 additions & 0 deletions test/Constraints/keypath_closure_conv_mismatch_generic.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// RUN: %target-swift-frontend -typecheck -verify -primary-file %s

// rdar://problem/57930643
struct School {
var name: String
}
func test<A, B>(_: (A, B) -> Bool) {} // expected-note {{in call to function 'test'}}
test(\School.name) // expected-error {{generic parameter 'A' could not be inferred}} // expected-error {{generic parameter 'B' could not be inferred}} // expected-error {{cannot convert key path into a multi-argument function type '(A, B) -> Bool'}}

10 changes: 10 additions & 0 deletions test/Constraints/keypath_closure_conv_mismatch_norettype.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// RUN: %target-swift-frontend -typecheck -verify -primary-file %s

// rdar://problem/57930643
struct School {
var name: String
}
func testKeyPathClosureLiteralError() {
let slist = [School(name:"AHS"), School(name:"BHS")]
_ = slist.sorted(by: \School.name) // expected-error {{cannot convert key path into a multi-argument function type '(School, School) throws -> Bool'}}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ public struct MyStruct<S> { public var x: S
// MYSTRUCT-NEXT: "title": "MyStruct",
// MYSTRUCT-NEXT: "navigator": [
// MYSTRUCT-NEXT: {
// MYSTRUCT-NEXT: "kind": "typeIdentifier"
// MYSTRUCT-NEXT: "kind": "identifier"
// MYSTRUCT-NEXT: "spelling": "MyStruct"
// MYSTRUCT-NEXT: "preciseIdentifier": "s:9Navigator8MyStructV"
// MYSTRUCT-NEXT: }
// MYSTRUCT-NEXT: ]

Expand Down
Loading

0 comments on commit 8750a0e

Please sign in to comment.