Skip to content

Commit 1915b06

Browse files
committed
Merge pull request #781 from JaSpa/highlight-generic-args
[Sema] Highlight angle brackets <…> in diagnostics
2 parents a9e1fc0 + 7822c92 commit 1915b06

File tree

3 files changed

+134
-103
lines changed

3 files changed

+134
-103
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 60 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -362,45 +362,59 @@ Type TypeChecker::resolveTypeInContext(
362362
fromType, /*isTypeReference=*/true);
363363
}
364364

365-
/// Apply generic arguments to the given type.
366-
Type TypeChecker::applyGenericArguments(Type type,
367-
SourceLoc loc,
365+
Type TypeChecker::applyGenericArguments(Type type, SourceLoc loc,
368366
DeclContext *dc,
369-
MutableArrayRef<TypeLoc> genericArgs,
367+
GenericIdentTypeRepr *generic,
370368
bool isGenericSignature,
371369
GenericTypeResolver *resolver) {
372-
// Make sure we always have a resolver to use.
373-
PartialGenericTypeToArchetypeResolver defaultResolver(*this);
374-
if (!resolver)
375-
resolver = &defaultResolver;
376370

377371
auto unbound = type->getAs<UnboundGenericType>();
378372
if (!unbound) {
379-
// FIXME: Highlight generic arguments and introduce a Fix-It to remove
380-
// them.
381-
if (!type->is<ErrorType>()) {
382-
diagnose(loc, diag::not_a_generic_type, type);
383-
}
384-
385-
// Just return the type; this provides better recovery anyway.
373+
if (!type->is<ErrorType>())
374+
diagnose(loc, diag::not_a_generic_type, type)
375+
.fixItRemove(generic->getAngleBrackets());
386376
return type;
387377
}
388378

389379
// Make sure we have the right number of generic arguments.
390380
// FIXME: If we have fewer arguments than we need, that might be okay, if
391381
// we're allowed to deduce the remaining arguments from context.
392-
auto genericParams = unbound->getDecl()->getGenericParams();
382+
auto unboundDecl = unbound->getDecl();
383+
auto genericArgs = generic->getGenericArgs();
384+
auto genericParams = unboundDecl->getGenericParams();
393385
if (genericParams->size() != genericArgs.size()) {
394-
// FIXME: Highlight <...>.
395-
diagnose(loc, diag::type_parameter_count_mismatch,
396-
unbound->getDecl()->getName(),
386+
diagnose(loc, diag::type_parameter_count_mismatch, unboundDecl->getName(),
397387
genericParams->size(), genericArgs.size(),
398-
genericArgs.size() < genericParams->size());
399-
diagnose(unbound->getDecl(), diag::generic_type_declared_here,
400-
unbound->getDecl()->getName());
388+
genericArgs.size() < genericParams->size())
389+
.highlight(generic->getAngleBrackets());
390+
diagnose(unboundDecl, diag::generic_type_declared_here,
391+
unboundDecl->getName());
401392
return nullptr;
402393
}
403394

395+
SmallVector<TypeLoc, 8> args;
396+
for (auto tyR : genericArgs)
397+
args.push_back(tyR);
398+
399+
return applyUnboundGenericArguments(unbound, loc, dc, args,
400+
isGenericSignature, resolver);
401+
}
402+
403+
/// Apply generic arguments to the given type.
404+
Type TypeChecker::applyUnboundGenericArguments(
405+
UnboundGenericType *unbound, SourceLoc loc, DeclContext *dc,
406+
MutableArrayRef<TypeLoc> genericArgs, bool isGenericSignature,
407+
GenericTypeResolver *resolver) {
408+
409+
assert(unbound &&
410+
genericArgs.size() == unbound->getDecl()->getGenericParams()->size() &&
411+
"invalid arguments, use applyGenricArguments for diagnostic emitting");
412+
413+
// Make sure we always have a resolver to use.
414+
PartialGenericTypeToArchetypeResolver defaultResolver(*this);
415+
if (!resolver)
416+
resolver = &defaultResolver;
417+
404418
TypeResolutionOptions options;
405419
if (isGenericSignature)
406420
options |= TR_GenericSignature;
@@ -449,20 +463,17 @@ Type TypeChecker::applyGenericArguments(Type type,
449463

450464
static Type applyGenericTypeReprArgs(TypeChecker &TC, Type type, SourceLoc loc,
451465
DeclContext *dc,
452-
ArrayRef<TypeRepr *> genericArgs,
466+
GenericIdentTypeRepr *generic,
453467
bool isGenericSignature,
454468
GenericTypeResolver *resolver) {
455-
SmallVector<TypeLoc, 8> args;
456-
for (auto tyR : genericArgs)
457-
args.push_back(tyR);
458-
Type ty = TC.applyGenericArguments(type, loc, dc, args,
459-
isGenericSignature, resolver);
469+
470+
Type ty = TC.applyGenericArguments(type, loc, dc, generic, isGenericSignature,
471+
resolver);
460472
if (!ty)
461473
return ErrorType::get(TC.Context);
462474
return ty;
463475
}
464476

465-
466477
/// \brief Diagnose a use of an unbound generic type.
467478
static void diagnoseUnboundGenericType(TypeChecker &tc, Type ty,SourceLoc loc) {
468479
tc.diagnose(loc, diag::generic_type_requires_arguments, ty);
@@ -474,7 +485,7 @@ static void diagnoseUnboundGenericType(TypeChecker &tc, Type ty,SourceLoc loc) {
474485
/// \brief Returns a valid type or ErrorType in case of an error.
475486
static Type resolveTypeDecl(TypeChecker &TC, TypeDecl *typeDecl, SourceLoc loc,
476487
DeclContext *dc,
477-
ArrayRef<TypeRepr *> genericArgs,
488+
GenericIdentTypeRepr *generic,
478489
TypeResolutionOptions options,
479490
GenericTypeResolver *resolver,
480491
UnsatisfiedDependency *unsatisfiedDependency) {
@@ -491,15 +502,15 @@ static Type resolveTypeDecl(TypeChecker &TC, TypeDecl *typeDecl, SourceLoc loc,
491502

492503
// Resolve the type declaration to a specific type. How this occurs
493504
// depends on the current context and where the type was found.
494-
Type type = TC.resolveTypeInContext(typeDecl, dc, options,
495-
!genericArgs.empty(), resolver);
505+
Type type =
506+
TC.resolveTypeInContext(typeDecl, dc, options, generic, resolver);
496507

497508
// FIXME: Defensive check that shouldn't be needed, but prevents a
498509
// huge number of crashes on ill-formed code.
499510
if (!type)
500511
return ErrorType::get(TC.Context);
501512

502-
if (type->is<UnboundGenericType>() && genericArgs.empty() &&
513+
if (type->is<UnboundGenericType>() && !generic &&
503514
!options.contains(TR_AllowUnboundGenerics) &&
504515
!options.contains(TR_ResolveStructure)) {
505516
diagnoseUnboundGenericType(TC, type, loc);
@@ -519,9 +530,9 @@ static Type resolveTypeDecl(TypeChecker &TC, TypeDecl *typeDecl, SourceLoc loc,
519530
}
520531
}
521532

522-
if (!genericArgs.empty() && !options.contains(TR_ResolveStructure)) {
533+
if (generic && !options.contains(TR_ResolveStructure)) {
523534
// Apply the generic arguments to the type.
524-
type = applyGenericTypeReprArgs(TC, type, loc, dc, genericArgs,
535+
type = applyGenericTypeReprArgs(TC, type, loc, dc, generic,
525536
options.contains(TR_GenericSignature),
526537
resolver);
527538
}
@@ -568,7 +579,7 @@ static Type diagnoseUnknownType(TypeChecker &tc, DeclContext *dc,
568579
(nominal = getEnclosingNominalContext(dc))) {
569580
// Retrieve the nominal type and resolve it within this context.
570581
assert(!isa<ProtocolDecl>(nominal) && "Cannot be a protocol");
571-
auto type = resolveTypeDecl(tc, nominal, comp->getIdLoc(), dc, { },
582+
auto type = resolveTypeDecl(tc, nominal, comp->getIdLoc(), dc, nullptr,
572583
options, resolver, unsatisfiedDependency);
573584
if (type->is<ErrorType>())
574585
return type;
@@ -661,15 +672,10 @@ resolveTopLevelIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
661672
return ErrorType::get(TC.Context);
662673
}
663674

664-
// Retrieve the generic arguments, if there are any.
665-
ArrayRef<TypeRepr *> genericArgs;
666-
if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp))
667-
genericArgs = genComp->getGenericArgs();
668-
669675
// Resolve the type declaration within this context.
670676
return resolveTypeDecl(TC, typeDecl, comp->getIdLoc(), DC,
671-
genericArgs, options, resolver,
672-
unsatisfiedDependency);
677+
dyn_cast<GenericIdentTypeRepr>(comp), options,
678+
resolver, unsatisfiedDependency);
673679
}
674680

675681
// Resolve the first component, which is the only one that requires
@@ -787,12 +793,10 @@ resolveTopLevelIdentTypeComponent(TypeChecker &TC, DeclContext *DC,
787793
TC.forceExternalDeclMembers(nomDecl);
788794
}
789795

790-
ArrayRef<TypeRepr *> genericArgs;
791-
if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp))
792-
genericArgs = genComp->getGenericArgs();
793-
Type type = resolveTypeDecl(TC, typeDecl, comp->getIdLoc(),
794-
DC, genericArgs, options, resolver,
795-
unsatisfiedDependency);
796+
Type type = resolveTypeDecl(TC, typeDecl, comp->getIdLoc(), DC,
797+
dyn_cast<GenericIdentTypeRepr>(comp), options,
798+
resolver, unsatisfiedDependency);
799+
796800
if (!type || type->is<ErrorType>())
797801
return type;
798802

@@ -923,10 +927,8 @@ static Type resolveNestedIdentTypeComponent(
923927
// If there are generic arguments, apply them now.
924928
if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp)) {
925929
memberType = applyGenericTypeReprArgs(
926-
TC, memberType, comp->getIdLoc(), DC,
927-
genComp->getGenericArgs(),
928-
options.contains(TR_GenericSignature),
929-
resolver);
930+
TC, memberType, comp->getIdLoc(), DC, genComp,
931+
options.contains(TR_GenericSignature), resolver);
930932

931933
// Propagate failure.
932934
if (!memberType || memberType->is<ErrorType>()) return memberType;
@@ -1041,8 +1043,8 @@ static Type resolveNestedIdentTypeComponent(
10411043
// If there are generic arguments, apply them now.
10421044
if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp))
10431045
memberType = applyGenericTypeReprArgs(
1044-
TC, memberType, comp->getIdLoc(), DC, genComp->getGenericArgs(),
1045-
options.contains(TR_GenericSignature), resolver);
1046+
TC, memberType, comp->getIdLoc(), DC, genComp,
1047+
options.contains(TR_GenericSignature), resolver);
10461048

10471049
if (member)
10481050
comp->setValue(member);
@@ -2124,9 +2126,9 @@ Type TypeResolver::resolveDictionaryType(DictionaryTypeRepr *repr,
21242126
nullptr, TC.Context);
21252127
TypeLoc args[2] = { TypeLoc(repr->getKey()), TypeLoc(repr->getValue()) };
21262128

2127-
if (!TC.applyGenericArguments(unboundTy, repr->getStartLoc(), DC, args,
2128-
options.contains(TR_GenericSignature),
2129-
Resolver)) {
2129+
if (!TC.applyUnboundGenericArguments(
2130+
unboundTy, repr->getStartLoc(), DC, args,
2131+
options.contains(TR_GenericSignature), Resolver)) {
21302132
return ErrorType::get(TC.Context);
21312133
}
21322134

0 commit comments

Comments
 (0)