Skip to content

Commit 0b3c210

Browse files
authored
Merge pull request #26716 from xedin/transform-incorrect-args
[Diagnostics] Transform `incorrect generic arguments` into a contexua…
2 parents a2b8826 + 7ac754a commit 0b3c210

File tree

9 files changed

+76
-82
lines changed

9 files changed

+76
-82
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -650,10 +650,8 @@ void GenericArgumentsMismatchFailure::emitNoteForMismatch(int position) {
650650
auto genericTypeDecl = paramSourceTy->getAnyGeneric();
651651
auto param = genericTypeDecl->getGenericParams()->getParams()[position];
652652

653-
auto lhs = resolveType(getActual()->getGenericArgs()[position])
654-
->reconstituteSugar(/*recursive=*/false);
655-
auto rhs = resolveType(getRequired()->getGenericArgs()[position])
656-
->reconstituteSugar(/*recursive=*/false);
653+
auto lhs = getActual()->getGenericArgs()[position];
654+
auto rhs = getRequired()->getGenericArgs()[position];
657655

658656
auto noteLocation = param->getLoc();
659657

@@ -677,8 +675,8 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() {
677675
const auto &last = path.back();
678676
switch (last.getKind()) {
679677
case ConstraintLocator::ContextualType: {
680-
auto purpose = getConstraintSystem().getContextualTypePurpose();
681-
assert(purpose != CTP_Unused);
678+
auto purpose = getContextualTypePurpose();
679+
assert(!(purpose == CTP_Unused && purpose == CTP_CannotFail));
682680
diagnostic = getDiagnosticFor(purpose);
683681
break;
684682
}
@@ -701,17 +699,14 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() {
701699
}
702700

703701
default:
704-
break;
702+
return false;
705703
}
706704
}
707705

708706
if (!diagnostic)
709707
return false;
710708

711-
emitDiagnostic(
712-
getAnchor()->getLoc(), *diagnostic,
713-
resolveType(getActual())->reconstituteSugar(/*recursive=*/false),
714-
resolveType(getRequired())->reconstituteSugar(/*recursive=*/false));
709+
emitDiagnostic(anchor->getLoc(), *diagnostic, getFromType(), getToType());
715710
emitNotesForMismatches();
716711
return true;
717712
}

lib/Sema/CSDiagnostics.h

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -367,45 +367,6 @@ class MissingConformanceFailure final : public RequirementFailure {
367367
}
368368
};
369369

370-
/// Diagnostics for mismatched generic arguments e.g
371-
/// ```swift
372-
/// struct F<G> {}
373-
/// let _:F<Int> = F<Bool>()
374-
/// ```
375-
class GenericArgumentsMismatchFailure final : public FailureDiagnostic {
376-
BoundGenericType *Actual;
377-
BoundGenericType *Required;
378-
ArrayRef<unsigned> Mismatches;
379-
380-
public:
381-
GenericArgumentsMismatchFailure(Expr *expr, ConstraintSystem &cs,
382-
BoundGenericType *actual,
383-
BoundGenericType *required,
384-
ArrayRef<unsigned> mismatches,
385-
ConstraintLocator *locator)
386-
: FailureDiagnostic(expr, cs, locator), Actual(actual),
387-
Required(required), Mismatches(mismatches) {}
388-
389-
bool diagnoseAsError() override;
390-
391-
private:
392-
void emitNotesForMismatches() {
393-
for (unsigned position : Mismatches) {
394-
emitNoteForMismatch(position);
395-
}
396-
}
397-
398-
void emitNoteForMismatch(int mismatchPosition);
399-
400-
Optional<Diag<Type, Type>> getDiagnosticFor(ContextualTypePurpose context);
401-
402-
/// The actual type being used.
403-
BoundGenericType *getActual() const { return Actual; }
404-
405-
/// The type needed by the generic requirement.
406-
BoundGenericType *getRequired() const { return Required; }
407-
};
408-
409370
/// Diagnose failures related to same-type generic requirements, e.g.
410371
/// ```swift
411372
/// protocol P {
@@ -723,8 +684,6 @@ class ContextualFailure : public FailureDiagnostic {
723684
Type contextualType);
724685

725686
private:
726-
ContextualTypePurpose getContextualTypePurpose() const { return CTP; }
727-
728687
Type resolve(Type rawType) {
729688
auto type = resolveType(rawType)->getWithoutSpecifierType();
730689
if (auto *BGT = type->getAs<BoundGenericType>()) {
@@ -749,10 +708,55 @@ class ContextualFailure : public FailureDiagnostic {
749708
bool isIntegerToStringIndexConversion() const;
750709

751710
protected:
711+
ContextualTypePurpose getContextualTypePurpose() const { return CTP; }
712+
752713
static Optional<Diag<Type, Type>>
753714
getDiagnosticFor(ContextualTypePurpose context, bool forProtocol);
754715
};
755716

717+
/// Diagnostics for mismatched generic arguments e.g
718+
/// ```swift
719+
/// struct F<G> {}
720+
/// let _:F<Int> = F<Bool>()
721+
/// ```
722+
class GenericArgumentsMismatchFailure final : public ContextualFailure {
723+
ArrayRef<unsigned> Mismatches;
724+
725+
public:
726+
GenericArgumentsMismatchFailure(Expr *expr, ConstraintSystem &cs,
727+
Type actualType, Type requiredType,
728+
ArrayRef<unsigned> mismatches,
729+
ConstraintLocator *locator)
730+
: ContextualFailure(expr, cs, actualType, requiredType, locator),
731+
Mismatches(mismatches) {
732+
assert(actualType->is<BoundGenericType>());
733+
assert(requiredType->is<BoundGenericType>());
734+
}
735+
736+
bool diagnoseAsError() override;
737+
738+
private:
739+
void emitNotesForMismatches() {
740+
for (unsigned position : Mismatches) {
741+
emitNoteForMismatch(position);
742+
}
743+
}
744+
745+
void emitNoteForMismatch(int mismatchPosition);
746+
747+
Optional<Diag<Type, Type>> getDiagnosticFor(ContextualTypePurpose context);
748+
749+
/// The actual type being used.
750+
BoundGenericType *getActual() const {
751+
return getFromType()->castTo<BoundGenericType>();
752+
}
753+
754+
/// The type needed by the generic requirement.
755+
BoundGenericType *getRequired() const {
756+
return getToType()->castTo<BoundGenericType>();
757+
}
758+
};
759+
756760
/// Diagnose failures related to conversion between throwing function type
757761
/// and non-throwing one e.g.
758762
///

lib/Sema/CSFix.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,14 @@ AllowTupleTypeMismatch::create(ConstraintSystem &cs, Type lhs, Type rhs,
247247
}
248248

249249
bool GenericArgumentsMismatch::diagnose(Expr *root, bool asNote) const {
250-
auto failure = GenericArgumentsMismatchFailure(root, getConstraintSystem(),
251-
getActual(), getRequired(),
252-
getMismatches(), getLocator());
250+
auto &cs = getConstraintSystem();
251+
GenericArgumentsMismatchFailure failure(root, cs, getFromType(), getToType(),
252+
getMismatches(), getLocator());
253253
return failure.diagnose(asNote);
254254
}
255255

256256
GenericArgumentsMismatch *GenericArgumentsMismatch::create(
257-
ConstraintSystem &cs, BoundGenericType *actual, BoundGenericType *required,
257+
ConstraintSystem &cs, Type actual, Type required,
258258
llvm::ArrayRef<unsigned> mismatches, ConstraintLocator *locator) {
259259
unsigned size = totalSizeToAlloc<unsigned>(mismatches.size());
260260
void *mem =

lib/Sema/CSFix.h

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -569,22 +569,21 @@ class RemoveAddressOf final : public ContextualMismatch {
569569
/// let _:F<Int> = F<Bool>()
570570
/// ```
571571
class GenericArgumentsMismatch final
572-
: public ConstraintFix,
572+
: public ContextualMismatch,
573573
private llvm::TrailingObjects<GenericArgumentsMismatch, unsigned> {
574574
friend TrailingObjects;
575575

576-
BoundGenericType *Actual;
577-
BoundGenericType *Required;
578-
579576
unsigned NumMismatches;
580577

581578
protected:
582-
GenericArgumentsMismatch(ConstraintSystem &cs, BoundGenericType *actual,
583-
BoundGenericType *required,
579+
GenericArgumentsMismatch(ConstraintSystem &cs, Type actual, Type required,
584580
llvm::ArrayRef<unsigned> mismatches,
585581
ConstraintLocator *locator)
586-
: ConstraintFix(cs, FixKind::GenericArgumentsMismatch, locator),
587-
Actual(actual), Required(required), NumMismatches(mismatches.size()) {
582+
: ContextualMismatch(cs, FixKind::GenericArgumentsMismatch, actual,
583+
required, locator),
584+
NumMismatches(mismatches.size()) {
585+
assert(actual->is<BoundGenericType>());
586+
assert(required->is<BoundGenericType>());
588587
std::uninitialized_copy(mismatches.begin(), mismatches.end(),
589588
getMismatchesBuf().begin());
590589
}
@@ -594,18 +593,14 @@ class GenericArgumentsMismatch final
594593
return "fix generic argument mismatch";
595594
}
596595

597-
BoundGenericType *getActual() const { return Actual; }
598-
BoundGenericType *getRequired() const { return Required; }
599-
600596
ArrayRef<unsigned> getMismatches() const {
601597
return {getTrailingObjects<unsigned>(), NumMismatches};
602598
}
603599

604600
bool diagnose(Expr *root, bool asNote = false) const override;
605601

606-
static GenericArgumentsMismatch *create(ConstraintSystem &cs,
607-
BoundGenericType *actual,
608-
BoundGenericType *required,
602+
static GenericArgumentsMismatch *create(ConstraintSystem &cs, Type actual,
603+
Type required,
609604
llvm::ArrayRef<unsigned> mismatches,
610605
ConstraintLocator *locator);
611606

lib/Sema/CSSimplify.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1771,7 +1771,7 @@ ConstraintSystem::matchDeepEqualityTypes(Type type1, Type type2,
17711771
return result;
17721772

17731773
auto *fix = GenericArgumentsMismatch::create(
1774-
*this, bound1, bound2, mismatches, getConstraintLocator(locator));
1774+
*this, type1, type2, mismatches, getConstraintLocator(locator));
17751775

17761776
if (!recordFix(fix)) {
17771777
// Increase the solution's score for each mismtach this fixes.

test/Parse/pointer_conversion.swift.gyb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func mutablePointerArguments(_ p: UnsafeMutablePointer<Int>,
5454
var ii: [Int] = [0, 1, 2]
5555
var ff: [Float] = [0, 1, 2]
5656
takesMutablePointer(&ii)
57-
takesMutablePointer(&ff) // expected-error{{cannot convert value of type '[Float]' to expected argument type 'UnsafeMutablePointer<Int>'}}
57+
takesMutablePointer(&ff) // expected-error{{cannot convert value of type 'Array<Float>' to expected argument type 'UnsafeMutablePointer<Int>'}}
5858
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('Float' and 'Int') are expected to be equal}}
5959
takesMutablePointer(ii) // expected-error{{cannot convert value of type '[Int]' to expected argument type 'UnsafeMutablePointer<Int>${diag_suffix}'}}
6060
takesMutablePointer(ff) // expected-error{{cannot convert value of type '[Float]' to expected argument type 'UnsafeMutablePointer<Int>${diag_suffix}'}}
@@ -153,10 +153,10 @@ func constPointerArguments(_ p: UnsafeMutablePointer<Int>,
153153
var ii: [Int] = [0, 1, 2]
154154
var ff: [Float] = [0, 1, 2]
155155
takesConstPointer(&ii)
156-
takesConstPointer(&ff) // expected-error{{cannot convert value of type '[Float]' to expected argument type 'UnsafePointer<Int>'}}
156+
takesConstPointer(&ff) // expected-error{{cannot convert value of type 'Array<Float>' to expected argument type 'UnsafePointer<Int>'}}
157157
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('Float' and 'Int') are expected to be equal}}
158158
takesConstPointer(ii)
159-
takesConstPointer(ff) // expected-error{{cannot convert value of type '[Float]' to expected argument type 'UnsafePointer<Int>'}}
159+
takesConstPointer(ff) // expected-error{{cannot convert value of type 'Array<Float>' to expected argument type 'UnsafePointer<Int>'}}
160160
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('Float' and 'Int') are expected to be equal}}
161161
takesConstPointer([0, 1, 2])
162162
// <rdar://problem/22308330> QoI: CSDiags doesn't handle array -> pointer impl conversions well
@@ -341,7 +341,7 @@ func f23202128() {
341341
UMP(&pipe) // expected-error {{cannot pass immutable value as inout argument: 'pipe' is a 'let' constant}}
342342

343343
var pipe2: [Int] = [0, 0]
344-
UMP(&pipe2) // expected-error {{cannot convert value of type '[Int]' to expected argument type 'UnsafeMutablePointer<Int32>'}}
344+
UMP(&pipe2) // expected-error {{cannot convert value of type 'Array<Int>' to expected argument type 'UnsafeMutablePointer<Int32>'}}
345345
// expected-note@-1 {{arguments to generic parameter 'Pointee' ('Int' and 'Int32') are expected to be equal}}
346346

347347

test/decl/typealias/generic.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@ let _: GenericClass<Int>.TA = GenericClass<Int>.TA<Float>(a: 1, b: 4.0)
278278
let _: GenericClass<Int>.TA<Float> = GenericClass.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'MyType<Double, Int>' to specified type 'GenericClass<Int>.TA<Float>' (aka 'MyType<Int, Float>')}}
279279
let _: GenericClass<Int>.TA<Float> = GenericClass.TA(a: 1, b: 4.0)
280280

281-
let _: GenericClass<Int>.TA<Float> = GenericClass.TA<Float>(a: 4.0, b: 1) // expected-error {{cannot assign value of type 'MyType<Float, Float>' to type 'MyType<Int, Float>'}}
282-
let _: GenericClass<Int>.TA<Float> = GenericClass.TA<Float>(a: 1, b: 4.0) // expected-error {{cannot assign value of type 'MyType<Float, Float>' to type 'MyType<Int, Float>'}}
281+
let _: GenericClass<Int>.TA<Float> = GenericClass.TA<Float>(a: 4.0, b: 1) // expected-error {{cannot assign value of type 'MyType<Float, Float>' to type 'GenericClass<Int>.TA<Float>' (aka 'MyType<Int, Float>')}}
282+
let _: GenericClass<Int>.TA<Float> = GenericClass.TA<Float>(a: 1, b: 4.0) // expected-error {{cannot assign value of type 'MyType<Float, Float>' to type 'GenericClass<Int>.TA<Float>' (aka 'MyType<Int, Float>')}}
283283

284284
let _: GenericClass<Int>.TA<Float> = GenericClass<Int>.TA(a: 4.0, b: 1) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
285285
let _: GenericClass<Int>.TA<Float> = GenericClass<Int>.TA(a: 1, b: 4.0)

test/expr/cast/dictionary_downcast.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ if let _ = dictCC as? Dictionary<D, C> { }
3232
if let _ = dictCC as? Dictionary<D, D> { }
3333

3434
// Test dictionary downcasts to unrelated types.
35-
dictCC as Dictionary<D, U> // expected-error{{cannot convert value of type '[C : C]' to type '[D : U]' in coercion}}
35+
dictCC as Dictionary<D, U> // expected-error{{cannot convert value of type '[C : C]' to type 'Dictionary<D, U>' in coercion}}
3636
// expected-note@-1 {{arguments to generic parameter 'Key' ('C' and 'D') are expected to be equal}}
3737
// expected-note@-2 {{arguments to generic parameter 'Value' ('C' and 'U') are expected to be equal}}
38-
dictCC as Dictionary<U, D> // expected-error{{cannot convert value of type '[C : C]' to type '[U : D]' in coercion}}
38+
dictCC as Dictionary<U, D> // expected-error{{cannot convert value of type '[C : C]' to type 'Dictionary<U, D>' in coercion}}
3939
// expected-note@-1 {{arguments to generic parameter 'Key' ('C' and 'U') are expected to be equal}}
4040
// expected-note@-2 {{arguments to generic parameter 'Value' ('C' and 'D') are expected to be equal}}
41-
dictCC as Dictionary<U, U> // expected-error{{cannot convert value of type '[C : C]' to type '[U : U]' in coercion}}
41+
dictCC as Dictionary<U, U> // expected-error{{cannot convert value of type '[C : C]' to type 'Dictionary<U, U>' in coercion}}
4242
// expected-note@-1 {{arguments to generic parameter 'Key' ('C' and 'U') are expected to be equal}}
4343
// expected-note@-2 {{arguments to generic parameter 'Value' ('C' and 'U') are expected to be equal}}
4444

test/expr/unary/keypath/salvage-with-other-type-errors.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// to diagnose other errors in adjacent exprs.
55

66
struct P<T: K> { }
7-
// expected-note@-1 {{arguments to generic parameter 'T' ('String' and '_') are expected to be equal}}
7+
// expected-note@-1 {{arguments to generic parameter 'T' ('String' and 'T') are expected to be equal}}
88

99
struct S {
1010
init<B>(_ a: P<B>) {
@@ -28,7 +28,7 @@ struct A {
2828
}
2929

3030
extension A: K {
31-
static let j = S(\A.id + "id") // expected-error {{cannot convert value of type 'P<String>' to expected argument type 'P<_>'}}
31+
static let j = S(\A.id + "id") // expected-error {{cannot convert value of type 'P<String>' to expected argument type 'P<T>'}}
3232
}
3333

3434
// SR-5034

0 commit comments

Comments
 (0)