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
|
/// in source control, you should also update the comment to briefly
|
||||||
/// describe what change you made. The content of this comment isn't important;
|
/// 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.
|
/// 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>;
|
using DeclIDField = BCFixed<31>;
|
||||||
|
|
||||||
@@ -819,7 +819,8 @@ namespace decls_block {
|
|||||||
TypeIDField, // interface type (no longer used)
|
TypeIDField, // interface type (no longer used)
|
||||||
BCFixed<1>, // implicit flag
|
BCFixed<1>, // implicit flag
|
||||||
GenericEnvironmentIDField, // generic environment
|
GenericEnvironmentIDField, // generic environment
|
||||||
AccessLevelField // access level
|
AccessLevelField, // access level
|
||||||
|
BCArray<TypeIDField> // dependency types
|
||||||
// Trailed by generic parameters (if any).
|
// Trailed by generic parameters (if any).
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
|||||||
@@ -2514,11 +2514,22 @@ ModuleFile::getDeclCheckedImpl(DeclID DID, Optional<DeclContext *> ForcedContext
|
|||||||
bool isImplicit;
|
bool isImplicit;
|
||||||
GenericEnvironmentID genericEnvID;
|
GenericEnvironmentID genericEnvID;
|
||||||
uint8_t rawAccessLevel;
|
uint8_t rawAccessLevel;
|
||||||
|
ArrayRef<uint64_t> dependencyIDs;
|
||||||
|
|
||||||
decls_block::TypeAliasLayout::readRecord(scratch, nameID, contextID,
|
decls_block::TypeAliasLayout::readRecord(scratch, nameID, contextID,
|
||||||
underlyingTypeID, interfaceTypeID,
|
underlyingTypeID, interfaceTypeID,
|
||||||
isImplicit, genericEnvID,
|
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);
|
auto DC = ForcedContext ? *ForcedContext : getDeclContext(contextID);
|
||||||
|
|
||||||
@@ -2526,8 +2537,7 @@ ModuleFile::getDeclCheckedImpl(DeclID DID, Optional<DeclContext *> ForcedContext
|
|||||||
if (declOrOffset.isComplete())
|
if (declOrOffset.isComplete())
|
||||||
return declOrOffset;
|
return declOrOffset;
|
||||||
|
|
||||||
auto alias = createDecl<TypeAliasDecl>(SourceLoc(), SourceLoc(),
|
auto alias = createDecl<TypeAliasDecl>(SourceLoc(), SourceLoc(), name,
|
||||||
getIdentifier(nameID),
|
|
||||||
SourceLoc(), genericParams, DC);
|
SourceLoc(), genericParams, DC);
|
||||||
declOrOffset = alias;
|
declOrOffset = alias;
|
||||||
|
|
||||||
|
|||||||
@@ -2831,6 +2831,18 @@ void Serializer::writeDecl(const Decl *D) {
|
|||||||
|
|
||||||
auto underlying = typeAlias->getUnderlyingTypeLoc().getType();
|
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 =
|
uint8_t rawAccessLevel =
|
||||||
getRawStableAccessLevel(typeAlias->getFormalAccess());
|
getRawStableAccessLevel(typeAlias->getFormalAccess());
|
||||||
|
|
||||||
@@ -2843,7 +2855,8 @@ void Serializer::writeDecl(const Decl *D) {
|
|||||||
typeAlias->isImplicit(),
|
typeAlias->isImplicit(),
|
||||||
addGenericEnvironmentRef(
|
addGenericEnvironmentRef(
|
||||||
typeAlias->getGenericEnvironment()),
|
typeAlias->getGenericEnvironment()),
|
||||||
rawAccessLevel);
|
rawAccessLevel,
|
||||||
|
dependencies);
|
||||||
writeGenericParams(typeAlias->getGenericParams());
|
writeGenericParams(typeAlias->getGenericParams());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,12 @@ let _ = unwrapped // okay
|
|||||||
_ = usesWrapped(nil) // expected-error {{use of unresolved identifier 'usesWrapped'}}
|
_ = usesWrapped(nil) // expected-error {{use of unresolved identifier 'usesWrapped'}}
|
||||||
_ = usesUnwrapped(nil) // expected-error {{nil is not compatible with expected argument type 'Int32'}}
|
_ = 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) {
|
func testExtensions(wrapped: WrappedInt, unwrapped: UnwrappedInt) {
|
||||||
wrapped.wrappedMethod() // expected-error {{value of type 'WrappedInt' (aka 'Int32') has no member 'wrappedMethod'}}
|
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'}}
|
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 WrappedProto {}
|
||||||
public protocol UnwrappedProto {}
|
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
|
#endif // TEST
|
||||||
|
|||||||
Reference in New Issue
Block a user