Skip to content

Commit 79446c4

Browse files
authored
Merge pull request #3181 from slavapestov/generic-typealias-fixes
2 parents 266ead9 + beb5018 commit 79446c4

File tree

13 files changed

+292
-87
lines changed

13 files changed

+292
-87
lines changed

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,6 +760,7 @@ namespace decls_block {
760760
TypeIDField, // interface type
761761
BCFixed<1>, // implicit flag
762762
AccessibilityKindField // accessibility
763+
// Trailed by generic parameters (if any).
763764
>;
764765

765766
using GenericTypeParamDeclLayout = BCRecordLayout<

lib/Sema/ConstraintSystem.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,8 @@ namespace {
593593
// pointing at a generic TypeAliasDecl here. If we find a way to
594594
// handle generic TypeAliases elsewhere, this can just become a
595595
// call to BoundGenericType::get().
596-
return cs.TC.applyUnboundGenericArguments(unbound, SourceLoc(), cs.DC,
597-
arguments,
596+
return cs.TC.applyUnboundGenericArguments(unbound, unboundDecl,
597+
SourceLoc(), cs.DC, arguments,
598598
/*isGenericSignature*/false,
599599
/*resolver*/nullptr);
600600
}

lib/Sema/TypeCheckStmt.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,13 +1017,17 @@ void TypeChecker::checkIgnoredExpr(Expr *E) {
10171017
return;
10181018
}
10191019

1020-
// Drill through noop expressions we don't care about, like ParanExprs.
1020+
// Drill through noop expressions we don't care about.
10211021
auto valueE = E;
10221022
while (1) {
10231023
valueE = valueE->getValueProvidingExpr();
10241024

10251025
if (auto *OEE = dyn_cast<OpenExistentialExpr>(valueE))
10261026
valueE = OEE->getSubExpr();
1027+
else if (auto *CRCE = dyn_cast<CovariantReturnConversionExpr>(valueE))
1028+
valueE = CRCE->getSubExpr();
1029+
else if (auto *EE = dyn_cast<ErasureExpr>(valueE))
1030+
valueE = EE->getSubExpr();
10271031
else
10281032
break;
10291033
}

lib/Sema/TypeCheckType.cpp

Lines changed: 90 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ Type TypeChecker::resolveTypeInContext(
209209
// If we have a callback to report dependencies, do so.
210210
if (unsatisfiedDependency &&
211211
(*unsatisfiedDependency)(requestResolveTypeDecl(typeDecl)))
212-
return nullptr;
212+
return Type();
213213

214214
// If we found a generic parameter, map to the archetype if there is one.
215215
if (auto genericParam = dyn_cast<GenericTypeParamDecl>(typeDecl)) {
@@ -233,7 +233,7 @@ Type TypeChecker::resolveTypeInContext(
233233
// We might have an invalid extension that didn't resolve.
234234
if (ownerNominal == nullptr && ownerDC->isExtensionContext()) {
235235
assert(cast<ExtensionDecl>(ownerDC)->isInvalid());
236-
return ErrorType::get(ownerDC->getASTContext());
236+
return ErrorType::get(Context);
237237
}
238238

239239
auto assocType = dyn_cast<AssociatedTypeDecl>(typeDecl);
@@ -372,7 +372,7 @@ Type TypeChecker::resolveTypeInContext(
372372

373373
auto protoSelf = parentDC->getProtocolSelf();
374374
if (protoSelf == nullptr)
375-
return ErrorType::get(parentDC->getASTContext());
375+
return ErrorType::get(Context);
376376

377377
auto selfType = protoSelf
378378
->getDeclaredType()
@@ -402,61 +402,85 @@ Type TypeChecker::resolveTypeInContext(
402402
}
403403

404404
assert(incomplete && "Should have found type by now");
405-
return ErrorType::get(ownerDC->getASTContext());
405+
return ErrorType::get(Context);
406406
}
407407

408-
Type TypeChecker::applyGenericArguments(Type type, SourceLoc loc,
409-
DeclContext *dc,
408+
Type TypeChecker::applyGenericArguments(Type type, TypeDecl *decl,
409+
SourceLoc loc, DeclContext *dc,
410410
GenericIdentTypeRepr *generic,
411411
bool isGenericSignature,
412412
GenericTypeResolver *resolver) {
413413

414-
auto unbound = type->getAs<UnboundGenericType>();
415-
if (!unbound) {
416-
if (!type->is<ErrorType>()) {
417-
auto diag = diagnose(loc, diag::not_a_generic_type, type);
414+
if (type->is<ErrorType>()) {
415+
generic->setInvalid();
416+
return type;
417+
}
418+
419+
// We must either have an unbound generic type, or a generic type alias.
420+
if (!type->is<UnboundGenericType>() &&
421+
!(isa<TypeAliasDecl>(decl) &&
422+
cast<TypeAliasDecl>(decl)->getGenericParams())) {
423+
424+
auto diag = diagnose(loc, diag::not_a_generic_type, type);
425+
426+
// Don't add fixit on module type; that isn't the right type regardless
427+
// of whether it had generic arguments.
428+
if (!type->is<ModuleType>())
429+
diag.fixItRemove(generic->getAngleBrackets());
418430

419-
// Don't add fixit on module type; that isn't the right type regardless
420-
// of whether it had generic arguments.
421-
if (!type->is<ModuleType>())
422-
diag.fixItRemove(generic->getAngleBrackets());
423-
}
424431
generic->setInvalid();
425432
return type;
426433
}
427434

435+
// If we have a non-generic type alias, we have an unbound generic type.
436+
// Grab the decl from the unbound generic type.
437+
//
438+
// The idea is if you write:
439+
//
440+
// typealias Foo = Bar.Baz
441+
//
442+
// Then 'Foo<Int>' applies arguments to Bar.Baz, whereas if you write:
443+
//
444+
// typealias Foo<T> = Bar.Baz<T>
445+
//
446+
// Then 'Foo<Int>' applies arguments to Foo itself.
447+
//
448+
if (isa<TypeAliasDecl>(decl) &&
449+
!cast<TypeAliasDecl>(decl)->getGenericParams()) {
450+
decl = type->castTo<UnboundGenericType>()->getDecl();
451+
}
452+
428453
// Make sure we have the right number of generic arguments.
429454
// FIXME: If we have fewer arguments than we need, that might be okay, if
430455
// we're allowed to deduce the remaining arguments from context.
431-
auto unboundDecl = unbound->getDecl();
456+
auto genericDecl = cast<GenericTypeDecl>(decl);
432457
auto genericArgs = generic->getGenericArgs();
433-
auto genericParams = unboundDecl->getGenericParams();
458+
auto genericParams = genericDecl->getGenericParams();
434459
if (genericParams->size() != genericArgs.size()) {
435-
diagnose(loc, diag::type_parameter_count_mismatch, unboundDecl->getName(),
460+
diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(),
436461
genericParams->size(), genericArgs.size(),
437462
genericArgs.size() < genericParams->size())
438463
.highlight(generic->getAngleBrackets());
439-
diagnose(unboundDecl, diag::generic_type_declared_here,
440-
unboundDecl->getName());
464+
diagnose(decl, diag::generic_type_declared_here,
465+
decl->getName());
441466
return nullptr;
442467
}
443468

444469
SmallVector<TypeLoc, 8> args;
445470
for (auto tyR : genericArgs)
446471
args.push_back(tyR);
447472

448-
return applyUnboundGenericArguments(unbound, loc, dc, args,
473+
return applyUnboundGenericArguments(type, genericDecl, loc, dc, args,
449474
isGenericSignature, resolver);
450475
}
451476

452477
/// Apply generic arguments to the given type.
453478
Type TypeChecker::applyUnboundGenericArguments(
454-
UnboundGenericType *unbound, SourceLoc loc, DeclContext *dc,
479+
Type type, GenericTypeDecl *decl, SourceLoc loc, DeclContext *dc,
455480
MutableArrayRef<TypeLoc> genericArgs, bool isGenericSignature,
456481
GenericTypeResolver *resolver) {
457482

458-
assert(unbound &&
459-
genericArgs.size() == unbound->getDecl()->getGenericParams()->size() &&
483+
assert(genericArgs.size() == decl->getGenericParams()->size() &&
460484
"invalid arguments, use applyGenericArguments for diagnostic emitting");
461485

462486
// Make sure we always have a resolver to use.
@@ -477,50 +501,48 @@ Type TypeChecker::applyUnboundGenericArguments(
477501

478502
genericArgTypes.push_back(genericArg.getType());
479503
}
480-
504+
481505
// If we're completing a generic TypeAlias, then we map the types provided
482506
// onto the underlying type.
483-
if (auto *TAD = dyn_cast<TypeAliasDecl>(unbound->getDecl())) {
507+
if (auto *TAD = dyn_cast<TypeAliasDecl>(decl)) {
484508
auto signature = TAD->getGenericSignature();
485-
assert(TAD->getGenericParams()->getAllArchetypes().size()
486-
== genericArgs.size() &&
487-
signature->getInnermostGenericParams().size() == genericArgs.size()&&
488-
"argument arity mismatch");
489509

490-
SmallVector<Substitution, 4> subs;
491-
subs.reserve(genericArgs.size());
492-
493-
// If we have any nested archetypes from an outer type, include them
494-
// verbatim.
495-
auto outerParams = signature->getGenericParams();
496-
outerParams = outerParams.drop_back(genericArgs.size());
497-
for (auto param : outerParams) {
498-
Type type = resolver->resolveGenericTypeParamType(param);
510+
TypeSubstitutionMap subs;
511+
for (unsigned i = 0, e = genericArgs.size(); i < e; i++) {
512+
auto t = signature->getInnermostGenericParams()[i];
513+
subs[t->getCanonicalType().getPointer()] = genericArgs[i].getType();
514+
}
499515

500-
subs.push_back(Substitution(type, {}));
516+
if (auto outerSig = TAD->getDeclContext()->getGenericSignatureOfContext()) {
517+
for (auto outerParam : outerSig->getGenericParams()) {
518+
subs[outerParam->getCanonicalType().getPointer()] =
519+
ArchetypeBuilder::mapTypeIntoContext(TAD->getDeclContext(),
520+
outerParam);
521+
}
501522
}
502-
503-
for (auto t : genericArgs)
504-
subs.push_back(Substitution(t.getType(), {}));
505-
506-
auto subst = TAD->getGenericParams()->getSubstitutionMap(subs);
523+
524+
// FIXME: Change callers to pass the right type in for generic typealiases
525+
if (type->is<UnboundGenericType>() || isa<NameAliasType>(type.getPointer())) {
526+
type = ArchetypeBuilder::mapTypeOutOfContext(TAD, TAD->getUnderlyingType());
527+
}
528+
529+
type = type.subst(dc->getParentModule(), subs, None);
507530

508531
// FIXME: return a SubstitutedType to preserve the fact that
509532
// we resolved a generic TypeAlias, for availability diagnostics.
510533
// A better fix might be to introduce a BoundGenericAliasType
511534
// which desugars as appropriate.
512-
return SubstitutedType::get(
513-
TAD->getDeclaredType(),
514-
TAD->getUnderlyingType().subst(TAD->getParentModule(), subst, None),
515-
Context);
535+
return SubstitutedType::get(TAD->getDeclaredType(), type, Context);
516536
}
517537

518538
// Form the bound generic type.
519-
auto *BGT = BoundGenericType::get(cast<NominalTypeDecl>(unbound->getDecl()),
520-
unbound->getParent(), genericArgTypes);
539+
auto *UGT = type->castTo<UnboundGenericType>();
540+
auto *BGT = BoundGenericType::get(cast<NominalTypeDecl>(decl),
541+
UGT->getParent(), genericArgTypes);
542+
521543
// Check protocol conformance.
522544
if (!BGT->hasTypeParameter() && !BGT->hasTypeVariable()) {
523-
SourceLoc noteLoc = unbound->getDecl()->getLoc();
545+
SourceLoc noteLoc = decl->getLoc();
524546
if (noteLoc.isInvalid())
525547
noteLoc = loc;
526548

@@ -532,14 +554,13 @@ Type TypeChecker::applyUnboundGenericArguments(
532554
ArrayRef<Type> allGenericArgs = BGT->getAllGenericArgs(scratch);
533555

534556
// Check the generic arguments against the generic signature.
535-
auto genericSig = unbound->getDecl()->getGenericSignature();
536-
if (!unbound->getDecl()->hasType() ||
537-
unbound->getDecl()->isValidatingGenericSignature()) {
557+
auto genericSig = decl->getGenericSignature();
558+
if (!decl->hasType() || decl->isValidatingGenericSignature()) {
538559
diagnose(loc, diag::recursive_requirement_reference);
539560
return nullptr;
540561
}
541562
assert(genericSig != nullptr);
542-
if (checkGenericArguments(dc, loc, noteLoc, unbound, genericSig,
563+
if (checkGenericArguments(dc, loc, noteLoc, UGT, genericSig,
543564
allGenericArgs))
544565
return nullptr;
545566

@@ -549,14 +570,16 @@ Type TypeChecker::applyUnboundGenericArguments(
549570
return BGT;
550571
}
551572

552-
static Type applyGenericTypeReprArgs(TypeChecker &TC, Type type, SourceLoc loc,
573+
static Type applyGenericTypeReprArgs(TypeChecker &TC, Type type,
574+
TypeDecl *decl,
575+
SourceLoc loc,
553576
DeclContext *dc,
554577
GenericIdentTypeRepr *generic,
555578
bool isGenericSignature,
556579
GenericTypeResolver *resolver) {
557580

558-
Type ty = TC.applyGenericArguments(type, loc, dc, generic, isGenericSignature,
559-
resolver);
581+
Type ty = TC.applyGenericArguments(type, decl, loc, dc, generic,
582+
isGenericSignature, resolver);
560583
if (!ty)
561584
return ErrorType::get(TC.Context);
562585
return ty;
@@ -660,7 +683,7 @@ static Type resolveTypeDecl(TypeChecker &TC, TypeDecl *typeDecl, SourceLoc loc,
660683

661684
if (generic && !options.contains(TR_ResolveStructure)) {
662685
// Apply the generic arguments to the type.
663-
type = applyGenericTypeReprArgs(TC, type, loc, dc, generic,
686+
type = applyGenericTypeReprArgs(TC, type, typeDecl, loc, dc, generic,
664687
options.contains(TR_GenericSignature),
665688
resolver);
666689
}
@@ -1035,7 +1058,7 @@ static Type resolveNestedIdentTypeComponent(
10351058
// If there are generic arguments, apply them now.
10361059
if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp)) {
10371060
memberType = applyGenericTypeReprArgs(
1038-
TC, memberType, comp->getIdLoc(), DC, genComp,
1061+
TC, memberType, typeDecl, comp->getIdLoc(), DC, genComp,
10391062
options.contains(TR_GenericSignature), resolver);
10401063

10411064
// Propagate failure.
@@ -1154,7 +1177,7 @@ static Type resolveNestedIdentTypeComponent(
11541177
// If there are generic arguments, apply them now.
11551178
if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp))
11561179
memberType = applyGenericTypeReprArgs(
1157-
TC, memberType, comp->getIdLoc(), DC, genComp,
1180+
TC, memberType, member, comp->getIdLoc(), DC, genComp,
11581181
options.contains(TR_GenericSignature), resolver);
11591182

11601183
// If we found a reference to an associated type or other member type that
@@ -2235,16 +2258,17 @@ Type TypeResolver::resolveDictionaryType(DictionaryTypeRepr *repr,
22352258

22362259
Type valueTy = resolveType(repr->getValue(), withoutContext(options));
22372260
if (!valueTy || valueTy->is<ErrorType>()) return valueTy;
2238-
2261+
2262+
auto dictDecl = TC.Context.getDictionaryDecl();
2263+
22392264
if (auto dictTy = TC.getDictionaryType(repr->getBrackets().Start, keyTy,
22402265
valueTy)) {
22412266
// Check the requirements on the generic arguments.
2242-
auto unboundTy = UnboundGenericType::get(TC.Context.getDictionaryDecl(),
2243-
nullptr, TC.Context);
2267+
auto unboundTy = dictDecl->getDeclaredType();
22442268
TypeLoc args[2] = { TypeLoc(repr->getKey()), TypeLoc(repr->getValue()) };
22452269

22462270
if (!TC.applyUnboundGenericArguments(
2247-
unboundTy, repr->getStartLoc(), DC, args,
2271+
unboundTy, dictDecl, repr->getStartLoc(), DC, args,
22482272
options.contains(TR_GenericSignature), Resolver)) {
22492273
return ErrorType::get(TC.Context);
22502274
}

lib/Sema/TypeChecker.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,7 @@ class TypeChecker final : public LazyResolver {
774774
/// to be in a correct and valid form.
775775
///
776776
/// \param type The generic type to which to apply arguments.
777+
/// \param decl The declaration of the type.
777778
/// \param loc The source location for diagnostic reporting.
778779
/// \param dc The context where the arguments are applied.
779780
/// \param generic The arguments to apply with the angle bracket range for
@@ -786,8 +787,8 @@ class TypeChecker final : public LazyResolver {
786787
/// error.
787788
///
788789
/// \see applyUnboundGenericArguments
789-
Type applyGenericArguments(Type type, SourceLoc loc, DeclContext *dc,
790-
GenericIdentTypeRepr *generic,
790+
Type applyGenericArguments(Type type, TypeDecl *decl, SourceLoc loc,
791+
DeclContext *dc, GenericIdentTypeRepr *generic,
791792
bool isGenericSignature,
792793
GenericTypeResolver *resolver);
793794

@@ -797,7 +798,8 @@ class TypeChecker final : public LazyResolver {
797798
/// number of generic arguments given, whereas applyGenericArguments emits
798799
/// diagnostics in those cases.
799800
///
800-
/// \param unbound The unbound generic type to which to apply arguments.
801+
/// \param type The unbound generic type to which to apply arguments.
802+
/// \param decl The declaration of the type.
801803
/// \param loc The source location for diagnostic reporting.
802804
/// \param dc The context where the arguments are applied.
803805
/// \param genericArgs The list of generic arguments to apply to the type.
@@ -809,8 +811,8 @@ class TypeChecker final : public LazyResolver {
809811
/// error.
810812
///
811813
/// \see applyGenericArguments
812-
Type applyUnboundGenericArguments(UnboundGenericType *unbound, SourceLoc loc,
813-
DeclContext *dc,
814+
Type applyUnboundGenericArguments(Type type, GenericTypeDecl *decl,
815+
SourceLoc loc, DeclContext *dc,
814816
MutableArrayRef<TypeLoc> genericArgs,
815817
bool isGenericSignature,
816818
GenericTypeResolver *resolver);

0 commit comments

Comments
 (0)