@@ -6488,39 +6488,112 @@ void ConstraintSystem::diagnoseFailureForExpr(Expr *expr) {
6488
6488
diagnosis.diagnoseAmbiguity (expr);
6489
6489
}
6490
6490
6491
+ static bool hasArchetype (const GenericTypeDecl *generic,
6492
+ const ArchetypeType *archetype) {
6493
+ return std::any_of (generic->getInnermostGenericParamTypes ().begin (),
6494
+ generic->getInnermostGenericParamTypes ().end (),
6495
+ [archetype](const GenericTypeParamType *genericParamTy) {
6496
+ return genericParamTy->getDecl ()->getArchetype () == archetype;
6497
+ });
6498
+ }
6499
+
6491
6500
static void noteArchetypeSource (const TypeLoc &loc, ArchetypeType *archetype,
6492
- TypeChecker &tc) {
6493
- GenericTypeDecl *FoundDecl = nullptr ;
6494
-
6501
+ ConstraintSystem &cs) {
6502
+ const GenericTypeDecl *FoundDecl = nullptr ;
6503
+ const ComponentIdentTypeRepr *FoundGenericTypeBase = nullptr ;
6504
+
6495
6505
// Walk the TypeRepr to find the type in question.
6496
6506
if (auto typerepr = loc.getTypeRepr ()) {
6497
6507
struct FindGenericTypeDecl : public ASTWalker {
6498
- GenericTypeDecl *&FoundDecl;
6499
- FindGenericTypeDecl (GenericTypeDecl *&FoundDecl) : FoundDecl(FoundDecl) {
6500
- }
6508
+ const GenericTypeDecl *FoundDecl = nullptr ;
6509
+ const ComponentIdentTypeRepr *FoundGenericTypeBase = nullptr ;
6510
+ const ArchetypeType *Archetype;
6511
+
6512
+ FindGenericTypeDecl (const ArchetypeType *Archetype)
6513
+ : Archetype(Archetype) {}
6501
6514
6502
6515
bool walkToTypeReprPre (TypeRepr *T) override {
6503
6516
// If we already emitted the note, we're done.
6504
6517
if (FoundDecl) return false ;
6505
6518
6506
- if (auto ident = dyn_cast<ComponentIdentTypeRepr>(T))
6507
- FoundDecl = dyn_cast_or_null<GenericTypeDecl>(ident->getBoundDecl ());
6519
+ if (auto ident = dyn_cast<ComponentIdentTypeRepr>(T)) {
6520
+ auto *generic =
6521
+ dyn_cast_or_null<GenericTypeDecl>(ident->getBoundDecl ());
6522
+ if (hasArchetype (generic, Archetype)) {
6523
+ FoundDecl = generic;
6524
+ FoundGenericTypeBase = ident;
6525
+ return false ;
6526
+ }
6527
+ }
6508
6528
// Keep walking.
6509
6529
return true ;
6510
6530
}
6511
- } findGenericTypeDecl (FoundDecl );
6512
-
6531
+ } findGenericTypeDecl (archetype );
6532
+
6513
6533
typerepr->walk (findGenericTypeDecl);
6534
+ FoundDecl = findGenericTypeDecl.FoundDecl ;
6535
+ FoundGenericTypeBase = findGenericTypeDecl.FoundGenericTypeBase ;
6514
6536
}
6515
-
6537
+
6516
6538
// If we didn't find the type in the TypeRepr, fall back to the type in the
6517
6539
// type checked expression.
6518
- if (!FoundDecl)
6519
- FoundDecl = loc.getType ()->getAnyGeneric ();
6520
-
6521
- if (FoundDecl)
6522
- tc.diagnose (FoundDecl, diag::archetype_declared_in_type, archetype,
6523
- FoundDecl->getDeclaredType ());
6540
+ if (!FoundDecl) {
6541
+ if (const GenericTypeDecl *generic = loc.getType ()->getAnyGeneric ())
6542
+ if (hasArchetype (generic, archetype))
6543
+ FoundDecl = generic;
6544
+ }
6545
+
6546
+ auto &tc = cs.getTypeChecker ();
6547
+ if (FoundDecl) {
6548
+ tc.diagnose (FoundDecl, diag::archetype_declared_in_type,
6549
+ archetype, FoundDecl->getDeclaredType ());
6550
+ }
6551
+
6552
+ if (FoundGenericTypeBase && !isa<GenericIdentTypeRepr>(FoundGenericTypeBase)){
6553
+ assert (FoundDecl);
6554
+
6555
+ // If we can, prefer using any types already fixed by the constraint system.
6556
+ // This lets us produce fixes like `Pair<Int, Any>` instead of defaulting to
6557
+ // `Pair<Any, Any>`.
6558
+ // Right now we only handle this when the type that's at fault is the
6559
+ // top-level type passed to this function.
6560
+ ArrayRef<Type> genericArgs;
6561
+ if (auto *boundGenericTy = loc.getType ()->getAs <BoundGenericType>()) {
6562
+ if (boundGenericTy->getDecl () == FoundDecl)
6563
+ genericArgs = boundGenericTy->getGenericArgs ();
6564
+ }
6565
+
6566
+ auto getPreferredType =
6567
+ [&](const GenericTypeParamDecl *genericParam) -> Type {
6568
+ // If we were able to get the generic arguments (i.e. the types used at
6569
+ // FoundDecl's use site), we can prefer those...
6570
+ if (genericArgs.empty ())
6571
+ return Type ();
6572
+
6573
+ Type preferred = genericArgs[genericParam->getIndex ()];
6574
+ if (!preferred || preferred->is <ErrorType>())
6575
+ return Type ();
6576
+
6577
+ // ...but only if they were actually resolved by the constraint system
6578
+ // despite the failure.
6579
+ TypeVariableType *unused;
6580
+ Type maybeFixedType = cs.getFixedTypeRecursive (preferred, unused,
6581
+ /* wantRValue*/ true );
6582
+ if (maybeFixedType->hasTypeVariable () ||
6583
+ maybeFixedType->hasUnresolvedType ()) {
6584
+ return Type ();
6585
+ }
6586
+ return maybeFixedType;
6587
+ };
6588
+
6589
+ SmallString<64 > genericParamBuf;
6590
+ if (tc.getDefaultGenericArgumentsString (genericParamBuf, FoundDecl,
6591
+ getPreferredType)) {
6592
+ tc.diagnose (FoundGenericTypeBase->getLoc (),
6593
+ diag::unbound_generic_parameter_explicit_fix)
6594
+ .fixItInsertAfter (FoundGenericTypeBase->getEndLoc (), genericParamBuf);
6595
+ }
6596
+ }
6524
6597
}
6525
6598
6526
6599
@@ -6636,11 +6709,7 @@ void FailureDiagnosis::diagnoseUnboundArchetype(ArchetypeType *archetype,
6636
6709
.highlight (ECE->getCastTypeLoc ().getSourceRange ());
6637
6710
6638
6711
// Emit a note specifying where this came from, if we can find it.
6639
- noteArchetypeSource (ECE->getCastTypeLoc (), archetype, tc);
6640
- if (auto *ND = ECE->getCastTypeLoc ().getType ()
6641
- ->getNominalOrBoundGenericNominal ())
6642
- tc.diagnose (ND, diag::archetype_declared_in_type, archetype,
6643
- ND->getDeclaredType ());
6712
+ noteArchetypeSource (ECE->getCastTypeLoc (), archetype, *CS);
6644
6713
return ;
6645
6714
}
6646
6715
@@ -6670,7 +6739,7 @@ void FailureDiagnosis::diagnoseUnboundArchetype(ArchetypeType *archetype,
6670
6739
6671
6740
if (auto TE = dyn_cast<TypeExpr>(anchor)) {
6672
6741
// Emit a note specifying where this came from, if we can find it.
6673
- noteArchetypeSource (TE->getTypeLoc (), archetype, tc );
6742
+ noteArchetypeSource (TE->getTypeLoc (), archetype, *CS );
6674
6743
return ;
6675
6744
}
6676
6745
0 commit comments