Skip to content

Commit 0dc1dc2

Browse files
committed
---
yaml --- r: 348118 b: refs/heads/master c: 0f98cd1 h: refs/heads/master
1 parent 59110ae commit 0dc1dc2

23 files changed

+427
-63
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: e604934626e3a3e3070d960d606c7756cb99e386
2+
refs/heads/master: 0f98cd18edb8f91687bf68f85162475006f6dce9
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,13 @@ ERROR(cannot_convert_closure_result_protocol,none,
393393
(Type, Type))
394394
ERROR(cannot_convert_closure_result_nil,none,
395395
"'nil' is not compatible with closure result type %0", (Type))
396+
ERROR(cannot_convert_parent_type,none,
397+
"cannot convert parent type %0 to expected type %1",
398+
(Type, Type))
399+
400+
NOTE(generic_argument_mismatch,none,
401+
"arguments to generic parameter %0 (%1 and %2) are expected to be equal",
402+
(Identifier, Type, Type))
396403

397404
ERROR(destructor_not_accessible,none,
398405
"deinitializers cannot be accessed", ())

trunk/lib/Sema/CSDiagnostics.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,117 @@ bool MissingConformanceFailure::diagnoseAsError() {
384384
return RequirementFailure::diagnoseAsError();
385385
}
386386

387+
Optional<Diag<Type, Type>> GenericArgumentsMismatchFailure::getDiagnosticFor(
388+
ContextualTypePurpose context) {
389+
switch (context) {
390+
case CTP_Initialization:
391+
case CTP_AssignSource:
392+
return diag::cannot_convert_assign;
393+
case CTP_ReturnStmt:
394+
case CTP_ReturnSingleExpr:
395+
return diag::cannot_convert_to_return_type;
396+
case CTP_DefaultParameter:
397+
return diag::cannot_convert_default_arg_value;
398+
case CTP_YieldByValue:
399+
return diag::cannot_convert_yield_value;
400+
case CTP_CallArgument:
401+
return diag::cannot_convert_argument_value;
402+
case CTP_ClosureResult:
403+
return diag::cannot_convert_closure_result;
404+
case CTP_ArrayElement:
405+
return diag::cannot_convert_array_element;
406+
// TODO(diagnostics): Make dictionary related diagnostics take prescedence
407+
// over CSDiag. Currently these won't ever be produced.
408+
case CTP_DictionaryKey:
409+
return diag::cannot_convert_dict_key;
410+
case CTP_DictionaryValue:
411+
return diag::cannot_convert_dict_value;
412+
case CTP_CoerceOperand:
413+
return diag::cannot_convert_coerce;
414+
case CTP_SubscriptAssignSource:
415+
return diag::cannot_convert_subscript_assign;
416+
417+
case CTP_ThrowStmt:
418+
case CTP_Unused:
419+
case CTP_CannotFail:
420+
case CTP_YieldByReference:
421+
case CTP_CalleeResult:
422+
case CTP_EnumCaseRawValue:
423+
break;
424+
}
425+
return None;
426+
}
427+
428+
void GenericArgumentsMismatchFailure::emitNoteForMismatch(int position) {
429+
auto genericTypeDecl = getActual()->getCanonicalType()->getAnyGeneric();
430+
auto param = genericTypeDecl->getGenericParams()->getParams()[position];
431+
432+
auto lhs = resolveType(getActual()->getGenericArgs()[position])
433+
->reconstituteSugar(/*recursive=*/false);
434+
auto rhs = resolveType(getRequired()->getGenericArgs()[position])
435+
->reconstituteSugar(/*recursive=*/false);
436+
437+
auto noteLocation = param->getLoc();
438+
439+
if (!noteLocation.isValid()) {
440+
noteLocation = getAnchor()->getLoc();
441+
}
442+
443+
emitDiagnostic(noteLocation, diag::generic_argument_mismatch,
444+
param->getName(), lhs, rhs);
445+
}
446+
447+
bool GenericArgumentsMismatchFailure::diagnoseAsError() {
448+
auto *anchor = getAnchor();
449+
auto path = getLocator()->getPath();
450+
451+
Optional<Diag<Type, Type>> diagnostic;
452+
if (path.empty()) {
453+
assert(isa<AssignExpr>(anchor));
454+
diagnostic = getDiagnosticFor(CTP_AssignSource);
455+
} else {
456+
const auto &last = path.back();
457+
switch (last.getKind()) {
458+
case ConstraintLocator::ContextualType: {
459+
auto purpose = getConstraintSystem().getContextualTypePurpose();
460+
assert(purpose != CTP_Unused);
461+
diagnostic = getDiagnosticFor(purpose);
462+
break;
463+
}
464+
465+
case ConstraintLocator::AutoclosureResult:
466+
case ConstraintLocator::ApplyArgToParam:
467+
case ConstraintLocator::ApplyArgument: {
468+
diagnostic = diag::cannot_convert_argument_value;
469+
break;
470+
}
471+
472+
case ConstraintLocator::ParentType: {
473+
diagnostic = diag::cannot_convert_parent_type;
474+
break;
475+
}
476+
477+
case ConstraintLocator::ClosureResult: {
478+
diagnostic = diag::cannot_convert_closure_result;
479+
break;
480+
}
481+
482+
default:
483+
break;
484+
}
485+
}
486+
487+
if (!diagnostic)
488+
return false;
489+
490+
emitDiagnostic(
491+
getAnchor()->getLoc(), *diagnostic,
492+
resolveType(getActual())->reconstituteSugar(/*recursive=*/false),
493+
resolveType(getRequired())->reconstituteSugar(/*recursive=*/false));
494+
emitNotesForMismatches();
495+
return true;
496+
}
497+
387498
bool LabelingFailure::diagnoseAsError() {
388499
auto &cs = getConstraintSystem();
389500
auto *anchor = getRawAnchor();

trunk/lib/Sema/CSDiagnostics.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class FailureDiagnostic {
6969
bool diagnose(bool asNote = false);
7070

7171
/// Try to produce an error diagnostic for the problem at hand.
72+
///
73+
/// \returns true If anything was diagnosed, false otherwise.
7274
virtual bool diagnoseAsError() = 0;
7375

7476
/// Instead of producing an error diagnostic, attempt to
@@ -359,6 +361,45 @@ class MissingConformanceFailure final : public RequirementFailure {
359361
}
360362
};
361363

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

trunk/lib/Sema/CSFix.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,23 @@ ContextualMismatch *ContextualMismatch::create(ConstraintSystem &cs, Type lhs,
228228
return new (cs.getAllocator()) ContextualMismatch(cs, lhs, rhs, locator);
229229
}
230230

231+
bool GenericArgumentsMismatch::diagnose(Expr *root, bool asNote) const {
232+
auto failure = GenericArgumentsMismatchFailure(root, getConstraintSystem(),
233+
getActual(), getRequired(),
234+
getMismatches(), getLocator());
235+
return failure.diagnose(asNote);
236+
}
237+
238+
GenericArgumentsMismatch *GenericArgumentsMismatch::create(
239+
ConstraintSystem &cs, BoundGenericType *actual, BoundGenericType *required,
240+
llvm::ArrayRef<unsigned> mismatches, ConstraintLocator *locator) {
241+
unsigned size = totalSizeToAlloc<unsigned>(mismatches.size());
242+
void *mem =
243+
cs.getAllocator().Allocate(size, alignof(GenericArgumentsMismatch));
244+
return new (mem)
245+
GenericArgumentsMismatch(cs, actual, required, mismatches, locator);
246+
}
247+
231248
bool AutoClosureForwarding::diagnose(Expr *root, bool asNote) const {
232249
auto failure =
233250
AutoClosureForwardingFailure(getConstraintSystem(), getLocator());

trunk/lib/Sema/CSFix.h

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ enum class FixKind : uint8_t {
8888
/// like the types are aligned.
8989
ContextualMismatch,
9090

91+
/// Fix up the generic arguments of two types so they match each other.
92+
GenericArgumentsMismatch,
93+
9194
/// Fix up @autoclosure argument to the @autoclosure parameter,
9295
/// to for a call to be able to foward it properly, since
9396
/// @autoclosure conversions are unsupported starting from
@@ -164,7 +167,8 @@ enum class FixKind : uint8_t {
164167
/// associated with single declaration.
165168
ExplicitlySpecifyGenericArguments,
166169

167-
/// Skip any unhandled constructs that occur within a closure argument that matches up with a
170+
/// Skip any unhandled constructs that occur within a closure argument that
171+
/// matches up with a
168172
/// parameter that has a function builder.
169173
SkipUnhandledConstructInFunctionBuilder,
170174
};
@@ -488,6 +492,60 @@ class ContextualMismatch : public ConstraintFix {
488492
ConstraintLocator *locator);
489493
};
490494

495+
/// Detect situations where two type's generic arguments must
496+
/// match but are not convertible e.g.
497+
///
498+
/// ```swift
499+
/// struct F<G> {}
500+
/// let _:F<Int> = F<Bool>()
501+
/// ```
502+
class GenericArgumentsMismatch final
503+
: public ConstraintFix,
504+
private llvm::TrailingObjects<GenericArgumentsMismatch, unsigned> {
505+
friend TrailingObjects;
506+
507+
BoundGenericType *Actual;
508+
BoundGenericType *Required;
509+
510+
unsigned NumMismatches;
511+
512+
protected:
513+
GenericArgumentsMismatch(ConstraintSystem &cs, BoundGenericType *actual,
514+
BoundGenericType *required,
515+
llvm::ArrayRef<unsigned> mismatches,
516+
ConstraintLocator *locator)
517+
: ConstraintFix(cs, FixKind::GenericArgumentsMismatch, locator),
518+
Actual(actual), Required(required), NumMismatches(mismatches.size()) {
519+
std::uninitialized_copy(mismatches.begin(), mismatches.end(),
520+
getMismatchesBuf().begin());
521+
}
522+
523+
public:
524+
std::string getName() const override {
525+
return "fix generic argument mismatch";
526+
}
527+
528+
BoundGenericType *getActual() const { return Actual; }
529+
BoundGenericType *getRequired() const { return Required; }
530+
531+
ArrayRef<unsigned> getMismatches() const {
532+
return {getTrailingObjects<unsigned>(), NumMismatches};
533+
}
534+
535+
bool diagnose(Expr *root, bool asNote = false) const override;
536+
537+
static GenericArgumentsMismatch *create(ConstraintSystem &cs,
538+
BoundGenericType *actual,
539+
BoundGenericType *required,
540+
llvm::ArrayRef<unsigned> mismatches,
541+
ConstraintLocator *locator);
542+
543+
private:
544+
MutableArrayRef<unsigned> getMismatchesBuf() {
545+
return {getTrailingObjects<unsigned>(), NumMismatches};
546+
}
547+
};
548+
491549
/// Detect situations where key path doesn't have capability required
492550
/// by the context e.g. read-only vs. writable, or either root or value
493551
/// types are incorrect e.g.

0 commit comments

Comments
 (0)