mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[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:
@@ -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).
|
||||
>;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user