[Serialization] Recover if a typealias's underlying type is broken (#12979)

We could handle a typealias itself disappearing, but not if the
typealias was okay but the underlying type wasn't. This came up in
real Swift 3/4 mix-and-match code.

rdar://problem/34940079
This commit is contained in:
Jordan Rose
2017-11-16 19:31:13 -08:00
committed by GitHub
parent dbce0409ce
commit ac6fd7214e
4 changed files with 42 additions and 6 deletions

View File

@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
/// in source control, you should also update the comment to briefly
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
const uint16_t VERSION_MINOR = 386; // Last change: @callee_guaranted closures
const uint16_t VERSION_MINOR = 387; // Last change: dependencies for typealiases
using DeclIDField = BCFixed<31>;
@@ -819,7 +819,8 @@ namespace decls_block {
TypeIDField, // interface type (no longer used)
BCFixed<1>, // implicit flag
GenericEnvironmentIDField, // generic environment
AccessLevelField // access level
AccessLevelField, // access level
BCArray<TypeIDField> // dependency types
// Trailed by generic parameters (if any).
>;

View File

@@ -2514,11 +2514,22 @@ ModuleFile::getDeclCheckedImpl(DeclID DID, Optional<DeclContext *> ForcedContext
bool isImplicit;
GenericEnvironmentID genericEnvID;
uint8_t rawAccessLevel;
ArrayRef<uint64_t> dependencyIDs;
decls_block::TypeAliasLayout::readRecord(scratch, nameID, contextID,
underlyingTypeID, interfaceTypeID,
isImplicit, genericEnvID,
rawAccessLevel);
rawAccessLevel, dependencyIDs);
Identifier name = getIdentifier(nameID);
for (TypeID dependencyID : dependencyIDs) {
auto dependency = getTypeChecked(dependencyID);
if (!dependency) {
return llvm::make_error<TypeError>(
name, takeErrorInfo(dependency.takeError()));
}
}
auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID);
@@ -2526,8 +2537,7 @@ ModuleFile::getDeclCheckedImpl(DeclID DID, Optional<DeclContext *> ForcedContext
if (declOrOffset.isComplete())
return declOrOffset;
auto alias = createDecl<TypeAliasDecl>(SourceLoc(), SourceLoc(),
getIdentifier(nameID),
auto alias = createDecl<TypeAliasDecl>(SourceLoc(), SourceLoc(), name,
SourceLoc(), genericParams, DC);
declOrOffset = alias;

View File

@@ -2831,6 +2831,18 @@ void Serializer::writeDecl(const Decl *D) {
auto underlying = typeAlias->getUnderlyingTypeLoc().getType();
SmallVector<TypeID, 2> dependencies;
for (Type dep : collectDependenciesFromType(underlying->getCanonicalType()))
dependencies.push_back(addTypeRef(dep));
for (Requirement req : typeAlias->getGenericRequirements()) {
for (Type dep : collectDependenciesFromType(req.getFirstType()))
dependencies.push_back(addTypeRef(dep));
if (req.getKind() != RequirementKind::Layout)
for (Type dep : collectDependenciesFromType(req.getSecondType()))
dependencies.push_back(addTypeRef(dep));
}
uint8_t rawAccessLevel =
getRawStableAccessLevel(typeAlias->getFormalAccess());
@@ -2843,7 +2855,8 @@ void Serializer::writeDecl(const Decl *D) {
typeAlias->isImplicit(),
addGenericEnvironmentRef(
typeAlias->getGenericEnvironment()),
rawAccessLevel);
rawAccessLevel,
dependencies);
writeGenericParams(typeAlias->getGenericParams());
break;
}

View File

@@ -52,6 +52,12 @@ let _ = unwrapped // okay
_ = usesWrapped(nil) // expected-error {{use of unresolved identifier 'usesWrapped'}}
_ = usesUnwrapped(nil) // expected-error {{nil is not compatible with expected argument type 'Int32'}}
let _: WrappedAlias = nil // expected-error {{use of undeclared type 'WrappedAlias'}}
let _: UnwrappedAlias = nil // expected-error {{nil cannot initialize specified type 'UnwrappedAlias' (aka 'Int32')}} expected-note {{add '?'}}
let _: ConstrainedWrapped<Int> = nil // expected-error {{use of undeclared type 'ConstrainedWrapped'}}
let _: ConstrainedUnwrapped<Int> = nil // expected-error {{type 'Int' does not conform to protocol 'HasAssoc'}}
func testExtensions(wrapped: WrappedInt, unwrapped: UnwrappedInt) {
wrapped.wrappedMethod() // expected-error {{value of type 'WrappedInt' (aka 'Int32') has no member 'wrappedMethod'}}
unwrapped.unwrappedMethod() // expected-error {{value of type 'UnwrappedInt' has no member 'unwrappedMethod'}}
@@ -344,4 +350,10 @@ public func returnsWrappedGeneric<T>(_: T.Type) -> WrappedInt { fatalError() }
public protocol WrappedProto {}
public protocol UnwrappedProto {}
public typealias WrappedAlias = WrappedInt
public typealias UnwrappedAlias = UnwrappedInt
public typealias ConstrainedWrapped<T: HasAssoc> = T where T.Assoc == WrappedInt
public typealias ConstrainedUnwrapped<T: HasAssoc> = T where T.Assoc == UnwrappedInt
#endif // TEST