diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index c45964588dfe7..d696e809e573b 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -519,9 +519,9 @@ class TypeVariableType::Implementation { /// Determine whether this type variable represents an opened opaque type. bool isOpaqueType() const; - /// Determine whether this type variable represents a type of an array literal - /// (represented by `ArrayExpr` in AST). - bool isArrayLiteralType() const; + /// Determine whether this type variable represents a type of a collection + /// literal (represented by `ArrayExpr` and `DictionaryExpr` in AST). + bool isCollectionLiteralType() const; /// Retrieve the representative of the equivalence class to which this /// type variable belongs. diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 56f06391f690e..8f0f7bf397136 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -1253,10 +1253,10 @@ bool BindingSet::favoredOverDisjunction(Constraint *disjunction) const { return boundType->lookThroughAllOptionalTypes()->is(); } - // If this is an array literal type, it's preferrable to bind it + // If this is a collection literal type, it's preferrable to bind it // early (unless it's delayed) to connect all of its elements even // if it doesn't have any bindings. - if (TypeVar->getImpl().isArrayLiteralType()) + if (TypeVar->getImpl().isCollectionLiteralType()) return !involvesTypeVariables(); // Don't prioritize type variables that don't have any direct bindings. diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 5e790e7400918..9637bc7612434 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -191,8 +191,9 @@ bool TypeVariableType::Implementation::isOpaqueType() const { return false; } -bool TypeVariableType::Implementation::isArrayLiteralType() const { - return locator && locator->directlyAt(); +bool TypeVariableType::Implementation::isCollectionLiteralType() const { + return locator && (locator->directlyAt() || + locator->directlyAt()); } void *operator new(size_t bytes, ConstraintSystem& cs, diff --git a/test/expr/cast/cf.swift b/test/expr/cast/cf.swift index e06c35e31ff18..0991d63b0eb52 100644 --- a/test/expr/cast/cf.swift +++ b/test/expr/cast/cf.swift @@ -105,3 +105,29 @@ func testBridgedCFDowncast(array: [Any], dictionary: [AnyHashable : Any], set: S _ = cfDictionary as? [AnyHashable : Any] _ = cfSet as? Set } + +func testCastWithImplicitErasure() { + enum Info { + var id: String { "" } + var options: [CFString : Any]? { nil } + } + + class Null {} + + struct Test { + var flag: Bool = false + var info: Info + + func test(key1: CFString!, key2: CFString!, key3: CFString) -> CFDictionary { + [ + key1: flag, + key2: info.id, + key3: info.options ?? Null() + // expected-warning@-1 {{expression implicitly coerced from 'Any?' to 'Any'}} + // expected-note@-2 {{provide a default value to avoid this warning}} + // expected-note@-3 {{force-unwrap the value to avoid this warning}} + // expected-note@-4 {{explicitly cast to 'Any' with 'as Any' to silence this warning}} + ] as CFDictionary + } + } +}