diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 7beb6644996d0..57d261a0e05e1 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -839,8 +839,8 @@ void SILGenModule::emitDifferentiabilityWitness( SILDifferentiabilityWitnessKey key{originalFunction->getName(), silConfig}; auto *diffWitness = M.lookUpDifferentiabilityWitness(key); if (!diffWitness) { - // Strip external from linkage of original function. - // Necessary for Clang-imported functions, which have external linkage. + // Differentiability witnesses have the same linkage as the original + // function, stripping external. auto linkage = stripExternalFromLinkage(originalFunction->getLinkage()); diffWitness = SILDifferentiabilityWitness::createDefinition( M, linkage, originalFunction, silConfig.parameterIndices, diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp index 6e7a8f353897f..3134c36c7305a 100644 --- a/lib/SILGen/SILGenPoly.cpp +++ b/lib/SILGen/SILGenPoly.cpp @@ -3941,14 +3941,17 @@ SILFunction *SILGenModule::getOrCreateCustomDerivativeThunk( auto loc = customDerivativeFn->getLocation(); SILGenFunctionBuilder fb(*this); - // This thunk is publicly exposed and cannot be transparent. - // Instead, mark it as "always inline" for optimization. + // Derivative thunks have the same linkage as the original function, stripping + // external. + auto linkage = stripExternalFromLinkage(originalFn->getLinkage()); auto *thunk = fb.getOrCreateFunction( - loc, name, customDerivativeFn->getLinkage(), thunkFnTy, IsBare, - IsNotTransparent, customDerivativeFn->isSerialized(), + loc, name, linkage, thunkFnTy, IsBare, IsNotTransparent, + customDerivativeFn->isSerialized(), customDerivativeFn->isDynamicallyReplaceable(), customDerivativeFn->getEntryCount(), IsThunk, customDerivativeFn->getClassSubclassScope()); + // This thunk may be publicly exposed and cannot be transparent. + // Instead, mark it as "always inline" for optimization. thunk->setInlineStrategy(AlwaysInline); if (!thunk->empty()) return thunk; diff --git a/test/AutoDiff/Sema/derivative_attr_type_checking.swift b/test/AutoDiff/Sema/derivative_attr_type_checking.swift index 803bcddf81f85..dd362a220d2a4 100644 --- a/test/AutoDiff/Sema/derivative_attr_type_checking.swift +++ b/test/AutoDiff/Sema/derivative_attr_type_checking.swift @@ -837,6 +837,27 @@ fileprivate func _fileprivate_original_fileprivate_derivative(_ x: Float) -> (va fatalError() } +func internal_original_usablefrominline_derivative(_ x: Float) -> Float { x } +@usableFromInline +@derivative(of: internal_original_usablefrominline_derivative) +func _internal_original_usablefrominline_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) { + fatalError() +} + +func internal_original_inlinable_derivative(_ x: Float) -> Float { x } +@inlinable +@derivative(of: internal_original_inlinable_derivative) +func _internal_original_inlinable_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) { + fatalError() +} + +func internal_original_alwaysemitintoclient_derivative(_ x: Float) -> Float { x } +@_alwaysEmitIntoClient +@derivative(of: internal_original_alwaysemitintoclient_derivative) +func _internal_original_alwaysemitintoclient_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) { + fatalError() +} + // MARK: - Original function visibility < derivative function visibility @usableFromInline diff --git a/test/AutoDiff/compiler_crashers_fixed/tf1160-derivative-usable-from-inline-mismatch.swift b/test/AutoDiff/compiler_crashers_fixed/tf1160-derivative-usable-from-inline-mismatch.swift new file mode 100644 index 0000000000000..f416264bd0e70 --- /dev/null +++ b/test/AutoDiff/compiler_crashers_fixed/tf1160-derivative-usable-from-inline-mismatch.swift @@ -0,0 +1,19 @@ +// RUN: %target-swift-frontend -c %s -verify +// REQUIRES: asserts + +// TF-1160: Linker error for `@usableFromInline` derivative function but +// non-`@usableFromInline` internal original function. + +import _Differentiation + +func internalOriginal(_ x: Float) -> Float { x } + +@usableFromInline +@derivative(of: internalOriginal) +func usableFromInlineDerivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) { + (x, { $0 }) +} + +// Original error: type-checking passes but TBDGen is not consistent with IRGen. +// :0: error: symbol 'AD__$s4main16internalOriginalyS2fF__vjp_src_0_wrt_0' (AD__$s4main16internalOriginalyS2fF__vjp_src_0_wrt_0) is in generated IR file, but not in TBD file +// :0: error: please file a radar or open a bug on bugs.swift.org with this code, and add -Xfrontend -validate-tbd-against-ir=none to squash the errors