mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
ModuleInterface: Avoid crashing on invalid extensions in lazy typechecking mode.
With `-experimental-lazy-typecheck` specified during module interface emission, `collectProtocols()` may be the first piece of code to request the extended type for a given extension and it therefore needs to ignore invalid extensions and ensure that diagnostics are emitted. Also, add some `PrettyStackTrace` coverage to `ModuleInterfaceSupport.cpp` to make investigating future issues easier. Resolves rdar://126232836.
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#ifndef SWIFT_FRONTEND_MODULEINTERFACESUPPORT_H
|
||||
#define SWIFT_FRONTEND_MODULEINTERFACESUPPORT_H
|
||||
|
||||
#include "swift/AST/PrintOptions.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/Basic/Version.h"
|
||||
#include "llvm/Support/Regex.h"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Frontend/ModuleInterfaceSupport.h"
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/ASTPrinter.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
@@ -20,13 +21,13 @@
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/ModuleNameLookup.h"
|
||||
#include "swift/AST/NameLookupRequests.h"
|
||||
#include "swift/AST/PrettyStackTrace.h"
|
||||
#include "swift/AST/ProtocolConformance.h"
|
||||
#include "swift/AST/TypeCheckRequests.h"
|
||||
#include "swift/AST/TypeRepr.h"
|
||||
#include "swift/Basic/Assertions.h"
|
||||
#include "swift/Basic/STLExtras.h"
|
||||
#include "swift/Frontend/Frontend.h"
|
||||
#include "swift/Frontend/ModuleInterfaceSupport.h"
|
||||
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
||||
#include "swift/SILOptimizer/PassManager/Passes.h"
|
||||
#include "swift/Serialization/SerializationOptions.h"
|
||||
@@ -530,6 +531,7 @@ class InheritedProtocolCollector {
|
||||
/// protocols.
|
||||
void recordProtocols(InheritedTypes directlyInherited, const Decl *D,
|
||||
bool skipExtra = false) {
|
||||
PrettyStackTraceDecl stackTrace("recording protocols for", D);
|
||||
std::optional<AvailableAttrList> availableAttrs;
|
||||
|
||||
for (int i : directlyInherited.getIndices()) {
|
||||
@@ -602,11 +604,19 @@ public:
|
||||
///
|
||||
/// \sa recordProtocols
|
||||
static void collectProtocols(PerTypeMap &map, const Decl *D) {
|
||||
PrettyStackTraceDecl stackTrace("collecting protocols for", D);
|
||||
InheritedTypes directlyInherited = InheritedTypes(D);
|
||||
const NominalTypeDecl *nominal;
|
||||
const IterableDeclContext *memberContext;
|
||||
|
||||
auto shouldInclude = [](const ExtensionDecl *extension) {
|
||||
// In lazy typechecking mode we may be resolving the extended type for the
|
||||
// first time here, so we need to call getExtendedType() to cause
|
||||
// diagnostics to be emitted if necessary.
|
||||
(void)extension->getExtendedType();
|
||||
if (extension->isInvalid())
|
||||
return false;
|
||||
|
||||
if (extension->isConstrainedExtension()) {
|
||||
// Conditional conformances never apply to inherited protocols, nor
|
||||
// can they provide unconditional conformances that might be used in
|
||||
@@ -615,9 +625,9 @@ public:
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if ((nominal = dyn_cast<NominalTypeDecl>(D))) {
|
||||
memberContext = nominal;
|
||||
|
||||
} else if (auto *extension = dyn_cast<ExtensionDecl>(D)) {
|
||||
if (!shouldInclude(extension)) {
|
||||
return;
|
||||
@@ -697,6 +707,9 @@ public:
|
||||
const PrintOptions &printOptions,
|
||||
ModuleDecl *M,
|
||||
const NominalTypeDecl *nominal) const {
|
||||
PrettyStackTraceDecl stackTrace("printing synthesized extensions for",
|
||||
nominal);
|
||||
|
||||
if (ExtraProtocols.empty())
|
||||
return;
|
||||
|
||||
@@ -881,6 +894,8 @@ const StringLiteral InheritedProtocolCollector::DummyProtocolName =
|
||||
bool swift::emitSwiftInterface(raw_ostream &out,
|
||||
ModuleInterfaceOptions const &Opts,
|
||||
ModuleDecl *M) {
|
||||
PrettyStackTraceDecl stackTrace("emitting swiftinterface for", M);
|
||||
|
||||
assert(M);
|
||||
|
||||
llvm::SmallSet<StringRef, 4> aliasModuleNamesTargets;
|
||||
|
||||
7
test/ModuleInterface/lazy-typecheck-errors.swift
Normal file
7
test/ModuleInterface/lazy-typecheck-errors.swift
Normal file
@@ -0,0 +1,7 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-swift-emit-module-interface(%t/Test.swiftinterface) -module-name Test %s -experimental-lazy-typecheck -verify
|
||||
|
||||
extension DoesNotExist { // expected-error {{cannot find type 'DoesNotExist' in scope}}
|
||||
public func method() {}
|
||||
}
|
||||
@@ -32,3 +32,7 @@ public var varWithImplicitInvalidType = (1 as InvalidType)
|
||||
// expected-serialization-remark@-3 {{serialization skipped for invalid type}}
|
||||
|
||||
public var _: InvalidType
|
||||
|
||||
extension InvalidType {
|
||||
public func method() {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user