Skip to content

Commit 0abb019

Browse files
authored
Merge pull request #18168 from slavapestov/fix-extension-binding
Sema: Iterative worklist algorithm for extension binding
2 parents 1d68b11 + f4df20b commit 0abb019

File tree

5 files changed

+318
-74
lines changed

5 files changed

+318
-74
lines changed

lib/Sema/TypeCheckPattern.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -458,13 +458,15 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
458458
SmallVector<ComponentIdentTypeRepr *, 2> components;
459459
if (!ExprToIdentTypeRepr(components, TC.Context).visit(ude->getBase()))
460460
return nullptr;
461-
461+
462+
TypeResolutionOptions options;
463+
options |= TypeResolutionFlags::AllowUnboundGenerics;
464+
options |= TypeResolutionFlags::SilenceErrors;
465+
462466
auto *repr = IdentTypeRepr::create(TC.Context, components);
463467

464468
// See if the repr resolves to a type.
465-
Type ty = TC.resolveIdentifierType(DC, repr,
466-
TypeResolutionFlags::AllowUnboundGenerics,
467-
/*diagnoseErrors*/false, &resolver);
469+
Type ty = TC.resolveIdentifierType(DC, repr, options, &resolver);
468470

469471
auto *enumDecl = dyn_cast_or_null<EnumDecl>(ty->getAnyNominal());
470472
if (!enumDecl)
@@ -576,13 +578,17 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
576578
auto *enumDecl = referencedElement->getParentEnum();
577579
loc = TypeLoc::withoutLoc(enumDecl->getDeclaredTypeInContext());
578580
} else {
581+
TypeResolutionOptions options;
582+
options |= TypeResolutionFlags::AllowUnboundGenerics;
583+
options |= TypeResolutionFlags::SilenceErrors;
584+
579585
// Otherwise, see whether we had an enum type as the penultimate
580586
// component, and look up an element inside it.
581587
auto *prefixRepr = IdentTypeRepr::create(TC.Context, components);
588+
582589
// See first if the entire repr resolves to a type.
583-
Type enumTy = TC.resolveIdentifierType(DC, prefixRepr,
584-
TypeResolutionFlags::AllowUnboundGenerics,
585-
/*diagnoseErrors*/false, &resolver);
590+
Type enumTy = TC.resolveIdentifierType(DC, prefixRepr, options,
591+
&resolver);
586592
if (!dyn_cast_or_null<EnumDecl>(enumTy->getAnyNominal()))
587593
return nullptr;
588594

lib/Sema/TypeCheckType.cpp

Lines changed: 46 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -357,19 +357,21 @@ Type TypeChecker::applyGenericArguments(Type type,
357357

358358
// We must either have an unbound generic type, or a generic type alias.
359359
if (!type->is<UnboundGenericType>()) {
360-
auto diag = diagnose(loc, diag::not_a_generic_type, type);
360+
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
361+
auto diag = diagnose(loc, diag::not_a_generic_type, type);
362+
363+
// Don't add fixit on module type; that isn't the right type regardless
364+
// of whether it had generic arguments.
365+
if (!type->is<ModuleType>()) {
366+
// When turning a SourceRange into CharSourceRange the closing angle
367+
// brackets on nested generics are lexed as one token.
368+
SourceRange angles = generic->getAngleBrackets();
369+
diag.fixItRemoveChars(angles.Start,
370+
angles.End.getAdvancedLocOrInvalid(1));
371+
}
361372

362-
// Don't add fixit on module type; that isn't the right type regardless
363-
// of whether it had generic arguments.
364-
if (!type->is<ModuleType>()) {
365-
// When turning a SourceRange into CharSourceRange the closing angle
366-
// brackets on nested generics are lexed as one token.
367-
SourceRange angles = generic->getAngleBrackets();
368-
diag.fixItRemoveChars(angles.Start,
369-
angles.End.getAdvancedLocOrInvalid(1));
373+
generic->setInvalid();
370374
}
371-
372-
generic->setInvalid();
373375
return type;
374376
}
375377

@@ -383,12 +385,14 @@ Type TypeChecker::applyGenericArguments(Type type,
383385
auto genericArgs = generic->getGenericArgs();
384386
auto genericParams = genericDecl->getGenericParams();
385387
if (genericParams->size() != genericArgs.size()) {
386-
diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(),
387-
genericParams->size(), genericArgs.size(),
388-
genericArgs.size() < genericParams->size())
389-
.highlight(generic->getAngleBrackets());
390-
diagnose(decl, diag::kind_identifier_declared_here,
391-
DescriptiveDeclKind::GenericType, decl->getName());
388+
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
389+
diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(),
390+
genericParams->size(), genericArgs.size(),
391+
genericArgs.size() < genericParams->size())
392+
.highlight(generic->getAngleBrackets());
393+
diagnose(decl, diag::kind_identifier_declared_here,
394+
DescriptiveDeclKind::GenericType, decl->getName());
395+
}
392396
return ErrorType::get(Context);
393397
}
394398

@@ -412,9 +416,11 @@ Type TypeChecker::applyGenericArguments(Type type,
412416

413417
// Cannot extend a bound generic type.
414418
if (options.contains(TypeResolutionFlags::ExtensionBinding)) {
415-
diagnose(loc, diag::extension_specialization,
416-
genericDecl->getName())
417-
.highlight(generic->getSourceRange());
419+
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
420+
diagnose(loc, diag::extension_specialization,
421+
genericDecl->getName())
422+
.highlight(generic->getSourceRange());
423+
}
418424
return ErrorType::get(Context);
419425
}
420426

@@ -901,14 +907,12 @@ static Type
901907
resolveTopLevelIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
902908
ComponentIdentTypeRepr *comp,
903909
TypeResolutionOptions options,
904-
bool diagnoseErrors,
905910
GenericTypeResolver *resolver);
906911

907912
static Type
908913
resolveGenericSignatureComponent(TypeChecker &TC, DeclContext *DC,
909914
ComponentIdentTypeRepr *comp,
910915
TypeResolutionOptions options,
911-
bool diagnoseErrors,
912916
GenericTypeResolver *resolver) {
913917
if (!DC->isInnermostContextGeneric())
914918
return Type();
@@ -926,8 +930,7 @@ resolveGenericSignatureComponent(TypeChecker &TC, DeclContext *DC,
926930
return Type();
927931

928932
comp->setValue(*matchingParam, nullptr);
929-
return resolveTopLevelIdentTypeComponent(TC, DC, comp, options,
930-
diagnoseErrors, resolver);
933+
return resolveTopLevelIdentTypeComponent(TC, DC, comp, options, resolver);
931934
}
932935

933936
// If we are inside an extension of a nested type, we have to visit
@@ -944,8 +947,7 @@ resolveGenericSignatureComponent(TypeChecker &TC, DeclContext *DC,
944947

945948
if (matchingParam != outerParams->end()) {
946949
comp->setValue(*matchingParam, nullptr);
947-
return resolveTopLevelIdentTypeComponent(TC, DC, comp, options,
948-
diagnoseErrors, resolver);
950+
return resolveTopLevelIdentTypeComponent(TC, DC, comp, options, resolver);
949951
}
950952
}
951953

@@ -972,7 +974,7 @@ resolveGenericSignatureComponent(TypeChecker &TC, DeclContext *DC,
972974

973975
comp->setValue(typeDecl, DC);
974976
return resolveTopLevelIdentTypeComponent(TC, DC, comp, options,
975-
diagnoseErrors, resolver);
977+
resolver);
976978
}
977979
}
978980
}
@@ -989,7 +991,6 @@ static Type
989991
resolveTopLevelIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
990992
ComponentIdentTypeRepr *comp,
991993
TypeResolutionOptions options,
992-
bool diagnoseErrors,
993994
GenericTypeResolver *resolver) {
994995
// Short-circuiting.
995996
if (comp->isInvalid()) return ErrorType::get(TC.Context);
@@ -1027,7 +1028,7 @@ resolveTopLevelIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
10271028
// parameters (only), then move up to the enclosing context.
10281029
if (options.contains(TypeResolutionFlags::GenericSignature)) {
10291030
Type type = resolveGenericSignatureComponent(
1030-
TC, DC, comp, options, diagnoseErrors, resolver);
1031+
TC, DC, comp, options, resolver);
10311032
if (type)
10321033
return type;
10331034

@@ -1088,7 +1089,7 @@ resolveTopLevelIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
10881089
// Complain about any ambiguities we detected.
10891090
// FIXME: We could recover by looking at later components.
10901091
if (isAmbiguous) {
1091-
if (diagnoseErrors) {
1092+
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
10921093
TC.diagnose(comp->getIdLoc(), diag::ambiguous_type_base,
10931094
comp->getIdentifier())
10941095
.highlight(comp->getIdLoc());
@@ -1105,7 +1106,7 @@ resolveTopLevelIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
11051106
if (current.isNull()) {
11061107
// If we're not allowed to complain or we couldn't fix the
11071108
// source, bail out.
1108-
if (!diagnoseErrors)
1109+
if (options.contains(TypeResolutionFlags::SilenceErrors))
11091110
return ErrorType::get(TC.Context);
11101111

11111112
return diagnoseUnknownType(TC, DC, nullptr, SourceRange(), comp, options,
@@ -1125,7 +1126,6 @@ static Type resolveNestedIdentTypeComponent(
11251126
SourceRange parentRange,
11261127
ComponentIdentTypeRepr *comp,
11271128
TypeResolutionOptions options,
1128-
bool diagnoseErrors,
11291129
GenericTypeResolver *resolver) {
11301130
auto maybeApplyGenericArgs = [&](Type memberType) {
11311131
// If there are generic arguments, apply them now.
@@ -1151,7 +1151,7 @@ static Type resolveNestedIdentTypeComponent(
11511151
AssociatedTypeDecl *inferredAssocType) {
11521152
// Diagnose invalid cases.
11531153
if (TC.isUnsupportedMemberTypeAccess(parentTy, member)) {
1154-
if (diagnoseErrors) {
1154+
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
11551155
if (parentTy->is<UnboundGenericType>())
11561156
diagnoseUnboundGenericType(TC, parentTy, parentRange.End);
11571157
else if (parentTy->isExistentialType() &&
@@ -1172,16 +1172,16 @@ static Type resolveNestedIdentTypeComponent(
11721172
// be an unbound generic.
11731173
if (options & TypeResolutionFlags::TypeAliasUnderlyingType) {
11741174
if (parentTy->is<UnboundGenericType>()) {
1175-
if (diagnoseErrors)
1175+
if (!options.contains(TypeResolutionFlags::SilenceErrors))
11761176
diagnoseUnboundGenericType(TC, parentTy, parentRange.End);
11771177

11781178
return ErrorType::get(TC.Context);
11791179
}
11801180
}
11811181

11821182
// Diagnose a bad conformance reference if we need to.
1183-
if (inferredAssocType && diagnoseErrors && memberType &&
1184-
memberType->hasError()) {
1183+
if (!options.contains(TypeResolutionFlags::SilenceErrors) &&
1184+
inferredAssocType && memberType && memberType->hasError()) {
11851185
maybeDiagnoseBadConformanceRef(TC, DC, parentTy, comp->getLoc(),
11861186
inferredAssocType);
11871187
}
@@ -1252,7 +1252,7 @@ static Type resolveNestedIdentTypeComponent(
12521252
// FIXME: Could try to apply generic arguments first, and see whether
12531253
// that resolves things. But do we really want that to succeed?
12541254
if (memberTypes.size() > 1) {
1255-
if (diagnoseErrors)
1255+
if (!options.contains(TypeResolutionFlags::SilenceErrors))
12561256
TC.diagnoseAmbiguousMemberType(parentTy, parentRange,
12571257
comp->getIdentifier(), comp->getIdLoc(),
12581258
memberTypes);
@@ -1266,7 +1266,7 @@ static Type resolveNestedIdentTypeComponent(
12661266
if (!memberTypes) {
12671267
// If we're not allowed to complain or we couldn't fix the
12681268
// source, bail out.
1269-
if (!diagnoseErrors)
1269+
if (options.contains(TypeResolutionFlags::SilenceErrors))
12701270
return ErrorType::get(TC.Context);
12711271

12721272
memberType = diagnoseUnknownType(TC, DC, parentTy, parentRange, comp,
@@ -1288,22 +1288,20 @@ static Type resolveIdentTypeComponent(
12881288
TypeChecker &TC, DeclContext *DC,
12891289
ArrayRef<ComponentIdentTypeRepr *> components,
12901290
TypeResolutionOptions options,
1291-
bool diagnoseErrors,
12921291
GenericTypeResolver *resolver) {
12931292
auto comp = components.back();
12941293

12951294
// The first component uses unqualified lookup.
12961295
auto parentComps = components.slice(0, components.size()-1);
12971296
if (parentComps.empty()) {
1298-
return resolveTopLevelIdentTypeComponent(TC, DC, comp, options,
1299-
diagnoseErrors, resolver);
1297+
return resolveTopLevelIdentTypeComponent(TC, DC, comp, options, resolver);
13001298
}
13011299

13021300
// All remaining components use qualified lookup.
13031301

13041302
// Resolve the parent type.
13051303
Type parentTy = resolveIdentTypeComponent(TC, DC, parentComps, options,
1306-
diagnoseErrors, resolver);
1304+
resolver);
13071305
if (!parentTy || parentTy->hasError()) return parentTy;
13081306

13091307
SourceRange parentRange(parentComps.front()->getIdLoc(),
@@ -1312,8 +1310,7 @@ static Type resolveIdentTypeComponent(
13121310
// Resolve the nested type.
13131311
return resolveNestedIdentTypeComponent(TC, DC, parentTy,
13141312
parentRange, comp,
1315-
options, diagnoseErrors,
1316-
resolver);
1313+
options, resolver);
13171314
}
13181315

13191316
static bool diagnoseAvailability(IdentTypeRepr *IdType,
@@ -1373,19 +1370,18 @@ Type TypeChecker::resolveIdentifierType(
13731370
DeclContext *DC,
13741371
IdentTypeRepr *IdType,
13751372
TypeResolutionOptions options,
1376-
bool diagnoseErrors,
13771373
GenericTypeResolver *resolver) {
13781374
assert(resolver && "Missing generic type resolver");
13791375

13801376
auto ComponentRange = IdType->getComponentRange();
13811377
auto Components = llvm::makeArrayRef(ComponentRange.begin(),
13821378
ComponentRange.end());
13831379
Type result = resolveIdentTypeComponent(*this, DC, Components, options,
1384-
diagnoseErrors, resolver);
1380+
resolver);
13851381
if (!result) return nullptr;
13861382

13871383
if (auto moduleTy = result->getAs<ModuleType>()) {
1388-
if (diagnoseErrors) {
1384+
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
13891385
auto moduleName = moduleTy->getModule()->getName();
13901386
diagnose(Components.back()->getIdLoc(),
13911387
diag::use_undeclared_type, moduleName);
@@ -1410,7 +1406,8 @@ Type TypeChecker::resolveIdentifierType(
14101406
// To support this, inside inheritance clauses we allow references to
14111407
// protocols that are unavailable in the current type refinement context.
14121408

1413-
if (!(options & TypeResolutionFlags::AllowUnavailable) &&
1409+
if (!options.contains(TypeResolutionFlags::SilenceErrors) &&
1410+
!options.contains(TypeResolutionFlags::AllowUnavailable) &&
14141411
diagnoseAvailability(IdType, DC, *this,
14151412
options.contains(TypeResolutionFlags::AllowUnavailableProtocol))) {
14161413
Components.back()->setInvalid();
@@ -1594,7 +1591,7 @@ Type TypeResolver::resolveType(TypeRepr *repr, TypeResolutionOptions options) {
15941591
case TypeReprKind::GenericIdent:
15951592
case TypeReprKind::CompoundIdent:
15961593
return TC.resolveIdentifierType(DC, cast<IdentTypeRepr>(repr), options,
1597-
/*diagnoseErrors*/ true, Resolver);
1594+
Resolver);
15981595

15991596
case TypeReprKind::Function: {
16001597
if (!(options & TypeResolutionFlags::SILType)) {

0 commit comments

Comments
 (0)