mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[CSSimplify] Specialization: Fix a crash when specialized declaration is not generic
Check whether there are any opened generic parameters associated with a declaration and if not, produce a fix which would be later diagnosed as either a warning (in Swift 5 mode) or an error (if it was a concrete type or the compiler is in Swift 6 language mode). Resolves: rdar://135610320
This commit is contained in:
@@ -13868,6 +13868,23 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
|
||||
return genericParams;
|
||||
};
|
||||
|
||||
auto fixInvalidSpecialization = [&](ValueDecl *decl) -> SolutionKind {
|
||||
if (isa<AbstractFunctionDecl>(decl)) {
|
||||
return recordFix(AllowFunctionSpecialization::create(
|
||||
*this, decl, getConstraintLocator(locator)))
|
||||
? SolutionKind::Error
|
||||
: SolutionKind::Solved;
|
||||
}
|
||||
|
||||
// Allow concrete macros to have specializations with just a warning.
|
||||
return recordFix(AllowConcreteTypeSpecialization::create(
|
||||
*this, type1, decl, getConstraintLocator(locator),
|
||||
isa<MacroDecl>(decl) ? FixBehavior::DowngradeToWarning
|
||||
: FixBehavior::Error))
|
||||
? SolutionKind::Error
|
||||
: SolutionKind::Solved;
|
||||
};
|
||||
|
||||
ValueDecl *decl;
|
||||
SmallVector<OpenedType, 2> openedTypes;
|
||||
if (auto *bound = dyn_cast<TypeAliasType>(type1.getPointer())) {
|
||||
@@ -13926,6 +13943,12 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
|
||||
decl = overloadChoice.getDecl();
|
||||
|
||||
auto openedOverloadTypes = getOpenedTypes(overloadLocator);
|
||||
// Attempting to specialize a non-generic declaration.
|
||||
if (openedOverloadTypes.empty()) {
|
||||
// Note that this is unconditional because the fix is
|
||||
// downgraded to a warning in swift language modes < 6.
|
||||
return fixInvalidSpecialization(decl);
|
||||
}
|
||||
|
||||
auto genericParams = getGenericParams(decl);
|
||||
if (genericParams) {
|
||||
@@ -13941,22 +13964,8 @@ ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
|
||||
}
|
||||
|
||||
auto genericParams = getGenericParams(decl);
|
||||
if (!decl->getAsGenericContext() || !genericParams) {
|
||||
if (isa<AbstractFunctionDecl>(decl)) {
|
||||
return recordFix(AllowFunctionSpecialization::create(
|
||||
*this, decl, getConstraintLocator(locator)))
|
||||
? SolutionKind::Error
|
||||
: SolutionKind::Solved;
|
||||
}
|
||||
|
||||
// Allow concrete macros to have specializations with just a warning.
|
||||
return recordFix(AllowConcreteTypeSpecialization::create(
|
||||
*this, type1, decl, getConstraintLocator(locator),
|
||||
isa<MacroDecl>(decl) ? FixBehavior::DowngradeToWarning
|
||||
: FixBehavior::Error))
|
||||
? SolutionKind::Error
|
||||
: SolutionKind::Solved;
|
||||
}
|
||||
if (!decl->getAsGenericContext() || !genericParams)
|
||||
return fixInvalidSpecialization(decl);
|
||||
|
||||
// Map the generic parameters we have over to their opened types.
|
||||
bool hasParameterPack = false;
|
||||
|
||||
76
test/Constraints/specialization_with_shadowing.swift
Normal file
76
test/Constraints/specialization_with_shadowing.swift
Normal file
@@ -0,0 +1,76 @@
|
||||
// RUN: %empty-directory(%t/src)
|
||||
// RUN: split-file %s %t/src
|
||||
|
||||
/// Build the library A
|
||||
// RUN: %target-swift-frontend -emit-module %t/src/A.swift \
|
||||
// RUN: -module-name A -swift-version 5 -enable-library-evolution \
|
||||
// RUN: -emit-module-path %t/A.swiftmodule \
|
||||
// RUN: -emit-module-interface-path %t/A.swiftinterface
|
||||
|
||||
/// Build the library B
|
||||
// RUN: %target-swift-frontend -emit-module %t/src/B.swift \
|
||||
// RUN: -module-name B -swift-version 5 -enable-library-evolution \
|
||||
// RUN: -emit-module-path %t/B.swiftmodule \
|
||||
// RUN: -emit-module-interface-path %t/B.swiftinterface
|
||||
|
||||
// Build the client AB (language mode 5)
|
||||
// RUN: %target-swift-frontend -emit-module %t/src/ClientAB.swift \
|
||||
// RUN: -module-name Client -I %t -swift-version 5 \
|
||||
// RUN: -verify
|
||||
|
||||
// Build the client AB (language mode 6)
|
||||
// RUN: %target-swift-frontend -emit-module %t/src/ClientAB.swift \
|
||||
// RUN: -module-name Client -I %t -swift-version 6 \
|
||||
// RUN: -verify
|
||||
|
||||
// Build the client BA (language mode 5)
|
||||
// RUN: %target-swift-frontend -emit-module %t/src/ClientBA.swift \
|
||||
// RUN: -module-name Client -I %t -swift-version 5 \
|
||||
// RUN: -verify
|
||||
|
||||
// Build the client BA (language mode 6)
|
||||
// RUN: %target-swift-frontend -emit-module %t/src/ClientBA.swift \
|
||||
// RUN: -module-name Client -I %t -swift-version 6 \
|
||||
// RUN: -verify
|
||||
|
||||
//--- A.swift
|
||||
public protocol EventSource {
|
||||
}
|
||||
|
||||
//--- B.swift
|
||||
public struct Event<T> {
|
||||
}
|
||||
|
||||
public class EventSource<Parameter> {
|
||||
public var event: Event<Parameter> {
|
||||
fatalError()
|
||||
}
|
||||
|
||||
public init() {}
|
||||
}
|
||||
|
||||
//--- ClientAB.swift
|
||||
import B
|
||||
// Note: import order is important in this case because successful match might
|
||||
// mean that the other overload is not going to be attempted and we want
|
||||
// to attempt protocol EventSource always.
|
||||
import A
|
||||
|
||||
func test() {
|
||||
let test: B.Event<Void>
|
||||
test = EventSource<Void>().event
|
||||
print(test)
|
||||
}
|
||||
|
||||
//--- ClientBA.swift
|
||||
import B
|
||||
// Note: import order is important in this case because successful match might
|
||||
// mean that the other overload is not going to be attempted and we want
|
||||
// to attempt protocol EventSource always.
|
||||
import A
|
||||
|
||||
func test() {
|
||||
let test: B.Event<Void>
|
||||
test = EventSource<Void>().event
|
||||
print(test)
|
||||
}
|
||||
Reference in New Issue
Block a user