Merge pull request #10486 from rjmccall/nested-access-tracking-4.0
[4.0] Fix some embarrassing list-management bugs with the exclusivity runtime
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 752701c..179e84b 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -1422,8 +1422,6 @@
// in the metatype.
assert(!declRef.getDecl()->getDeclContext()->isTypeContext()
&& "c pointers to static methods not implemented");
- assert(declRef.getSubstitutions().empty()
- && "c pointers to generics not implemented");
loc = declRef.getDecl();
};
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 3ae3461..2c64498 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -2158,6 +2158,11 @@
Optional<std::function<bool(ArrayRef<OverloadChoice>)>> callback = None,
bool includeInaccessibleMembers = true);
+ bool diagnoseTrailingClosureErrors(ApplyExpr *expr);
+
+ bool diagnoseClosureExpr(ClosureExpr *closureExpr, Type contextualType,
+ std::function<bool(Type, Type)> resultTypeProcessor);
+
bool visitExpr(Expr *E);
bool visitIdentityExpr(IdentityExpr *E);
bool visitTryExpr(TryExpr *E);
@@ -5486,7 +5491,7 @@
// It could be that the argument doesn't conform to an archetype.
if (CCI.diagnoseGenericParameterErrors(badArgExpr))
return true;
-
+
// Re-type-check the argument with the expected type of the candidate set.
// This should produce a specific and tailored diagnostic saying that the
// type mismatches with expectations.
@@ -5945,10 +5950,235 @@
return true;
}
+static bool diagnoseClosureExplicitParameterMismatch(ConstraintSystem *const CS,
+ SourceLoc loc,
+ Type paramType,
+ Type argType) {
+ SmallVector<Identifier, 4> argLabels;
+ gatherArgumentLabels(argType, argLabels);
+
+ auto params = decomposeParamType(paramType, nullptr, 0);
+ auto args = decomposeArgType(argType, argLabels);
+
+ // We are not trying to diagnose structural problems with top-level
+ // arguments here.
+ if (params.size() != args.size())
+ return false;
+
+ for (unsigned i = 0, n = params.size(); i != n; ++i) {
+ auto ¶mType = params[i].Ty;
+ auto &argType = args[i].Ty;
+
+ if (auto paramFnType = paramType->getAs<AnyFunctionType>()) {
+ if (auto argFnType = argType->getAs<AnyFunctionType>())
+ return diagnoseClosureExplicitParameterMismatch(
+ CS, loc, paramFnType->getInput(), argFnType->getInput());
+ }
+
+ if (!paramType || !argType || isUnresolvedOrTypeVarType(paramType) ||
+ isUnresolvedOrTypeVarType(argType))
+ continue;
+
+ if (!CS->TC.isConvertibleTo(argType, paramType, CS->DC)) {
+ CS->TC.diagnose(loc, diag::types_not_convertible, false, paramType,
+ argType);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool FailureDiagnosis::diagnoseTrailingClosureErrors(ApplyExpr *callExpr) {
+ if (!callExpr->hasTrailingClosure())
+ return false;
+
+ auto *fnExpr = callExpr->getFn();
+ auto *argExpr = callExpr->getArg();
+
+ ClosureExpr *closureExpr = nullptr;
+ if (auto *PE = dyn_cast<ParenExpr>(argExpr)) {
+ closureExpr = dyn_cast<ClosureExpr>(PE->getSubExpr());
+ } else {
+ return false;
+ }
+
+ if (!closureExpr)
+ return false;
+
+ class CallResultListener : public ExprTypeCheckListener {
+ Type expectedResultType;
+
+ public:
+ explicit CallResultListener(Type resultType)
+ : expectedResultType(resultType) {}
+
+ bool builtConstraints(ConstraintSystem &cs, Expr *expr) override {
+ if (!expectedResultType)
+ return false;
+
+ auto resultType = cs.getType(expr);
+ auto *locator = cs.getConstraintLocator(expr);
+
+ // Since we know that this is trailing closure, format of the
+ // type could be like this - ((Input) -> Result) -> ClosureResult
+ // which we can leverage to create specific conversion for
+ // result type of the call itself, this might help us gain
+ // some valuable contextual information.
+ if (auto *fnType = resultType->getAs<AnyFunctionType>()) {
+ cs.addConstraint(ConstraintKind::Conversion, fnType->getResult(),
+ expectedResultType, locator);
+ } else if (auto *typeVar = resultType->getAs<TypeVariableType>()) {
+ auto tv =
+ cs.createTypeVariable(cs.getConstraintLocator(expr),
+ TVO_CanBindToLValue | TVO_CanBindToInOut |
+ TVO_PrefersSubtypeBinding);
+
+ auto extInfo = FunctionType::ExtInfo().withThrows();
+ auto fTy = FunctionType::get(ParenType::get(cs.getASTContext(), tv),
+ expectedResultType, extInfo);
+
+ // Add a conversion constraint between the types.
+ cs.addConstraint(ConstraintKind::Conversion, typeVar, fTy, locator,
+ /*isFavored*/ true);
+ }
+
+ return false;
+ }
+ };
+
+ SmallVector<Type, 4> possibleTypes;
+ auto currentType = CS->getType(fnExpr);
+
+ // If current type has type variables or unresolved types
+ // let's try to re-typecheck it to see if we can get some
+ // more information about what is going on.
+ if (currentType->hasTypeVariable() || currentType->hasUnresolvedType()) {
+ auto contextualType = CS->getContextualType();
+ CallResultListener listener(contextualType);
+
+ Type originalType = CS->getType(fnExpr);
+ CS->TC.getPossibleTypesOfExpressionWithoutApplying(
+ fnExpr, CS->DC, possibleTypes, FreeTypeVariableBinding::UnresolvedType,
+ &listener);
+
+ // Looks like there is there a contextual mismatch
+ // related to function type, let's try to diagnose it.
+ if (possibleTypes.empty() && contextualType &&
+ !contextualType->hasUnresolvedType())
+ return diagnoseContextualConversionError();
+
+ auto currentType = fnExpr->getType();
+ if (currentType && currentType->is<ErrorType>())
+ fnExpr->setType(originalType);
+ } else {
+ possibleTypes.push_back(currentType);
+ }
+
+
+ for (auto type : possibleTypes) {
+ auto *fnType = type->getAs<AnyFunctionType>();
+ if (!fnType)
+ continue;
+
+ auto paramType = fnType->getInput();
+ switch (paramType->getKind()) {
+ case TypeKind::Tuple: {
+ auto tuple = paramType->getAs<TupleType>();
+ if (tuple->getNumElements() != 1)
+ continue;
+
+ paramType = tuple->getElement(0).getType();
+ break;
+ }
+
+ case TypeKind::Paren:
+ paramType = paramType->getWithoutParens();
+ break;
+
+ default:
+ return false;
+ }
+
+ if (auto fnType = paramType->getAs<AnyFunctionType>()) {
+ if (auto *params = closureExpr->getParameters()) {
+ auto closureParamType = params->getType(CS->getASTContext());
+ if (diagnoseClosureExplicitParameterMismatch(CS, params->getStartLoc(),
+ closureParamType,
+ fnType->getInput()))
+ return true;
+ }
+ }
+
+ auto processor = [&](Type resultType, Type expectedResultType) -> bool {
+ if (resultType && expectedResultType) {
+ if (!resultType->isEqual(expectedResultType)) {
+ CS->TC.diagnose(closureExpr->getEndLoc(),
+ diag::cannot_convert_closure_result, resultType,
+ expectedResultType);
+ return true;
+ }
+
+ // Looks like both actual and expected result types match,
+ // there is nothing we can diagnose in this case.
+ return false;
+ }
+
+ // If we got a result type, let's re-typecheck the function using it,
+ // maybe we can find a problem where contextually we expect one type
+ // but trailing closure produces completely different one.
+ auto fnType = paramType->getAs<AnyFunctionType>();
+ if (!fnType)
+ return false;
+
+ auto expectedArgType = FunctionType::get(fnType->getInput(), resultType,
+ fnType->getExtInfo());
+
+ auto expectedType =
+ FunctionType::get(expectedArgType, CS->getContextualType());
+
+ class ClosureCalleeListener : public ExprTypeCheckListener {
+ Type contextualType;
+
+ public:
+ explicit ClosureCalleeListener(Type contextualType)
+ : contextualType(contextualType) {}
+
+ bool builtConstraints(ConstraintSystem &cs, Expr *expr) override {
+ cs.addConstraint(ConstraintKind::Conversion, cs.getType(expr),
+ contextualType, cs.getConstraintLocator(expr),
+ /*isFavored*/ true);
+ return false;
+ }
+ };
+
+ ClosureCalleeListener listener(expectedType);
+ return !typeCheckChildIndependently(callExpr->getFn(), Type(),
+ CTP_CalleeResult, TCC_ForceRecheck,
+ &listener);
+ };
+
+ // Let's see if there are any structural problems with closure itself.
+ if (diagnoseClosureExpr(closureExpr, paramType, processor))
+ return true;
+ }
+
+ return false;
+}
+
bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
- // Type check the function subexpression to resolve a type for it if possible.
+ // If this call involves trailing closure as an argument,
+ // let's treat it specially, because re-typecheck of the
+ // either function or arguments might results in diagnosing
+ // of the unrelated problems due to luck of context.
+ if (diagnoseTrailingClosureErrors(callExpr))
+ return true;
+
+ // Type check the function subexpression to resolve a type for it if
+ // possible.
auto fnExpr = typeCheckChildIndependently(callExpr->getFn());
- if (!fnExpr) return true;
+ if (!fnExpr)
+ return true;
SWIFT_DEFER {
if (!fnExpr) return;
@@ -6107,6 +6337,23 @@
}
}
+ // If there is a failing constraint associated with current constraint
+ // system which points to the argument/parameter mismatch, let's use
+ // that information while re-typechecking argument expression, this
+ // makes it a lot easier to determine contextual mismatch.
+ if (CS->failedConstraint && !hasTrailingClosure) {
+ auto *constraint = CS->failedConstraint;
+ if (constraint->getKind() == ConstraintKind::ArgumentTupleConversion) {
+ if (auto *locator = constraint->getLocator()) {
+ if (locator->getAnchor() == callExpr) {
+ argType = constraint->getSecondType();
+ if (auto *typeVar = argType->getAs<TypeVariableType>())
+ argType = CS->getFixedType(typeVar);
+ }
+ }
+ }
+ }
+
// Get the expression result of type checking the arguments to the call
// independently, so we have some idea of what we're working with.
//
@@ -6585,9 +6832,36 @@
return false;
}
+static bool isInvalidClosureResultType(Type resultType) {
+ return !resultType || resultType->hasUnresolvedType() ||
+ resultType->hasTypeVariable() || resultType->hasArchetype();
+}
bool FailureDiagnosis::visitClosureExpr(ClosureExpr *CE) {
- auto contextualType = CS->getContextualType();
+ return diagnoseClosureExpr(
+ CE, CS->getContextualType(),
+ [&](Type resultType, Type expectedResultType) -> bool {
+ if (isInvalidClosureResultType(expectedResultType))
+ return false;
+
+ // Following situations are possible:
+ // * No result type - possible structurable problem in the body;
+ // * Function result type - possible use of function without calling it,
+ // which is properly diagnosed by actual type-check call.
+ if (resultType && !resultType->getRValueType()->is<AnyFunctionType>()) {
+ if (!resultType->isEqual(expectedResultType)) {
+ diagnose(CE->getEndLoc(), diag::cannot_convert_closure_result,
+ resultType, expectedResultType);
+ return true;
+ }
+ }
+ return false;
+ });
+}
+
+bool FailureDiagnosis::diagnoseClosureExpr(
+ ClosureExpr *CE, Type contextualType,
+ std::function<bool(Type, Type)> resultTypeProcessor) {
// Look through IUO because it doesn't influence
// neither parameter nor return type diagnostics itself,
// but if we have function type inside, that might
@@ -6748,7 +7022,7 @@
// - if the there is a result type associated with the closure;
// - and it's not a void type;
// - and it hasn't been explicitly written.
- auto resultType = CE->getResultType();
+ auto resultType = fnType->getResult();
auto hasResult = [](Type resultType) -> bool {
return resultType && !resultType->isVoid();
};
@@ -6868,6 +7142,9 @@
if (!CE->hasSingleExpressionBody())
return false;
+ if (isInvalidClosureResultType(expectedResultType))
+ expectedResultType = Type();
+
// When we're type checking a single-expression closure, we need to reset the
// DeclContext to this closure for the recursive type checking. Otherwise,
// if there is a closure in the subexpression, we can violate invariants.
@@ -6893,19 +7170,8 @@
auto type = CS->TC.getTypeOfExpressionWithoutApplying(
closure, CS->DC, decl, FreeTypeVariableBinding::Disallow);
- Type resultType = type.hasValue() ? *type : Type();
-
- // Following situations are possible:
- // * No result type - possible structurable problem in the body;
- // * Function result type - possible use of function without calling it,
- // which is properly diagnosed by actual type-check call.
- if (resultType && !resultType->getRValueType()->is<AnyFunctionType>()) {
- if (!resultType->isEqual(expectedResultType)) {
- diagnose(closure->getEndLoc(), diag::cannot_convert_closure_result,
- resultType, expectedResultType);
- return true;
- }
- }
+ if (type && resultTypeProcessor(*type, expectedResultType))
+ return true;
}
// If the closure had an expected result type, use it.
@@ -6916,9 +7182,14 @@
// let's run proper type-check with expected type and try to verify it.
auto CTP = expectedResultType ? CTP_ClosureResult : CTP_Unused;
- if (!typeCheckChildIndependently(CE->getSingleExpressionBody(),
- expectedResultType, CTP, TCCOptions(),
- nullptr, false))
+ auto *bodyExpr = typeCheckChildIndependently(CE->getSingleExpressionBody(),
+ expectedResultType, CTP,
+ TCCOptions(), nullptr, false);
+
+ if (!bodyExpr)
+ return true;
+
+ if (resultTypeProcessor(bodyExpr->getType(), expectedResultType))
return true;
}
@@ -6930,12 +7201,18 @@
if (!fnType || fnType->isEqual(CE->getType()))
return false;
+ auto contextualResultType = fnType->getResult();
+ // If the result type was unknown, it doesn't really make
+ // sense to diagnose from expected to unknown here.
+ if (isInvalidClosureResultType(contextualResultType))
+ return false;
+
// If the closure had an explicitly written return type incompatible with
// the contextual type, diagnose that.
if (CE->hasExplicitResultType() &&
CE->getExplicitResultTypeLoc().getTypeRepr()) {
auto explicitResultTy = CE->getExplicitResultTypeLoc().getType();
- if (fnType && !explicitResultTy->isEqual(fnType->getResult())) {
+ if (fnType && !explicitResultTy->isEqual(contextualResultType)) {
auto repr = CE->getExplicitResultTypeLoc().getTypeRepr();
diagnose(repr->getStartLoc(), diag::incorrect_explicit_closure_result,
explicitResultTy, fnType->getResult())
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index 74f7636..1c35968 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -2069,7 +2069,8 @@
// If there is more than one viable system, attempt to pick the best
// solution.
auto size = solutions.size();
- if (size > 1) {
+ if (size > 1 &&
+ !Options.contains(ConstraintSystemFlags::ReturnAllDiscoveredSolutions)) {
if (auto best = findBestSolution(solutions, /*minimize=*/false)) {
if (*best != 0)
solutions[0] = std::move(solutions[*best]);
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 442820f..8e71583 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -754,6 +754,10 @@
/// Set if the client prefers fixits to be in the form of force unwrapping
/// or optional chaining to return an optional.
PreferForceUnwrapToOptional = 0x02,
+
+ /// If set, this is going to prevent constraint system from erasing all
+ /// discovered solutions except the best one.
+ ReturnAllDiscoveredSolutions = 0x04,
};
/// Options that affect the constraint system as a whole.
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index bc7b1ed..0decb20 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -2015,6 +2015,48 @@
return exprType;
}
+void TypeChecker::getPossibleTypesOfExpressionWithoutApplying(
+ Expr *&expr, DeclContext *dc, SmallVectorImpl<Type> &types,
+ FreeTypeVariableBinding allowFreeTypeVariables,
+ ExprTypeCheckListener *listener) {
+ PrettyStackTraceExpr stackTrace(Context, "type-checking", expr);
+
+ // Construct a constraint system from this expression.
+ ConstraintSystemOptions options;
+ options |= ConstraintSystemFlags::AllowFixes;
+ options |= ConstraintSystemFlags::ReturnAllDiscoveredSolutions;
+
+ ConstraintSystem cs(*this, dc, options);
+ CleanupIllFormedExpressionRAII cleanup(Context, expr);
+
+ // Attempt to solve the constraint system.
+ SmallVector<Solution, 4> viable;
+ const Type originalType = expr->getType();
+ const bool needClearType = originalType && originalType->hasError();
+ const auto recoverOriginalType = [&]() {
+ if (needClearType)
+ expr->setType(originalType);
+ };
+
+ // If the previous checking gives the expr error type,
+ // clear the result and re-check.
+ if (needClearType)
+ expr->setType(Type());
+
+ solveForExpression(expr, dc, /*convertType*/ Type(), allowFreeTypeVariables,
+ listener, cs, viable,
+ TypeCheckExprFlags::SuppressDiagnostics);
+
+ for (auto &solution : viable) {
+ auto exprType = solution.simplifyType(cs.getType(expr));
+ assert(exprType && !exprType->hasTypeVariable());
+ types.push_back(exprType);
+ }
+
+ // Recover the original type if needed.
+ recoverOriginalType();
+}
+
bool TypeChecker::typeCheckCompletionSequence(Expr *&expr, DeclContext *DC) {
PrettyStackTraceExpr stackTrace(Context, "type-checking", expr);
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 77b42f7..4e99569 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -1547,6 +1547,12 @@
FreeTypeVariableBinding::Disallow,
ExprTypeCheckListener *listener = nullptr);
+ void getPossibleTypesOfExpressionWithoutApplying(
+ Expr *&expr, DeclContext *dc, SmallVectorImpl<Type> &types,
+ FreeTypeVariableBinding allowFreeTypeVariables =
+ FreeTypeVariableBinding::Disallow,
+ ExprTypeCheckListener *listener = nullptr);
+
bool typeCheckCompletionSequence(Expr *&expr, DeclContext *DC);
/// \brief Type check the given expression assuming that its children
diff --git a/test/Compatibility/tuple_arguments.swift b/test/Compatibility/tuple_arguments.swift
index aa7ddf5..b156918 100644
--- a/test/Compatibility/tuple_arguments.swift
+++ b/test/Compatibility/tuple_arguments.swift
@@ -1460,7 +1460,7 @@
}
let pages1: MutableProperty<(data: DataSourcePage<Int>, totalCount: Int)> = MutableProperty((
- // expected-error@-1 {{cannot convert value of type 'MutableProperty<(data: _, totalCount: Int)>' to specified type 'MutableProperty<(data: DataSourcePage<Int>, totalCount: Int)>'}}
+ // expected-error@-1 {{expression type 'MutableProperty<(data: DataSourcePage<Int>, totalCount: Int)>' is ambiguous without more context}}
data: .notLoaded,
totalCount: 0
))
diff --git a/test/Constraints/closures.swift b/test/Constraints/closures.swift
index bfb7424..6108a15 100644
--- a/test/Constraints/closures.swift
+++ b/test/Constraints/closures.swift
@@ -366,8 +366,7 @@
func r22058555() {
var firstChar: UInt8 = 0
"abc".withCString { chars in
- // FIXME https://bugs.swift.org/browse/SR-4836: was {{cannot assign value of type 'Int8' to type 'UInt8'}}
- firstChar = chars[0] // expected-error {{cannot subscript a value of incorrect or ambiguous type}}
+ firstChar = chars[0] // expected-error {{cannot assign value of type 'Int8' to type 'UInt8'}}
}
}
@@ -529,3 +528,30 @@
// expected-error@-1 {{contextual closure type '() -> ()' expects 0 arguments, but 2 were used in closure body}} {{13-19=}}
print("answer is 42")
}
+
+// rdar://problem/30106822 - Swift ignores type error in closure and presents a bogus error about the caller
+[1, 2].first { $0.foo = 3 }
+// expected-error@-1 {{value of type 'Int' has no member 'foo'}}
+
+// rdar://problem/32433193, SR-5030 - Higher-order function diagnostic mentions the wrong contextual type conversion problem
+protocol A_SR_5030 {
+ associatedtype Value
+ func map<U>(_ t : @escaping (Self.Value) -> U) -> B_SR_5030<U>
+}
+
+struct B_SR_5030<T> : A_SR_5030 {
+ typealias Value = T
+ func map<U>(_ t : @escaping (T) -> U) -> B_SR_5030<U> { fatalError() }
+}
+
+func sr5030_exFalso<T>() -> T {
+ fatalError()
+}
+
+extension A_SR_5030 {
+ func foo() -> B_SR_5030<Int> {
+ let tt : B_SR_5030<Int> = sr5030_exFalso()
+ return tt.map { x in (idx: x) }
+ // expected-error@-1 {{cannot convert value of type '(idx: (Int))' to closure result type 'Int'}}
+ }
+}
diff --git a/test/Constraints/function.swift b/test/Constraints/function.swift
index 6aeb021..d6e661c 100644
--- a/test/Constraints/function.swift
+++ b/test/Constraints/function.swift
@@ -90,12 +90,12 @@
init(f: T) { self.f = f }
}
-func foo(block: () -> ()) {
+func foo(block: () -> ()) { // expected-note 2 {{parameter 'block' is implicitly non-escaping}}
let a = SR2657BlockClass(f: block) // No error
let b = SR2657BlockClass<()->()>(f: block)
- // expected-error@-1 {{invalid conversion from non-escaping function of type '() -> ()' to potentially escaping function type '() -> ()'}}
+ // expected-error@-1 {{passing non-escaping parameter 'block' to function expecting an @escaping closure}}
let c: SR2657BlockClass<()->()> = SR2657BlockClass(f: block)
// expected-error@-1 {{cannot convert value of type 'SR2657BlockClass<() -> ()>' to specified type 'SR2657BlockClass<() -> ()>'}}
let d: SR2657BlockClass<()->()> = SR2657BlockClass<()->()>(f: block)
- // expected-error@-1 {{invalid conversion from non-escaping function of type '() -> ()' to potentially escaping function type '() -> ()'}}
+ // expected-error@-1 {{passing non-escaping parameter 'block' to function expecting an @escaping closure}}
}
diff --git a/test/Constraints/trailing_closures_objc.swift b/test/Constraints/trailing_closures_objc.swift
new file mode 100644
index 0000000..ecea125
--- /dev/null
+++ b/test/Constraints/trailing_closures_objc.swift
@@ -0,0 +1,29 @@
+// RUN: %target-swift-frontend -typecheck -verify %s
+
+// REQUIRES: objc_interop
+// REQUIRES: OS=macosx
+
+import Foundation
+import AVFoundation
+import AppKit
+
+func foo(options: [AVMediaSelectionOption]) {
+ let menuItems: [NSMenuItem] = options.map { (option: AVMediaSelectionOption) in
+ NSMenuItem(title: option.displayName, action: #selector(NSViewController.respondToMediaOptionSelection(from:)), keyEquivalent: "")
+ // expected-error@-1 {{type 'NSViewController' has no member 'respondToMediaOptionSelection(from:)'}}
+ }
+}
+
+func rdar28004686(a: [IndexPath]) {
+ _ = a.sorted { (lhs: NSIndexPath, rhs: NSIndexPath) -> Bool in true }
+ // expected-error@-1 {{'NSIndexPath' is not convertible to 'IndexPath'}}
+}
+
+class Test: NSObject {
+ var categories : NSArray?
+ func rdar28012273() {
+ let categories = ["hello", "world"]
+ self.categories = categories.sorted { $0.localizedCaseInsensitiveCompare($1) == ComparisonResult.orderedDescending }
+ // expected-error@-1 {{cannot assign value of type '[String]' to type 'NSArray?'}} {{121-121= as NSArray}}
+ }
+}
diff --git a/test/Constraints/tuple_arguments.swift b/test/Constraints/tuple_arguments.swift
index 9ec6aa5..3b89692 100644
--- a/test/Constraints/tuple_arguments.swift
+++ b/test/Constraints/tuple_arguments.swift
@@ -1542,3 +1542,12 @@
_ = zip(array1, array2).map(+)
}
+
+struct SR_5199 {}
+extension Sequence where Iterator.Element == (key: String, value: String?) {
+ func f() -> [SR_5199] {
+ return self.map { (key, value) in
+ SR_5199() // Ok
+ }
+ }
+}
diff --git a/test/Generics/invalid.swift b/test/Generics/invalid.swift
index b6e9500..60b320c 100644
--- a/test/Generics/invalid.swift
+++ b/test/Generics/invalid.swift
@@ -54,8 +54,8 @@
func badDiagnostic1() {
_ = Lunch<Pizzas<Pepper>.NewYork>.Dinner<HotDog>(
- leftovers: Pizzas<ChiliFlakes>.NewYork(),
- transformation: { _ in HotDog() }) // expected-error {{cannot convert value of type 'HotDog' to closure result type '_'}}
+ leftovers: Pizzas<ChiliFlakes>.NewYork(), // expected-error {{cannot convert value of type 'Pizzas<ChiliFlakes>.NewYork' to expected argument type 'Pizzas<Pepper>.NewYork'}}
+ transformation: { _ in HotDog() })
}
func badDiagnostic2() {
diff --git a/test/SILGen/c_function_pointers.swift b/test/SILGen/c_function_pointers.swift
index 7724353..18e5141 100644
--- a/test/SILGen/c_function_pointers.swift
+++ b/test/SILGen/c_function_pointers.swift
@@ -63,3 +63,9 @@
init(a: ()) {}
init(b: ()) {}
}
+
+func pointers_to_nested_local_functions_in_generics<T>(x: T) -> Int{
+ func foo(y: Int) -> Int { return y }
+
+ return calls(foo, 0)
+}
diff --git a/test/Sema/substring_to_string_conversion_swift3.swift b/test/Sema/substring_to_string_conversion_swift3.swift
index 1706b39..8035c92 100644
--- a/test/Sema/substring_to_string_conversion_swift3.swift
+++ b/test/Sema/substring_to_string_conversion_swift3.swift
@@ -45,7 +45,7 @@
// CTP_ClosureResult
do {
- [ss].map { (x: Substring) -> String in x } // expected-error {{declared closure result 'String' is incompatible with contextual type '_'}}
+ [ss].map { (x: Substring) -> String in x } // expected-error {{'Substring' is not convertible to 'String'}}
}
// CTP_ArrayElement
diff --git a/test/expr/closure/closures.swift b/test/expr/closure/closures.swift
index cf13d3e..6d043e9 100644
--- a/test/expr/closure/closures.swift
+++ b/test/expr/closure/closures.swift
@@ -14,7 +14,8 @@
var closure3b : (Int,Int) -> (Int) -> (Int,Int) = {{ (4, 2) }} // expected-error{{contextual type for closure argument list expects 2 arguments, which cannot be implicitly ignored}} {{52-52=_,_ in }}
var closure4 : (Int,Int) -> Int = { $0 + $1 }
var closure5 : (Double) -> Int = {
- $0 + 1.0 // expected-error {{cannot convert value of type 'Double' to closure result type 'Int'}}
+ $0 + 1.0
+ // expected-error@+1 {{cannot convert value of type 'Double' to closure result type 'Int'}}
}
var closure6 = $0 // expected-error {{anonymous closure argument not contained in a closure}}