[ConstraintSystem] Detect and diagnose missing generic arguments

Introduce a fix to detect and diagnose situations when omitted
generic arguments couldn't be deduced by the solver based on
the enclosing context.

Example:

```swift
struct S<T> {
}

_ = S() // There is not enough context to deduce `T`
```

Resolves: rdar://problem/51203824
This commit is contained in:
Pavel Yaskevich
2019-05-29 15:21:15 -07:00
parent 636b4ceeb2
commit c30845fa74
24 changed files with 342 additions and 84 deletions

View File

@@ -365,6 +365,10 @@ public:
ArrayRef<TypeRepr*> GenericArgs,
SourceRange AngleBrackets);
unsigned getNumGenericArgs() const {
return Bits.GenericIdentTypeRepr.NumGenericArgs;
}
ArrayRef<TypeRepr*> getGenericArgs() const {
return {getTrailingObjects<TypeRepr*>(),
Bits.GenericIdentTypeRepr.NumGenericArgs};

View File

@@ -1244,14 +1244,11 @@ class MissingGenericArgumentsFailure final : public FailureDiagnostic {
public:
MissingGenericArgumentsFailure(Expr *root, ConstraintSystem &cs,
TypeRepr *baseType,
ArrayRef<TypeVariableType *> missingParams,
ArrayRef<GenericTypeParamType *> missingParams,
ConstraintLocator *locator)
: FailureDiagnostic(root, cs, locator), BaseType(baseType) {
assert(!missingParams.empty());
llvm::transform(missingParams, std::back_inserter(Parameters),
[](const TypeVariableType *GP) {
return GP->getImpl().getGenericParameter();
});
Parameters.append(missingParams.begin(), missingParams.end());
}
SourceLoc getLoc() const;

View File

@@ -540,3 +540,110 @@ CollectionElementContextualMismatch::create(ConstraintSystem &cs, Type srcType,
return new (cs.getAllocator())
CollectionElementContextualMismatch(cs, srcType, dstType, locator);
}
bool ExplicitlySpecifyGenericArguments::diagnose(Expr *root,
bool asNote) const {
auto &cs = getConstraintSystem();
bool diagnosed = false;
for (const auto &paramsPerAnchor : Parameters) {
auto anchor = paramsPerAnchor.first;
ArrayRef<GenericTypeParamType *> missingParameters = paramsPerAnchor.second;
MissingGenericArgumentsFailure failure(root, cs,
anchor.dyn_cast<TypeRepr *>(),
missingParameters, getLocator());
diagnosed |= failure.diagnose(asNote);
}
return diagnosed;
}
ExplicitlySpecifyGenericArguments *ExplicitlySpecifyGenericArguments::create(
ConstraintSystem &cs, ArrayRef<GenericTypeParamType *> params,
ConstraintLocator *locator) {
llvm::SmallDenseMap<TypeRepr *, llvm::SmallVector<GenericTypeParamType *, 4>>
typeBasedParams;
if (findArgumentLocations(locator->getAnchor(), params,
[&](TypeRepr *base, GenericTypeParamType *GP) {
typeBasedParams[base].push_back(GP);
}))
return new (cs.getAllocator())
ExplicitlySpecifyGenericArguments(cs, typeBasedParams, locator);
return new (cs.getAllocator())
ExplicitlySpecifyGenericArguments(cs, params, locator);
}
bool ExplicitlySpecifyGenericArguments::findArgumentLocations(
Expr *anchor, ArrayRef<GenericTypeParamType *> genericParams,
llvm::function_ref<void(TypeRepr *, GenericTypeParamType *)> callback) {
using Callback = llvm::function_ref<void(TypeRepr *, GenericTypeParamType *)>;
if (!anchor)
return false;
TypeLoc typeLoc;
if (auto *TE = dyn_cast<TypeExpr>(anchor))
typeLoc = TE->getTypeLoc();
else if (auto *ECE = dyn_cast<ExplicitCastExpr>(anchor))
typeLoc = ECE->getCastTypeLoc();
if (!typeLoc.hasLocation())
return false;
llvm::SmallVector<GenericTypeParamType *, 4> params(genericParams.begin(),
genericParams.end());
struct AssociateMissingParams : public ASTWalker {
llvm::SmallVectorImpl<GenericTypeParamType *> &Params;
Callback Fn;
AssociateMissingParams(SmallVectorImpl<GenericTypeParamType *> &params,
Callback callback)
: Params(params), Fn(callback) {}
bool walkToTypeReprPre(TypeRepr *T) override {
if (Params.empty())
return false;
auto *ident = dyn_cast<ComponentIdentTypeRepr>(T);
if (!ident)
return true;
auto *decl = dyn_cast_or_null<GenericTypeDecl>(ident->getBoundDecl());
if (!decl)
return true;
auto *paramList = decl->getGenericParams();
if (!paramList)
return true;
// There could a situation like `S<S>()`, so we need to be
// careful not to point at first `S` because it has all of
// its generic parameters specified.
if (auto *generic = dyn_cast<GenericIdentTypeRepr>(ident)) {
if (paramList->size() == generic->getNumGenericArgs())
return true;
}
for (auto *candidate : paramList->getParams()) {
auto result =
llvm::find_if(Params, [&](const GenericTypeParamType *param) {
return candidate == param->getDecl();
});
if (result != Params.end()) {
Fn(ident, *result);
Params.erase(result);
}
}
// Keep walking.
return true;
}
} paramAssociator(params, callback);
typeLoc.getTypeRepr()->walk(paramAssociator);
return params.empty();
}

View File

@@ -153,6 +153,11 @@ enum class FixKind : uint8_t {
/// Remove `return` or default last expression of single expression
/// function to `Void` to conform to expected result type.
RemoveReturn,
/// Generic parameters could not be inferred and have to be explicitly
/// specified in the source. This fix groups all of the missing arguments
/// associated with single declaration.
ExplicitlySpecifyGenericArguments,
};
class ConstraintFix {
@@ -917,6 +922,53 @@ public:
ConstraintLocator *locator);
};
class ExplicitlySpecifyGenericArguments final : public ConstraintFix {
using Anchor = llvm::PointerUnion<ConstraintLocator *, TypeRepr *>;
llvm::SmallDenseMap<Anchor, llvm::SmallVector<GenericTypeParamType *, 4>>
Parameters;
ExplicitlySpecifyGenericArguments(ConstraintSystem &cs,
ArrayRef<GenericTypeParamType *> params,
ConstraintLocator *locator)
: ConstraintFix(cs, FixKind::ExplicitlySpecifyGenericArguments, locator) {
assert(!params.empty());
Parameters[locator].append(params.begin(), params.end());
}
ExplicitlySpecifyGenericArguments(
ConstraintSystem &cs,
llvm::SmallDenseMap<TypeRepr *,
llvm::SmallVector<GenericTypeParamType *, 4>> &params,
ConstraintLocator *locator)
: ConstraintFix(cs, FixKind::ExplicitlySpecifyGenericArguments, locator) {
assert(!params.empty());
for (const auto &elt : params) {
Parameters.insert(elt);
}
}
public:
std::string getName() const override {
return "default missing generic argument to `Any`";
}
bool diagnose(Expr *root, bool asNote = false) const override;
static ExplicitlySpecifyGenericArguments *
create(ConstraintSystem &cs, ArrayRef<GenericTypeParamType *> params,
ConstraintLocator *locator);
private:
/// Retrieve representative locations for given generic prameters
/// rooted at the given anchor.
///
/// \returns true if all of the parameters have been covered.
static bool findArgumentLocations(
Expr *anchor, ArrayRef<GenericTypeParamType *> genericParams,
llvm::function_ref<void(TypeRepr *, GenericTypeParamType *)> callback);
};
} // end namespace constraints
} // end namespace swift

View File

@@ -6659,6 +6659,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
case FixKind::AllowAnyObjectKeyPathRoot:
case FixKind::TreatKeyPathSubscriptIndexAsHashable:
case FixKind::AllowInvalidRefInKeyPath:
case FixKind::ExplicitlySpecifyGenericArguments:
llvm_unreachable("handled elsewhere");
}

View File

@@ -275,8 +275,58 @@ StepResult ComponentStep::take(bool prevFailed) {
// If there are no disjunctions or type variables to bind
// we can't solve this system unless we have free type variables
// allowed in the solution.
if (!CS.solverState->allowsFreeTypeVariables() && CS.hasFreeTypeVariables())
return done(/*isSuccess=*/false);
if (!CS.solverState->allowsFreeTypeVariables() && CS.hasFreeTypeVariables()) {
if (!CS.shouldAttemptFixes())
return done(/*isSuccess=*/false);
// Let's see if all of the free type variables are associated with
// generic parameters and if so, let's default them to `Any` and continue
// solving so we can properly diagnose the problem later by suggesting
// to explictly specify them.
llvm::SmallDenseMap<ConstraintLocator *,
llvm::SmallVector<GenericTypeParamType *, 4>>
defaultableGenericParams;
for (auto *typeVar : CS.getTypeVariables()) {
if (typeVar->getImpl().hasRepresentativeOrFixed())
continue;
// If this free type variable is not a generic parameter
// we are done.
auto *locator = typeVar->getImpl().getLocator();
auto *anchor = locator->getAnchor();
if (!(anchor && locator->isForGenericParameter()))
return done(/*isSuccess=*/false);
// Increment the score for every missing generic argument
// to make ranking of the solutions with different number
// of generic arguments easier.
CS.increaseScore(ScoreKind::SK_Fix);
// Default argument to `Any`.
CS.assignFixedType(typeVar, CS.getASTContext().TheAnyType);
// Note that this generic argument has been given a default value.
CS.DefaultedConstraints.push_back(locator);
auto path = locator->getPath();
// Let's drop `generic parameter '...'` part of the locator to
// group all of the missing generic parameters related to the
// same path together.
defaultableGenericParams[CS.getConstraintLocator(anchor, path.drop_back(),
/*summaryFlags=*/0)]
.push_back(locator->getGenericParameter());
}
for (const auto &missing : defaultableGenericParams) {
auto *locator = missing.first;
auto &missingParams = missing.second;
auto *fix =
ExplicitlySpecifyGenericArguments::create(CS, missingParams, locator);
if (CS.recordFix(fix))
return done(/*isSuccess=*/false);
}
}
// If this solution is worse than the best solution we've seen so far,
// skip it.

View File

@@ -100,13 +100,9 @@ void ConstraintSystem::incrementLeafScopes() {
bool ConstraintSystem::hasFreeTypeVariables() {
// Look for any free type variables.
for (auto tv : TypeVariables) {
if (!tv->getImpl().hasRepresentativeOrFixed()) {
return true;
}
}
return false;
return llvm::any_of(TypeVariables, [](const TypeVariableType *typeVar) {
return !typeVar->getImpl().hasRepresentativeOrFixed();
});
}
void ConstraintSystem::addTypeVariable(TypeVariableType *typeVar) {

View File

@@ -102,7 +102,7 @@ func longArray() {
var _=["1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"]
}
[1,2].map // expected-error {{expression type '((Int) throws -> _) throws -> [_]' is ambiguous without more context}}
[1,2].map // expected-error {{generic parameter 'T' could not be inferred}}
// <rdar://problem/25563498> Type checker crash assigning array literal to type conforming to ArrayProtocol

View File

@@ -223,7 +223,9 @@ func takesDictionary<K, V>(_ p: Dictionary<K, V>) {} // expected-note {{in call
func takesArray<T>(_ t: Array<T>) {} // expected-note {{in call to function 'takesArray'}}
func rdar19695671() {
takesSet(NSSet() as! Set) // expected-error{{generic parameter 'T' could not be inferred}}
takesDictionary(NSDictionary() as! Dictionary) // expected-error{{generic parameter 'K' could not be inferred}}
takesDictionary(NSDictionary() as! Dictionary)
// expected-error@-1 {{generic parameter 'K' could not be inferred}}
// expected-error@-2 {{generic parameter 'V' could not be inferred}}
takesArray(NSArray() as! Array) // expected-error{{generic parameter 'T' could not be inferred}}
}

View File

@@ -716,7 +716,7 @@ func rdar37790062() {
}
// <rdar://problem/39489003>
typealias KeyedItem<K, T> = (key: K, value: T)
typealias KeyedItem<K, T> = (key: K, value: T) // expected-note {{'T' declared as parameter to type 'KeyedItem'}}
protocol Node {
associatedtype T
@@ -730,8 +730,7 @@ extension Node {
func getChild(for key:K)->(key: K, value: T) {
return children.first(where: { (item:KeyedItem) -> Bool in
return item.key == key
// expected-error@-1 {{binary operator '==' cannot be applied to operands of type '_' and 'Self.K'}}
// expected-note@-2 {{overloads for '==' exist with these partially matching parameter lists:}}
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
})!
}
}
@@ -814,13 +813,15 @@ func rdar_40537960() {
init(_: P_40537960) {}
}
struct A<T: Collection, P: P_40537960> {
struct A<T: Collection, P: P_40537960> { // expected-note {{'P' declared as parameter to type 'A'}}
typealias Data = T.Element
init(_: T, fn: (Data) -> R<P>) {}
}
var arr: [S] = []
_ = A(arr, fn: { L($0.v) }) // expected-error {{cannot convert value of type 'L' to closure result type 'R<T>'}}
_ = A(arr, fn: { L($0.v) }) // expected-error {{cannot convert value of type 'L' to closure result type 'R<Any>'}}
// expected-error@-1 {{generic parameter 'P' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{8-8=<[S], <#P: P_40537960#>>}}
}
// rdar://problem/45659733

View File

@@ -903,7 +903,7 @@ func test2208() {
// SR-2164: Erroneous diagnostic when unable to infer generic type
struct SR_2164<A, B> { // expected-note 3 {{'B' declared as parameter to type 'SR_2164'}} expected-note 2 {{'A' declared as parameter to type 'SR_2164'}} expected-note * {{generic type 'SR_2164' declared here}}
struct SR_2164<A, B> { // expected-note 4 {{'B' declared as parameter to type 'SR_2164'}} expected-note 2 {{'A' declared as parameter to type 'SR_2164'}} expected-note * {{generic type 'SR_2164' declared here}}
init(a: A) {}
init(b: B) {}
init(c: Int) {}
@@ -921,7 +921,10 @@ struct SR_2164_Dict<A: Hashable, B> { // expected-note {{'B' declared as paramet
SR_2164(a: 0) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}}
SR_2164(b: 1) // expected-error {{generic parameter 'A' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}}
SR_2164(c: 2) // expected-error {{generic parameter 'A' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}}
SR_2164(c: 2)
// expected-error@-1 {{generic parameter 'A' could not be inferred}}
// expected-error@-2 {{generic parameter 'B' could not be inferred}}
// expected-note@-3 {{explicitly specify the generic arguments to fix this issue}} {{8-8=<Any, Any>}}
SR_2164(3) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}}
SR_2164_Array([4]) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}}
SR_2164(e: 5) // expected-error {{generic parameter 'B' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}}

View File

@@ -52,7 +52,7 @@ func generic_metatypes<T : SomeProtocol>(_ x: T)
}
// Inferring a variable's type from a call to a generic.
struct Pair<T, U> { } // expected-note 3 {{'T' declared as parameter to type 'Pair'}} expected-note 2 {{'U' declared as parameter to type 'Pair'}}
struct Pair<T, U> { } // expected-note 3 {{'T' declared as parameter to type 'Pair'}} expected-note 3 {{'U' declared as parameter to type 'Pair'}}
func pair<T, U>(_ x: T, _ y: U) -> Pair<T, U> { }
@@ -219,8 +219,7 @@ protocol P19215114 {}
func body9215114<T: P19215114, U: Q19215114>(_ t: T) -> (_ u: U) -> () {}
func test9215114<T: P19215114, U: Q19215114>(_ t: T) -> (U) -> () {
//Should complain about not being able to infer type of U.
let f = body9215114(t) // expected-error {{generic parameter 'T' could not be inferred}}
let f = body9215114(t) // expected-error {{generic parameter 'U' could not be inferred}}
return f
}
@@ -231,7 +230,7 @@ class Whatever<A: Numeric, B: Numeric> { // expected-note 2 {{'A' declared as p
static func bar() {}
}
Whatever.foo(a: 23) // expected-error {{generic parameter 'A' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{9-9=<<#A: Numeric#>, <#B: Numeric#>>}}
Whatever.foo(a: 23) // expected-error {{generic parameter 'A' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{9-9=<<#A: Numeric#>, Int>}}
// <rdar://problem/21718955> Swift useless error: cannot invoke 'foo' with no arguments
Whatever.bar() // expected-error {{generic parameter 'A' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{9-9=<<#A: Numeric#>, <#B: Numeric#>>}}
@@ -262,7 +261,7 @@ protocol SubProto: BaseProto {}
func copy() -> Any
}
struct FullyGeneric<Foo> {} // expected-note 11 {{'Foo' declared as parameter to type 'FullyGeneric'}} expected-note 1 {{generic type 'FullyGeneric' declared here}}
struct FullyGeneric<Foo> {} // expected-note 13 {{'Foo' declared as parameter to type 'FullyGeneric'}} expected-note 1 {{generic type 'FullyGeneric' declared here}}
struct AnyClassBound<Foo: AnyObject> {} // expected-note {{'Foo' declared as parameter to type 'AnyClassBound'}} expected-note {{generic type 'AnyClassBound' declared here}}
// expected-note@-1{{requirement specified as 'Foo' : 'AnyObject'}}
@@ -340,7 +339,10 @@ func testFixIts() {
// expected-error@-1 {{referencing initializer 'init()' on 'ClassAndProtosBound2' requires that 'X' conform to 'NSCopyish'}}
// expected-error@-2 {{referencing initializer 'init()' on 'ClassAndProtosBound2' requires that 'X' conform to 'SubProto'}}
_ = Pair() // expected-error {{generic parameter 'T' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{11-11=<Any, Any>}}
_ = Pair()
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
// expected-error@-2 {{generic parameter 'U' could not be inferred}}
// expected-note@-3 {{explicitly specify the generic arguments to fix this issue}} {{11-11=<Any, Any>}}
_ = Pair(first: S()) // expected-error {{generic parameter 'U' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{11-11=<S, Any>}}
_ = Pair(second: S()) // expected-error {{generic parameter 'T' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{11-11=<Any, S>}}
}
@@ -359,13 +361,13 @@ func testFixItClassBound() {
}
func testFixItCasting(x: Any) {
_ = x as! FullyGeneric // expected-error {{generic parameter 'Foo' could not be inferred in cast to 'FullyGeneric<_>'}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{25-25=<Any>}}
_ = x as! FullyGeneric // expected-error {{generic parameter 'Foo' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{25-25=<Any>}}
}
func testFixItContextualKnowledge() {
// FIXME: These could propagate backwards.
let _: Int = Pair().first // expected-error {{generic parameter 'U' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{20-20=<Any, Any>}}
let _: Int = Pair().second // expected-error {{generic parameter 'T' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{20-20=<Any, Any>}}
let _: Int = Pair().first // expected-error {{generic parameter 'U' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{20-20=<Int, Any>}}
let _: Int = Pair().second // expected-error {{generic parameter 'T' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{20-20=<Any, Int>}}
}
func testFixItTypePosition() {
@@ -382,32 +384,47 @@ func testFixItNested() {
_ = [FullyGeneric]() // expected-error {{generic parameter 'Foo' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{20-20=<Any>}}
_ = FullyGeneric<FullyGeneric>() // expected-error {{generic parameter 'Foo' could not be inferred}}
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} {{32-32=<Any>}}
_ = Pair< // expected-error {{generic parameter 'Foo' could not be inferred}}
_ = Pair<
FullyGeneric,
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
FullyGeneric // FIXME: We could diagnose both of these, but we don't.
// expected-error@-1 {{generic parameter 'Foo' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
FullyGeneric
// expected-error@-1 {{generic parameter 'Foo' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
>()
_ = Pair< // expected-error {{generic parameter 'Foo' could not be inferred}}
_ = Pair<
FullyGeneric<Any>,
FullyGeneric
// expected-error@-1 {{generic parameter 'Foo' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
>()
_ = Pair< // expected-error {{generic parameter 'Foo' could not be inferred}}
_ = Pair<
FullyGeneric,
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
// expected-error@-1 {{generic parameter 'Foo' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
FullyGeneric<Any>
>()
_ = pair( // expected-error {{generic parameter 'Foo' could not be inferred}} {{none}}
FullyGeneric(), // expected-note {{explicitly specify the generic arguments to fix this issue}}
_ = pair(
FullyGeneric(),
// expected-error@-1 {{generic parameter 'Foo' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
FullyGeneric()
// expected-error@-1 {{generic parameter 'Foo' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
)
_ = pair( // expected-error {{generic parameter 'Foo' could not be inferred}} {{none}}
_ = pair(
FullyGeneric<Any>(),
FullyGeneric() // expected-note {{explicitly specify the generic arguments to fix this issue}}
FullyGeneric()
// expected-error@-1 {{generic parameter 'Foo' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
)
_ = pair( // expected-error {{generic parameter 'Foo' could not be inferred}} {{none}}
FullyGeneric(), // expected-note {{explicitly specify the generic arguments to fix this issue}}
_ = pair(
FullyGeneric(),
// expected-error@-1 {{generic parameter 'Foo' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
FullyGeneric<Any>()
)
}
@@ -435,7 +452,7 @@ class GenericClass<A> {}
func genericFunc<T>(t: T) {
_ = [T: GenericClass] // expected-error {{generic parameter 'A' could not be inferred}}
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}}
// expected-error@-2 3 {{type 'T' does not conform to protocol 'Hashable'}}
// expected-error@-2 {{type 'T' does not conform to protocol 'Hashable'}}
}
struct SR_3525<T> {}
@@ -707,3 +724,26 @@ struct SR10694 {
// expected-error@-1 {{initializing from a metatype value must reference 'init' explicitly}}
}
}
// SR-7003 (rdar://problem/51203824) - Poor diagnostics when attempting to access members on unfulfilled generic type
func sr_7003() {
struct E<T> { // expected-note 4 {{'T' declared as parameter to type 'E'}}
static var foo: String { return "" }
var bar: String { return "" }
static func baz() -> String { return "" }
func qux() -> String { return "" }
}
let _: Any = E.foo
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
let _: Any = E().bar
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
let _: Any = E.baz()
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
let _: Any = E().qux()
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{17-17=<Any>}}
}

View File

@@ -1,12 +1,13 @@
// RUN: %target-typecheck-verify-swift
struct MyCollection<Element> { // expected-note {{'Element' declared as parameter to type 'MyCollection'}}
func map<T>(_ transform: (Element) -> T) -> MyCollection<T> {
func map<T>(_ transform: (Element) -> T) -> MyCollection<T> { // expected-note 2 {{in call to function 'map'}}
fatalError("implement")
}
}
MyCollection.map // expected-error{{generic parameter 'Element' could not be inferred}} expected-note {{explicitly specify the generic arguments to fix this issue}} {{13-13=<Any>}}
// expected-error@-1 {{generic parameter 'T' could not be inferred}}
let a = MyCollection<Int>()
a.map // expected-error{{generic parameter 'T' could not be inferred}}

View File

@@ -347,7 +347,9 @@ func trailingClosure5<T>(_ file: String = #file, line: UInt = #line, expression:
func trailingClosure6<T>(value: Int, expression: () -> T?) { }
trailingClosure5(file: "hello", line: 17) { return Optional.Some(5) } // expected-error{{extraneous argument label 'file:' in call}}{{18-24=}}
// expected-error@-1 {{enum type 'Optional<Any>' has no case 'Some'; did you mean 'some'}} {{61-65=some}}
trailingClosure6(5) { return Optional.Some(5) } // expected-error{{missing argument label 'value:' in call}}{{18-18=value: }}
// expected-error@-1 {{enum type 'Optional<Any>' has no case 'Some'; did you mean 'some'}} {{39-43=some}}
class MismatchOverloaded1 {
func method1(_ x: Int!, arg: ((Int) -> Int)!) { }

View File

@@ -3,7 +3,7 @@
struct D {}
class Future<T> {
func then<U>(_ fn: @escaping (T) -> Future<U>) -> Future<U> { fatalError() }
func then<U>(_ fn: @escaping (T) -> Future<U>) -> Future<U> { fatalError() } // expected-note {{in call to function 'then'}}
func thenThrowing<U>(_ fn: @escaping (T) throws -> U) -> Future<U> { fatalError() }
func whenFailure(_ fn: @escaping (Error) -> Void) {}
@@ -12,21 +12,18 @@ class Future<T> {
protocol P {
func foo(arr: [D], data: ArraySlice<UInt8>) -> Future<D>
// expected-note@-1 {{found this candidate}}
func bar(root: D, from: P) -> Future<D>
}
extension P {
func foo(arr: [D] = [], data: [UInt8]) -> Future<D> { fatalError() }
// expected-note@-1 {{found this candidate}}
}
func crash(_ p: P, payload: [UInt8]) throws {
p.foo(data: payload).then { _ in
return Future<(D, [D])>()
}.then { (id, arr) in
}.then { (id, arr) in // expected-error {{generic parameter 'U' could not be inferred}}
p.foo(arr: arr, data: []).and(result: (id, arr))
// expected-error@-1 {{mbiguous reference to member 'foo(arr:data:)'}}
}.then { args0 in
let (parentID, args1) = args0
p.bar(root: parentID, from: p).and(args1)

View File

@@ -219,13 +219,13 @@ extension r25271859 {
func map<U>(f: (T) -> U) -> r25271859<U> {
}
func andThen<U>(f: (T) -> r25271859<U>) {
func andThen<U>(f: (T) -> r25271859<U>) { // expected-note {{in call to function 'andThen(f:)'}}
}
}
func f(a : r25271859<(Float, Int)>) {
a.map { $0.0 }
.andThen { _ in // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{18-18=-> r25271859<String> }}
a.map { $0.0 } // expected-error {{generic parameter 'U' could not be inferred}} (This is related to how solver is setup with multiple statements)
.andThen { _ in
print("hello") // comment this out and it runs, leave any form of print in and it doesn't
return r25271859<String>()
}

View File

@@ -23,7 +23,7 @@ struct Lunch<T> {
}
}
class Deli<Spices> {
class Deli<Spices> { // expected-note {{'Spices' declared as parameter to type 'Deli'}}
class Pepperoni {}
struct Sausage {}
@@ -79,7 +79,8 @@ func badDiagnostic2() {
func takesAny(_ a: Any) {}
func badDiagnostic3() {
takesAny(Deli.self) // expected-error {{argument type 'Deli<_>.Type' does not conform to expected type 'Any'}}
takesAny(Deli.self) // expected-error {{generic parameter 'Spices' could not be inferred}}
// expected-note@-1 {{explicitly specify the generic arguments to fix this issue}} {{16-16=<Any>}}
}
// Crash with missing nested type inside concrete type

View File

@@ -121,7 +121,7 @@ protocol P {} // expected-error {{invalid redeclaration of 'P'}}
// expected-note@-1 {{did you mean 'P'?}}
func hasTypo() {
_ = P.a.a // expected-error {{type 'Generic<_>' has no member 'a'}}
_ = P.a.a // expected-error {{type 'Generic<Any>' has no member 'a'}}
}
// Typo correction with AnyObject.

View File

@@ -390,7 +390,8 @@ func testPostfixOperatorOnTuple<A, B>(a: A, b: B) {
_ = (§)foo
// expected-error@-1 {{consecutive statements on a line must be separated by ';'}}
// expected-error@-2 {{generic parameter 'T' could not be inferred}}
// expected-warning@-3 {{expression of type '(A, (B, B), A)' is unused}}
// expected-error@-3 {{generic parameter 'U' could not be inferred}}
// expected-warning@-4 {{expression of type '(A, (B, B), A)' is unused}}
_ = (§)(foo)
_ = (a, (b, b), a)§
_ = (§)(a, (b, b), a) // expected-error {{operator function '§' expects a single parameter of type '(T, (U, U), T)'}}

View File

@@ -377,7 +377,7 @@ protocol ExpressibleByDogLiteral {}
struct Kitten : ExpressibleByCatLiteral {}
struct Puppy : ExpressibleByDogLiteral {}
struct Claws<A: ExpressibleByCatLiteral> {
struct Claws<A: ExpressibleByCatLiteral> { // expected-note 3 {{'A' declared as parameter to type 'Claws'}}
struct Fangs<B: ExpressibleByDogLiteral> { } // expected-note {{where 'B' = 'NotADog'}}
}
@@ -387,7 +387,7 @@ func pets<T>(fur: T) -> Claws<Kitten>.Fangs<T> {
return Claws<Kitten>.Fangs<T>()
}
func something<T>() -> T { // expected-note {{in call to function 'something()'}}
func something<T>() -> T {
while true {}
}
@@ -398,11 +398,14 @@ func test() {
let _: Claws.Fangs<Puppy> = pets(fur: Puppy())
let _: Claws.Fangs<Puppy> = Claws<Kitten>.Fangs()
let _: Claws.Fangs<Puppy> = Claws.Fangs()
// expected-error@-1 {{cannot convert value of type 'Claws<_>.Fangs<_>' to specified type 'Claws.Fangs<Puppy>'}}
// expected-error@-1 {{generic parameter 'A' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{36-36=<<#A: ExpressibleByCatLiteral#>>}}
let _: Claws.Fangs<NotADog> = something()
// expected-error@-1 {{generic parameter 'T' could not be inferred}} // FIXME: bad diagnostic
_ = Claws.Fangs<NotADog>() // TODO(diagnostics): There should be two errors here - "cannot infer A" and "NotADog conformance to ExpressibleByDogLiteral"
// expected-error@-1 {{referencing initializer 'init()' on 'Claws.Fangs' requires that 'NotADog' conform to 'ExpressibleByDogLiteral'}}
// expected-error@-1 {{generic parameter 'A' could not be inferred}}
_ = Claws.Fangs<NotADog>()
// expected-error@-1 {{generic parameter 'A' could not be inferred}}
// expected-error@-2 {{referencing initializer 'init()' on 'Claws.Fangs' requires that 'NotADog' conform to 'ExpressibleByDogLiteral'}}
// expected-note@-3 {{explicitly specify the generic arguments to fix this issue}} {{12-12=<<#A: ExpressibleByCatLiteral#>>}}
}
// https://bugs.swift.org/browse/SR-4379

View File

@@ -60,7 +60,7 @@ typealias B<T1> = MyType<T1, T1> // expected-note {{'T1' declared as parameter
typealias C<T> = MyType<String, T>
// Type aliases with unused generic params.
typealias D<T1, T2, T3> = MyType<T2, T1> // expected-note {{'T3' declared as parameter to type 'D'}}
typealias D<T1, T2, T3> = MyType<T2, T1> // expected-note 3 {{'T3' declared as parameter to type 'D'}}
typealias E<T1, T2> = Int // expected-note {{generic type 'E' declared here}}
@@ -72,17 +72,18 @@ typealias G<S1, S2> = A<S1, S2>
let _ : E<Int, Float> = 42
let _ : E<Float> = 42 // expected-error {{generic type 'E' specialized with too few type parameters (got 1, but expected 2)}}
let _ : E = 42 // expected-error {{cannot convert value of type 'Int' to specified type 'E'}}
let _ : D = D(a: 1, b: 2) // expected-error {{cannot convert value of type 'MyType<Int, Int>' to specified type 'D'}}
let _ : D = D(a: 1, b: 2)
// expected-error@-1 {{generic parameter 'T3' could not be inferred}}
// expected-note@-2 {{explicitly specify the generic arguments to fix this issue}} {{14-14=<Int, Int, Any>}}
let _ : D<Int, Int, Float> = D<Int, Int, Float>(a: 1, b: 2)
// FIXME: This is not a great error.
// expected-error @+1 {{cannot convert value of type 'D<Int, Int, Float>' (aka 'MyType<Int, Int>') to specified type 'D'}}
let _ : D = D<Int, Int, Float>(a: 1, b: 2)
// expected-error@-1 {{generic parameter 'T3' could not be inferred}}
// expected-error @+2 {{generic parameter 'T3' could not be inferred}}
// expected-note @+1 {{explicitly specify the generic arguments to fix this issue}} {{31-31=<Any, Any, Any>}}
// expected-note @+1 {{explicitly specify the generic arguments to fix this issue}} {{31-31=<Int, Int, Any>}}
let _ : D<Int, Int, Float> = D(a: 1, b: 2)
let _ : F = { (a : Int) -> Int in a } // Infer the types of F

View File

@@ -15,7 +15,7 @@ e1 = .Third(5, 3.14159)
e1 = .default // SE-0071
// Generic enumeration type
enum E2<T> {
enum E2<T> { // expected-note {{'T' declared as parameter to type 'E2'}}
case First
case Second(T)
}

View File

@@ -36,7 +36,7 @@ struct A: Hashable {
func hash(into hasher: inout Hasher) { fatalError() }
}
struct B {}
struct C<T> {
struct C<T> { // expected-note 2 {{'T' declared as parameter to type 'C'}}
var value: T
subscript() -> T { get { return value } }
subscript(sub: Sub) -> T { get { return value } set { } }
@@ -190,7 +190,7 @@ func testKeyPath(sub: Sub, optSub: OptSub,
let _: AnyKeyPath = \A.property
let _: AnyKeyPath = \C<A>.value
let _: AnyKeyPath = \.property // expected-error{{ambiguous}}
let _: AnyKeyPath = \C.value // expected-error{{cannot convert}} (need to improve diagnostic)
let _: AnyKeyPath = \C.value // expected-error{{generic parameter 'T' could not be inferred}}
let _: AnyKeyPath = \.value // expected-error{{ambiguous}}
let _ = \Prop.[nonHashableSub] // expected-error{{subscript index of type 'NonHashableSub' in a key path must be Hashable}}
@@ -282,9 +282,8 @@ func tupleGeneric<T, U>(_ v: (T, U)) {
_ = ("tuple", "too", "big")[keyPath: tuple_el_1()]
// expected-note@-12 {{}}
// expected-error@-2 {{cannot be applied}}
// expected-error@-3 {{cannot be applied}}
// expected-error@-4 {{could not be inferred}}
// expected-error@-2 {{generic parameter 'T' could not be inferred}}
// expected-error@-3 {{generic parameter 'U' could not be inferred}}
}
struct Z { }

View File

@@ -49,32 +49,32 @@ func mismatchedAppends<T, U, V>(readOnlyLeft: KeyPath<T, U>,
readOnlyRight: KeyPath<U, V>,
writableRight: WritableKeyPath<U, V>,
referenceRight: ReferenceWritableKeyPath<U, V>){
// expected-error@+1{{}}
_ = readOnlyRight.appending(path: readOnlyLeft)
// expected-error@-1 {{referencing instance method 'appending(path:)' on '_AppendKeyPath' requires the types 'KeyPath<U, V>' and 'AnyKeyPath' be equivalent}}
// expected-error@+1{{}}
_ = readOnlyRight.appending(path: writableLeft)
// expected-error@-1 {{referencing instance method 'appending(path:)' on '_AppendKeyPath' requires the types 'KeyPath<U, V>' and 'AnyKeyPath' be equivalent}}
// expected-error@+1{{}}
_ = readOnlyRight.appending(path: referenceLeft)
// expected-error@-1 {{referencing instance method 'appending(path:)' on '_AppendKeyPath' requires the types 'KeyPath<U, V>' and 'AnyKeyPath' be equivalent}}
// expected-error@+1{{}}
_ = writableRight.appending(path: readOnlyLeft)
// expected-error@-1 {{referencing instance method 'appending(path:)' on '_AppendKeyPath' requires the types 'WritableKeyPath<U, V>' and 'AnyKeyPath' be equivalent}}
// expected-error@+1{{}}
_ = writableRight.appending(path: writableLeft)
// expected-error@-1 {{referencing instance method 'appending(path:)' on '_AppendKeyPath' requires the types 'WritableKeyPath<U, V>' and 'AnyKeyPath' be equivalent}}
// expected-error@+1{{}}
_ = writableRight.appending(path: referenceLeft)
// expected-error@-1 {{referencing instance method 'appending(path:)' on '_AppendKeyPath' requires the types 'WritableKeyPath<U, V>' and 'AnyKeyPath' be equivalent}}
// expected-error@+1{{}}
_ = referenceRight.appending(path: readOnlyLeft)
// expected-error@-1 {{referencing instance method 'appending(path:)' on '_AppendKeyPath' requires the types 'ReferenceWritableKeyPath<U, V>' and 'AnyKeyPath' be equivalent}}
// expected-error@+1{{}}
_ = referenceRight.appending(path: writableLeft)
// expected-error@-1 {{referencing instance method 'appending(path:)' on '_AppendKeyPath' requires the types 'ReferenceWritableKeyPath<U, V>' and 'AnyKeyPath' be equivalent}}
// expected-error@+1{{}}
_ = referenceRight.appending(path: referenceLeft)
// expected-error@-1 {{referencing instance method 'appending(path:)' on '_AppendKeyPath' requires the types 'ReferenceWritableKeyPath<U, V>' and 'AnyKeyPath' be equivalent}}
}
func partialAppends<T, U, V>(partial: PartialKeyPath<T>,