Skip to content

Commit 0956cfa

Browse files
committed
[Sema] typecheck implicit extensions too
When asking about the Copyable conformance for a nominal, we will end up synthesizing a conditional conformance to Copyable depending on the presence of ~Copyable in a generic param. We were not actually checking that conformance for validity (i.e., the containment rule) because we were skipping over implicit ExtensionDecl's at a high level, but only during Sema. There doesn't appear to be a fundamental issue with also checking the implicit decls; it just requires care when dealing with the inheritance clause's lack of TypeRepr's. Perhaps it's debatable whether the inheritance clause should have any entries at all for an implicit extension, if it's generic signature has already been set. It's where-clause isn't populated either.
1 parent d4522fa commit 0956cfa

File tree

3 files changed

+9
-12
lines changed

3 files changed

+9
-12
lines changed

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,7 +1640,7 @@ static void diagnoseRetroactiveConformances(
16401640
// We better only be conforming it to protocols declared within this module.
16411641
llvm::SmallSetVector<ProtocolDecl *, 8> externalProtocols;
16421642
for (const InheritedEntry &entry : ext->getInherited().getEntries()) {
1643-
if (entry.getType().isNull()) {
1643+
if (entry.getType().isNull() || !entry.getTypeRepr()) {
16441644
continue;
16451645
}
16461646

@@ -3821,7 +3821,7 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
38213821
auto *extTypeNominal = extType->getAnyNominal();
38223822
bool firstNominalIsNotMostSpecific =
38233823
extTypeNominal && extTypeNominal != nominal;
3824-
if (isa<CompositionTypeRepr>(extTypeRepr)
3824+
if ((extTypeRepr && isa<CompositionTypeRepr>(extTypeRepr))
38253825
|| firstNominalIsNotMostSpecific) {
38263826
auto diag = ED->diagnose(diag::composition_in_extended_type,
38273827
nominal->getDeclaredType());

lib/Sema/TypeCheckInvertible.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ static void tryEmitContainmentFixits(NominalTypeDecl *enclosingNom,
7878
}
7979
break;
8080
case InverseMarking::Kind::Explicit:
81-
assert(false && "how did it become Copyable?");
8281
break;
8382
};
8483

@@ -326,11 +325,11 @@ ProtocolConformance *deriveConformanceForInvertible(Evaluator &evaluator,
326325
ext->setExtendedNominal(nominal);
327326
nominal->addExtension(ext);
328327

329-
// Make it accessible to getTopLevelDecls()
330-
if (auto file = dyn_cast<FileUnit>(nominal->getModuleScopeContext()))
331-
file->getOrCreateSynthesizedFile().addTopLevelDecl(ext);
328+
// Make it accessible to getTopLevelDecls() so it gets type-checked.
329+
auto file = cast<FileUnit>(nominal->getModuleScopeContext());
330+
file->getOrCreateSynthesizedFile().addTopLevelDecl(ext);
332331

333-
// Then reate the conformance using the extension as the conformance's
332+
// Then create the conformance using the extension as the conformance's
334333
// DeclContext, which is how we register these conditional requirements
335334
// with the conformance.
336335
return generateConformance(ext);

lib/Sema/TypeChecker.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -290,13 +290,11 @@ TypeCheckSourceFileRequest::evaluate(Evaluator &eval, SourceFile *SF) const {
290290
}
291291
}
292292

293-
// Type-check macro-generated extensions.
293+
// Type-check macro-generated or implicitly-synthesized extensions.
294294
if (auto *synthesizedSF = SF->getSynthesizedFile()) {
295295
for (auto *decl : synthesizedSF->getTopLevelDecls()) {
296-
if (!decl->isImplicit()) {
297-
assert(isa<ExtensionDecl>(decl));
298-
TypeChecker::typeCheckDecl(decl);
299-
}
296+
assert(isa<ExtensionDecl>(decl));
297+
TypeChecker::typeCheckDecl(decl);
300298
}
301299
}
302300
SF->typeCheckDelayedFunctions();

0 commit comments

Comments
 (0)