@@ -6478,39 +6478,112 @@ void ConstraintSystem::diagnoseFailureForExpr(Expr *expr) {
6478
6478
diagnosis.diagnoseAmbiguity (expr);
6479
6479
}
6480
6480
6481
+ static bool hasArchetype (const GenericTypeDecl *generic,
6482
+ const ArchetypeType *archetype) {
6483
+ return std::any_of (generic->getInnermostGenericParamTypes ().begin (),
6484
+ generic->getInnermostGenericParamTypes ().end (),
6485
+ [archetype](const GenericTypeParamType *genericParamTy) {
6486
+ return genericParamTy->getDecl ()->getArchetype () == archetype;
6487
+ });
6488
+ }
6489
+
6481
6490
static void noteArchetypeSource (const TypeLoc &loc, ArchetypeType *archetype,
6482
- TypeChecker &tc) {
6483
- GenericTypeDecl *FoundDecl = nullptr ;
6484
-
6491
+ ConstraintSystem &cs) {
6492
+ const GenericTypeDecl *FoundDecl = nullptr ;
6493
+ const ComponentIdentTypeRepr *FoundGenericTypeBase = nullptr ;
6494
+
6485
6495
// Walk the TypeRepr to find the type in question.
6486
6496
if (auto typerepr = loc.getTypeRepr ()) {
6487
6497
struct FindGenericTypeDecl : public ASTWalker {
6488
- GenericTypeDecl *&FoundDecl;
6489
- FindGenericTypeDecl (GenericTypeDecl *&FoundDecl) : FoundDecl(FoundDecl) {
6490
- }
6498
+ const GenericTypeDecl *FoundDecl = nullptr ;
6499
+ const ComponentIdentTypeRepr *FoundGenericTypeBase = nullptr ;
6500
+ const ArchetypeType *Archetype;
6501
+
6502
+ FindGenericTypeDecl (const ArchetypeType *Archetype)
6503
+ : Archetype(Archetype) {}
6491
6504
6492
6505
bool walkToTypeReprPre (TypeRepr *T) override {
6493
6506
// If we already emitted the note, we're done.
6494
6507
if (FoundDecl) return false ;
6495
6508
6496
- if (auto ident = dyn_cast<ComponentIdentTypeRepr>(T))
6497
- FoundDecl = dyn_cast_or_null<GenericTypeDecl>(ident->getBoundDecl ());
6509
+ if (auto ident = dyn_cast<ComponentIdentTypeRepr>(T)) {
6510
+ auto *generic =
6511
+ dyn_cast_or_null<GenericTypeDecl>(ident->getBoundDecl ());
6512
+ if (hasArchetype (generic, Archetype)) {
6513
+ FoundDecl = generic;
6514
+ FoundGenericTypeBase = ident;
6515
+ return false ;
6516
+ }
6517
+ }
6498
6518
// Keep walking.
6499
6519
return true ;
6500
6520
}
6501
- } findGenericTypeDecl (FoundDecl );
6502
-
6521
+ } findGenericTypeDecl (archetype );
6522
+
6503
6523
typerepr->walk (findGenericTypeDecl);
6524
+ FoundDecl = findGenericTypeDecl.FoundDecl ;
6525
+ FoundGenericTypeBase = findGenericTypeDecl.FoundGenericTypeBase ;
6504
6526
}
6505
-
6527
+
6506
6528
// If we didn't find the type in the TypeRepr, fall back to the type in the
6507
6529
// type checked expression.
6508
- if (!FoundDecl)
6509
- FoundDecl = loc.getType ()->getAnyGeneric ();
6510
-
6511
- if (FoundDecl)
6512
- tc.diagnose (FoundDecl, diag::archetype_declared_in_type, archetype,
6513
- FoundDecl->getDeclaredType ());
6530
+ if (!FoundDecl) {
6531
+ if (const GenericTypeDecl *generic = loc.getType ()->getAnyGeneric ())
6532
+ if (hasArchetype (generic, archetype))
6533
+ FoundDecl = generic;
6534
+ }
6535
+
6536
+ auto &tc = cs.getTypeChecker ();
6537
+ if (FoundDecl) {
6538
+ tc.diagnose (FoundDecl, diag::archetype_declared_in_type,
6539
+ archetype, FoundDecl->getDeclaredType ());
6540
+ }
6541
+
6542
+ if (FoundGenericTypeBase && !isa<GenericIdentTypeRepr>(FoundGenericTypeBase)){
6543
+ assert (FoundDecl);
6544
+
6545
+ // If we can, prefer using any types already fixed by the constraint system.
6546
+ // This lets us produce fixes like `Pair<Int, Any>` instead of defaulting to
6547
+ // `Pair<Any, Any>`.
6548
+ // Right now we only handle this when the type that's at fault is the
6549
+ // top-level type passed to this function.
6550
+ ArrayRef<Type> genericArgs;
6551
+ if (auto *boundGenericTy = loc.getType ()->getAs <BoundGenericType>()) {
6552
+ if (boundGenericTy->getDecl () == FoundDecl)
6553
+ genericArgs = boundGenericTy->getGenericArgs ();
6554
+ }
6555
+
6556
+ auto getPreferredType =
6557
+ [&](const GenericTypeParamDecl *genericParam) -> Type {
6558
+ // If we were able to get the generic arguments (i.e. the types used at
6559
+ // FoundDecl's use site), we can prefer those...
6560
+ if (genericArgs.empty ())
6561
+ return Type ();
6562
+
6563
+ Type preferred = genericArgs[genericParam->getIndex ()];
6564
+ if (!preferred || preferred->is <ErrorType>())
6565
+ return Type ();
6566
+
6567
+ // ...but only if they were actually resolved by the constraint system
6568
+ // despite the failure.
6569
+ TypeVariableType *unused;
6570
+ Type maybeFixedType = cs.getFixedTypeRecursive (preferred, unused,
6571
+ /* wantRValue*/ true );
6572
+ if (maybeFixedType->hasTypeVariable () ||
6573
+ maybeFixedType->hasUnresolvedType ()) {
6574
+ return Type ();
6575
+ }
6576
+ return maybeFixedType;
6577
+ };
6578
+
6579
+ SmallString<64 > genericParamBuf;
6580
+ if (tc.getDefaultGenericArgumentsString (genericParamBuf, FoundDecl,
6581
+ getPreferredType)) {
6582
+ tc.diagnose (FoundGenericTypeBase->getLoc (),
6583
+ diag::unbound_generic_parameter_explicit_fix)
6584
+ .fixItInsertAfter (FoundGenericTypeBase->getEndLoc (), genericParamBuf);
6585
+ }
6586
+ }
6514
6587
}
6515
6588
6516
6589
@@ -6626,11 +6699,7 @@ void FailureDiagnosis::diagnoseUnboundArchetype(ArchetypeType *archetype,
6626
6699
.highlight (ECE->getCastTypeLoc ().getSourceRange ());
6627
6700
6628
6701
// Emit a note specifying where this came from, if we can find it.
6629
- noteArchetypeSource (ECE->getCastTypeLoc (), archetype, tc);
6630
- if (auto *ND = ECE->getCastTypeLoc ().getType ()
6631
- ->getNominalOrBoundGenericNominal ())
6632
- tc.diagnose (ND, diag::archetype_declared_in_type, archetype,
6633
- ND->getDeclaredType ());
6702
+ noteArchetypeSource (ECE->getCastTypeLoc (), archetype, *CS);
6634
6703
return ;
6635
6704
}
6636
6705
@@ -6660,7 +6729,7 @@ void FailureDiagnosis::diagnoseUnboundArchetype(ArchetypeType *archetype,
6660
6729
6661
6730
if (auto TE = dyn_cast<TypeExpr>(anchor)) {
6662
6731
// Emit a note specifying where this came from, if we can find it.
6663
- noteArchetypeSource (TE->getTypeLoc (), archetype, tc );
6732
+ noteArchetypeSource (TE->getTypeLoc (), archetype, *CS );
6664
6733
return ;
6665
6734
}
6666
6735
0 commit comments