From 0b265b041d48db9570ca9025ce45c750dd866bf1 Mon Sep 17 00:00:00 2001 From: Philip Turner Date: Wed, 2 Feb 2022 21:52:50 -0500 Subject: [PATCH 01/12] Debugging branch (#7) * a commit * another commit * Update lib/Sema/TypeCheckType.cpp * Update lib/Sema/TypeCheckType.cpp --- lib/AST/Type.cpp | 5 ++--- lib/Sema/TypeChecker.cpp | 9 +++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index cecaa0bec6cc8..641a3dbc91c21 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -6178,7 +6178,7 @@ TypeBase::getAutoDiffTangentSpace(LookupConformanceFn lookupConformance) { return tangentSpace; }; - // For tuple types: the tangent space is a tuple of the elements' tangent + // For tuple types: the tangent space is a tuple of the elements' tangent // space types, for the elements that have a tangent space. if (auto *tupleTy = getAs()) { SmallVector newElts; @@ -6189,8 +6189,7 @@ TypeBase::getAutoDiffTangentSpace(LookupConformanceFn lookupConformance) { newElts.push_back(elt.getWithType(eltSpace->getType())); } if (newElts.empty()) - return cache( - TangentSpace::getTuple(ctx.TheEmptyTupleType->castTo())); + return cache(None); if (newElts.size() == 1) return cache(TangentSpace::getTangentVector(newElts.front().getType())); auto *tupleType = TupleType::get(newElts, ctx)->castTo(); diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 32d2a293f9b05..e47e8e48481ae 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -619,13 +619,17 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, dc, stage); }) != params.end(); bool alreadyDiagnosedOneParam = false; + bool hasInoutDiffParameter = false; for (unsigned i = 0, end = fnTy->getNumParams(); i != end; ++i) { auto param = params[i]; if (param.isNoDerivative()) continue; auto paramType = param.getPlainType(); - if (TypeChecker::isDifferentiable(paramType, isLinear, dc, stage)) + if (TypeChecker::isDifferentiable(paramType, isLinear, dc, stage)) { + if (param.isInOut()) + hasInoutDiffParameter = true; continue; + } auto diagLoc = repr ? (*repr)->getArgsTypeRepr()->getElement(i).Type->getLoc() : loc; auto paramTypeString = paramType->getString(); @@ -654,7 +658,8 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, // Check the result bool differentiable = isDifferentiable(result, /*tangentVectorEqualsSelf*/ isLinear, - dc, stage); + dc, stage) ^ hasInoutDiffParameter; + // TODO: make the error cleaner if (!differentiable) { auto diagLoc = repr ? (*repr)->getResultTypeRepr()->getLoc() : loc; auto resultStr = fnTy->getResult()->getString(); From b64c7dcde624f77a8e0c8cb629a5b3dbe7ba31a8 Mon Sep 17 00:00:00 2001 From: Philip Turner <71743241+philipturner@users.noreply.github.com> Date: Thu, 3 Feb 2022 07:16:46 -0500 Subject: [PATCH 02/12] Can't get tangent space of void anymore --- include/swift/AST/AutoDiff.h | 4 +--- lib/AST/AutoDiff.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/swift/AST/AutoDiff.h b/include/swift/AST/AutoDiff.h index 3bcdc5dc0852e..45c74263ff9f1 100644 --- a/include/swift/AST/AutoDiff.h +++ b/include/swift/AST/AutoDiff.h @@ -364,9 +364,7 @@ class TangentSpace { static TangentSpace getTangentVector(Type tangentVectorType) { return {Kind::TangentVector, tangentVectorType}; } - static TangentSpace getTuple(TupleType *tupleTy) { - return {Kind::Tuple, tupleTy}; - } + static TangentSpace getTuple(TupleType *tupleTy); bool isTangentVector() const { return kind == Kind::TangentVector; } bool isTuple() const { return kind == Kind::Tuple; } diff --git a/lib/AST/AutoDiff.cpp b/lib/AST/AutoDiff.cpp index 60a49b43e304f..c2168c999f581 100644 --- a/lib/AST/AutoDiff.cpp +++ b/lib/AST/AutoDiff.cpp @@ -366,6 +366,13 @@ GenericSignature autodiff::getDifferentiabilityWitnessGenericSignature( return derivativeGenSig; } +TangentSpace TangentSpace::getTuple(TupleType *tupleTy) { + if (tupleTy->getElements().size() == 0) { + llvm::report_fatal_error("Attempted to get tangent space of emtpy tuple."); + } + return {Kind::Tuple, tupleTy}; +} + Type TangentSpace::getType() const { switch (kind) { case Kind::TangentVector: From f293cee69da39d3191c3632cb05a7ae822199fcf Mon Sep 17 00:00:00 2001 From: Philip Turner <71743241+philipturner@users.noreply.github.com> Date: Thu, 3 Feb 2022 07:19:17 -0500 Subject: [PATCH 03/12] Fix typo --- lib/AST/AutoDiff.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/AST/AutoDiff.cpp b/lib/AST/AutoDiff.cpp index c2168c999f581..1a68da526ecb3 100644 --- a/lib/AST/AutoDiff.cpp +++ b/lib/AST/AutoDiff.cpp @@ -368,7 +368,7 @@ GenericSignature autodiff::getDifferentiabilityWitnessGenericSignature( TangentSpace TangentSpace::getTuple(TupleType *tupleTy) { if (tupleTy->getElements().size() == 0) { - llvm::report_fatal_error("Attempted to get tangent space of emtpy tuple."); + llvm::report_fatal_error("Attempted to get tangent space of empty tuple."); } return {Kind::Tuple, tupleTy}; } From 9dbe874f2dfa9d52f85231955183b28d8dd19651 Mon Sep 17 00:00:00 2001 From: Philip Turner <71743241+philipturner@users.noreply.github.com> Date: Thu, 3 Feb 2022 15:15:30 -0500 Subject: [PATCH 04/12] Fix some stuff --- lib/AST/AutoDiff.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/AST/AutoDiff.cpp b/lib/AST/AutoDiff.cpp index 1a68da526ecb3..db13456d546bc 100644 --- a/lib/AST/AutoDiff.cpp +++ b/lib/AST/AutoDiff.cpp @@ -367,9 +367,9 @@ GenericSignature autodiff::getDifferentiabilityWitnessGenericSignature( } TangentSpace TangentSpace::getTuple(TupleType *tupleTy) { - if (tupleTy->getElements().size() == 0) { - llvm::report_fatal_error("Attempted to get tangent space of empty tuple."); - } + assert(!tupleTy->isVoid() && + "Attempted to get tangent space of 'Void', which cannot be " + "differentiated."); return {Kind::Tuple, tupleTy}; } From a5691a60a3ab2d329a84979fc316f3bfb8b8cd05 Mon Sep 17 00:00:00 2001 From: Philip Turner <71743241+philipturner@users.noreply.github.com> Date: Thu, 3 Feb 2022 15:21:46 -0500 Subject: [PATCH 05/12] Clean up conditional --- lib/Sema/TypeChecker.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index e47e8e48481ae..b58fa59ccc75f 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -656,11 +656,12 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, } // Check the result - bool differentiable = isDifferentiable(result, - /*tangentVectorEqualsSelf*/ isLinear, - dc, stage) ^ hasInoutDiffParameter; + bool resultIsDifferentiable = + isDifferentiable(result, + /*tangentVectorEqualsSelf*/ isLinear, + dc, stage); // TODO: make the error cleaner - if (!differentiable) { + if (resultIsDifferentiable == hasInoutDiffParameter) { auto diagLoc = repr ? (*repr)->getResultTypeRepr()->getLoc() : loc; auto resultStr = fnTy->getResult()->getString(); auto diag = ctx.Diags.diagnose( From ed830e8f06200738175f9295a436ae7c3568f3d2 Mon Sep 17 00:00:00 2001 From: Philip Turner <71743241+philipturner@users.noreply.github.com> Date: Thu, 3 Feb 2022 16:58:31 -0500 Subject: [PATCH 06/12] Add real diagnostic --- include/swift/AST/DiagnosticsSema.def | 3 +++ lib/Sema/TypeChecker.cpp | 28 ++++++++++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 14810a84256bb..d3697d312fba1 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -5040,6 +5040,9 @@ ERROR(differentiable_function_type_invalid_result,none, "%select{| and satisfy '%0 == %0.TangentVector'}1, but the enclosing " "function type is '@differentiable%select{|(_linear)}1'", (StringRef, bool)) +ERROR(differentiable_function_type_multiple_semantic_results,none, + "'@differentiable' function type cannot have both an 'inout' parameter " + "and a differentiable result", ()) ERROR(differentiable_function_type_no_differentiability_parameters, none, "'@differentiable' function type requires at least one differentiability " diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index b58fa59ccc75f..f76c259f5a39f 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -641,6 +641,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, if (hasValidDifferentiabilityParam) diagnostic.fixItInsert(diagLoc, "@noDerivative "); } + // Reject the case where all parameters have '@noDerivative'. if (!alreadyDiagnosedOneParam && !hasValidDifferentiabilityParam) { auto diagLoc = repr ? (*repr)->getArgsTypeRepr()->getLoc() : loc; @@ -655,20 +656,33 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, } } - // Check the result + // Check the result. bool resultIsDifferentiable = - isDifferentiable(result, - /*tangentVectorEqualsSelf*/ isLinear, - dc, stage); - // TODO: make the error cleaner - if (resultIsDifferentiable == hasInoutDiffParameter) { + isDifferentiable(result, /*tangentVectorEqualsSelf*/ isLinear, dc, + stage); + + // Reject the case where there are multiple semantic results. + if (resultIsDifferentiable && hasInoutDiffParameter) { + auto diagLoc = repr ? (*repr)->getArgsTypeRepr()->getLoc() : loc; + auto diag = ctx.Diags.diagnose( + diagLoc, + diag::differentiable_function_type_multiple_semantic_results); + hadAnyError = true; + + if (repr) { + diag.highlight((*repr)->getSourceRange()); + } + } + + // Reject the case where there are no semantic results. + if (!resultIsDifferentiable && !hasInoutDiffParameter) { auto diagLoc = repr ? (*repr)->getResultTypeRepr()->getLoc() : loc; auto resultStr = fnTy->getResult()->getString(); auto diag = ctx.Diags.diagnose( diagLoc, diag::differentiable_function_type_invalid_result, resultStr, isLinear); hadAnyError = true; - + if (repr) { diag.highlight((*repr)->getResultTypeRepr()->getSourceRange()); } From d5f1beeea714de9c36c2f8a374f4517a56853a00 Mon Sep 17 00:00:00 2001 From: Philip Turner <71743241+philipturner@users.noreply.github.com> Date: Thu, 3 Feb 2022 17:03:01 -0500 Subject: [PATCH 07/12] Fix whitespace issues --- lib/Sema/TypeChecker.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index f76c259f5a39f..1f9e4beb01562 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -641,7 +641,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, if (hasValidDifferentiabilityParam) diagnostic.fixItInsert(diagLoc, "@noDerivative "); } - + // Reject the case where all parameters have '@noDerivative'. if (!alreadyDiagnosedOneParam && !hasValidDifferentiabilityParam) { auto diagLoc = repr ? (*repr)->getArgsTypeRepr()->getLoc() : loc; @@ -660,7 +660,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, bool resultIsDifferentiable = isDifferentiable(result, /*tangentVectorEqualsSelf*/ isLinear, dc, stage); - + // Reject the case where there are multiple semantic results. if (resultIsDifferentiable && hasInoutDiffParameter) { auto diagLoc = repr ? (*repr)->getArgsTypeRepr()->getLoc() : loc; @@ -668,12 +668,12 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, diagLoc, diag::differentiable_function_type_multiple_semantic_results); hadAnyError = true; - + if (repr) { diag.highlight((*repr)->getSourceRange()); } } - + // Reject the case where there are no semantic results. if (!resultIsDifferentiable && !hasInoutDiffParameter) { auto diagLoc = repr ? (*repr)->getResultTypeRepr()->getLoc() : loc; @@ -682,7 +682,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, diagLoc, diag::differentiable_function_type_invalid_result, resultStr, isLinear); hadAnyError = true; - + if (repr) { diag.highlight((*repr)->getResultTypeRepr()->getSourceRange()); } From 566e552f1f901883e07ba5a771906cae53cf8c84 Mon Sep 17 00:00:00 2001 From: Philip Turner <71743241+philipturner@users.noreply.github.com> Date: Thu, 3 Feb 2022 17:43:03 -0500 Subject: [PATCH 08/12] Add test 1/2 --- ...on-differentiable-closure-parameters.swift | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 test/AutoDiff/compiler_crashers_fixed/sr15808-non-differentiable-closure-parameters.swift diff --git a/test/AutoDiff/compiler_crashers_fixed/sr15808-non-differentiable-closure-parameters.swift b/test/AutoDiff/compiler_crashers_fixed/sr15808-non-differentiable-closure-parameters.swift new file mode 100644 index 0000000000000..e203868e37baa --- /dev/null +++ b/test/AutoDiff/compiler_crashers_fixed/sr15808-non-differentiable-closure-parameters.swift @@ -0,0 +1,61 @@ +// RUN: %target-swift-frontend -emit-sil -verify %s + +// SR-15808: In AST, type checking skips a closure with non-differentiable input +// where `Void` is included as a parameter without being marked `@noDerivative`. +// It also crashes when the output is `Void` and no input is `inout`. As a +// result, the compiler crashes during Sema. + +import _Differentiation + +// expected-error @+2 {{parameter type '()' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} +// expected-error @+1 {{result type 'Void' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} +func helloWorld(_ x: @differentiable(reverse) (()) -> Void) {} + +// expected-error @+1 {{parameter type '()' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} +func helloWorld(_ x: @differentiable(reverse) (()) -> Float) {} + +// expected-error @+1 {{result type 'Void' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} +func helloWorld(_ x: @differentiable(reverse) (Float) -> Void) {} + +// expected-error @+1 {{parameter type 'Void' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} +func helloWorld(_ x: @differentiable(reverse) (@noDerivative Float, Void) -> Float) {} + +// Original crash: +// Assertion failed: (!parameterIndices->isEmpty() && "Parameter indices must not be empty"), function getAutoDiffDerivativeFunctionType, file SILFunctionType.cpp, line 800. +// Stack dump: +// ... +// 1. Apple Swift version 5.6-dev (LLVM 7b20e61dd04138a, Swift 9438cf6b2e83c5f) +// 2. Compiling with the current language version +// 3. While evaluating request ASTLoweringRequest(Lowering AST to SIL for file "/Users/philipturner/Desktop/Experimentation4/Experimentation4/main.swift") +// Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it): +// 0 swift-frontend 0x0000000108d7a5c0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56 +// 1 swift-frontend 0x0000000108d79820 llvm::sys::RunSignalHandlers() + 128 +// 2 swift-frontend 0x0000000108d7ac24 SignalHandler(int) + 304 +// 3 libsystem_platform.dylib 0x00000001bb5304e4 _sigtramp + 56 +// 4 libsystem_pthread.dylib 0x00000001bb518eb0 pthread_kill + 288 +// 5 libsystem_c.dylib 0x00000001bb456314 abort + 164 +// 6 libsystem_c.dylib 0x00000001bb45572c err + 0 +// 7 swift-frontend 0x0000000108d9ae3c swift::SILFunctionType::getAutoDiffDerivativeFunctionType(swift::IndexSubset*, swift::IndexSubset*, swift::AutoDiffDerivativeFunctionKind, swift::Lowering::TypeConverter&, llvm::function_ref, swift::CanGenericSignature, bool, swift::CanType) (.cold.3) + 0 +// 8 swift-frontend 0x0000000104abc35c swift::SILFunctionType::getAutoDiffDerivativeFunctionType(swift::IndexSubset*, swift::IndexSubset*, swift::AutoDiffDerivativeFunctionKind, swift::Lowering::TypeConverter&, llvm::function_ref, swift::CanGenericSignature, bool, swift::CanType) + 152 +// 9 swift-frontend 0x0000000104b496cc (anonymous namespace)::TypeClassifierBase<(anonymous namespace)::LowerType, swift::Lowering::TypeLowering*>::getNormalDifferentiableSILFunctionTypeRecursiveProperties(swift::CanTypeWrapper, swift::Lowering::AbstractionPattern) + 184 +// 10 swift-frontend 0x0000000104b3b72c swift::CanTypeVisitor<(anonymous namespace)::LowerType, swift::Lowering::TypeLowering*, swift::Lowering::AbstractionPattern, swift::Lowering::IsTypeExpansionSensitive_t>::visit(swift::CanType, swift::Lowering::AbstractionPattern, swift::Lowering::IsTypeExpansionSensitive_t) + 1980 +// 11 swift-frontend 0x0000000104b3c0e0 swift::Lowering::TypeConverter::getTypeLoweringForLoweredType(swift::Lowering::AbstractionPattern, swift::CanType, swift::TypeExpansionContext, swift::Lowering::IsTypeExpansionSensitive_t) + 648 +// 12 swift-frontend 0x0000000104b3ae08 swift::Lowering::TypeConverter::getTypeLowering(swift::Lowering::AbstractionPattern, swift::Type, swift::TypeExpansionContext) + 708 +// 13 swift-frontend 0x0000000104ac8544 (anonymous namespace)::DestructureInputs::visit(swift::ValueOwnership, bool, swift::Lowering::AbstractionPattern, swift::CanType, bool, bool) + 184 +// 14 swift-frontend 0x0000000104ac6a1c getSILFunctionType(swift::Lowering::TypeConverter&, swift::TypeExpansionContext, swift::Lowering::AbstractionPattern, swift::CanTypeWrapper, swift::SILExtInfoBuilder, (anonymous namespace)::Conventions const&, swift::ForeignInfo const&, llvm::Optional, llvm::Optional, llvm::Optional, swift::ProtocolConformanceRef, llvm::Optional) + 2584 +// 15 swift-frontend 0x0000000104ac5f98 getNativeSILFunctionType(swift::Lowering::TypeConverter&, swift::TypeExpansionContext, swift::Lowering::AbstractionPattern, swift::CanTypeWrapper, swift::SILExtInfoBuilder, llvm::Optional, llvm::Optional, llvm::Optional, swift::ProtocolConformanceRef, llvm::Optional)::$_12::operator()((anonymous namespace)::Conventions const&) const + 316 +// 16 swift-frontend 0x0000000104abf55c getNativeSILFunctionType(swift::Lowering::TypeConverter&, swift::TypeExpansionContext, swift::Lowering::AbstractionPattern, swift::CanTypeWrapper, swift::SILExtInfoBuilder, llvm::Optional, llvm::Optional, llvm::Optional, swift::ProtocolConformanceRef, llvm::Optional) + 508 +// 17 swift-frontend 0x0000000104ac0b44 getUncachedSILFunctionTypeForConstant(swift::Lowering::TypeConverter&, swift::TypeExpansionContext, swift::SILDeclRef, swift::Lowering::TypeConverter::LoweredFormalTypes) + 1920 +// 18 swift-frontend 0x0000000104ac1474 swift::Lowering::TypeConverter::getConstantInfo(swift::TypeExpansionContext, swift::SILDeclRef) + 216 +// 19 swift-frontend 0x0000000104ab9808 swift::SILFunctionBuilder::getOrCreateFunction(swift::SILLocation, swift::SILDeclRef, swift::ForDefinition_t, llvm::function_ref, swift::ProfileCounter) + 132 +// 20 swift-frontend 0x0000000104f1d120 swift::Lowering::SILGenModule::getFunction(swift::SILDeclRef, swift::ForDefinition_t) + 328 +// 21 swift-frontend 0x0000000104f2086c emitOrDelayFunction(swift::Lowering::SILGenModule&, swift::SILDeclRef, bool) + 344 +// 22 swift-frontend 0x0000000104f1d828 swift::Lowering::SILGenModule::emitFunction(swift::FuncDecl*) + 140 +// 23 swift-frontend 0x0000000104f2294c swift::ASTLoweringRequest::evaluate(swift::Evaluator&, swift::ASTLoweringDescriptor) const + 1612 +// 24 swift-frontend 0x0000000104fcbca4 swift::SimpleRequest > (swift::ASTLoweringDescriptor), (swift::RequestFlags)9>::evaluateRequest(swift::ASTLoweringRequest const&, swift::Evaluator&) + 156 +// 25 swift-frontend 0x0000000104f2647c llvm::Expected swift::Evaluator::getResultUncached(swift::ASTLoweringRequest const&) + 408 +// 26 swift-frontend 0x0000000104f233b0 swift::performASTLowering(swift::FileUnit&, swift::Lowering::TypeConverter&, swift::SILOptions const&) + 104 +// 27 swift-frontend 0x0000000104a12088 swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 496 +// 28 swift-frontend 0x0000000104a13d08 swift::performFrontend(llvm::ArrayRef, char const*, void*, swift::FrontendObserver*) + 2936 +// 29 swift-frontend 0x00000001049b213c swift::mainEntry(int, char const**) + 500 +// 30 dyld 0x00000001113c90f4 start + 520 From f4657661bd3655813270eacb4cb93cf6a3f1a1c6 Mon Sep 17 00:00:00 2001 From: Philip Turner <71743241+philipturner@users.noreply.github.com> Date: Thu, 3 Feb 2022 17:49:45 -0500 Subject: [PATCH 09/12] Add test 2/2 --- test/AutoDiff/Sema/differentiable_func_type.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/AutoDiff/Sema/differentiable_func_type.swift b/test/AutoDiff/Sema/differentiable_func_type.swift index 9ad3c19b4a8ba..7012c46bf3b2a 100644 --- a/test/AutoDiff/Sema/differentiable_func_type.swift +++ b/test/AutoDiff/Sema/differentiable_func_type.swift @@ -18,7 +18,6 @@ let _: @differentiable(reverse) (Float) throws -> Float struct NonDiffType { var x: Int } -// FIXME: Properly type-check parameters and the result's differentiability // expected-error @+1 {{parameter type 'NonDiffType' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} let _: @differentiable(reverse) (NonDiffType) -> Float @@ -41,6 +40,12 @@ let _: @differentiable(_linear) (Float) -> NonDiffType let _: @differentiable(_linear) (Float) -> Float +// expected-error @+1 {{'@differentiable' function type cannot have both an 'inout' parameter and a differentiable result}} +let _: @differentiable(reverse) (inout Float) -> Float + +// expected-error @+1 {{'@differentiable' function type cannot have both an 'inout' parameter and a differentiable result}} +let _: @differentiable(_linear) (inout Float) -> Float + // expected-error @+1 {{result type '@differentiable(reverse) (U) -> Float' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} func test1(_: @differentiable(reverse) (T) -> @differentiable(reverse) (U) -> Float) {} // expected-error @+1 {{result type '(U) -> Float' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} From 17f43eb4f403c9e48d6c93e968b33c68d9768f78 Mon Sep 17 00:00:00 2001 From: Philip Turner <71743241+philipturner@users.noreply.github.com> Date: Thu, 3 Feb 2022 19:35:18 -0500 Subject: [PATCH 10/12] Fix SR-15818 and add test --- include/swift/AST/DiagnosticsSema.def | 8 +-- .../Sema/derivative_attr_type_checking.swift | 6 +- .../differentiable_attr_type_checking.swift | 10 ++-- .../Sema/differentiable_func_type.swift | 4 +- ...inout-noderivative-closure-parameter.swift | 55 +++++++++++++++++++ 5 files changed, 69 insertions(+), 14 deletions(-) create mode 100644 test/AutoDiff/compiler_crashers_fixed/sr15818-inout-noderivative-closure-parameter.swift diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index d3697d312fba1..7c96656c21f24 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -3462,8 +3462,8 @@ NOTE(autodiff_attr_original_decl_not_same_type_context,none, ERROR(autodiff_attr_original_void_result,none, "cannot differentiate void function %0", (DeclName)) ERROR(autodiff_attr_original_multiple_semantic_results,none, - "cannot differentiate functions with both an 'inout' parameter and a " - "result", ()) + "cannot differentiate functions with both a differentiable 'inout' " + "parameter and a result", ()) ERROR(autodiff_attr_result_not_differentiable,none, "can only differentiate functions with results that conform to " "'Differentiable', but %0 does not conform to 'Differentiable'", (Type)) @@ -5041,8 +5041,8 @@ ERROR(differentiable_function_type_invalid_result,none, "function type is '@differentiable%select{|(_linear)}1'", (StringRef, bool)) ERROR(differentiable_function_type_multiple_semantic_results,none, - "'@differentiable' function type cannot have both an 'inout' parameter " - "and a differentiable result", ()) + "'@differentiable' function type cannot have both a differentiable " + "'inout' parameter and a result", ()) ERROR(differentiable_function_type_no_differentiability_parameters, none, "'@differentiable' function type requires at least one differentiability " diff --git a/test/AutoDiff/Sema/derivative_attr_type_checking.swift b/test/AutoDiff/Sema/derivative_attr_type_checking.swift index 8e99b4bdab4e0..f2be21ef64bcc 100644 --- a/test/AutoDiff/Sema/derivative_attr_type_checking.swift +++ b/test/AutoDiff/Sema/derivative_attr_type_checking.swift @@ -746,7 +746,7 @@ extension ProtocolRequirementDerivative { func multipleSemanticResults(_ x: inout Float) -> Float { return x } -// expected-error @+1 {{cannot differentiate functions with both an 'inout' parameter and a result}} +// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} @derivative(of: multipleSemanticResults) func vjpMultipleSemanticResults(x: inout Float) -> ( value: Float, pullback: (Float) -> Float @@ -885,14 +885,14 @@ func vjpNoSemanticResults(_ x: Float) -> (value: Void, pullback: Void) {} extension InoutParameters { func multipleSemanticResults(_ x: inout Float) -> Float { x } - // expected-error @+1 {{cannot differentiate functions with both an 'inout' parameter and a result}} + // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} @derivative(of: multipleSemanticResults) func vjpMultipleSemanticResults(_ x: inout Float) -> ( value: Float, pullback: (inout Float) -> Void ) { fatalError() } func inoutVoid(_ x: Float, _ void: inout Void) -> Float {} - // expected-error @+1 {{cannot differentiate functions with both an 'inout' parameter and a result}} + // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} @derivative(of: inoutVoid) func vjpInoutVoidParameter(_ x: Float, _ void: inout Void) -> ( value: Float, pullback: (inout Float) -> Void diff --git a/test/AutoDiff/Sema/differentiable_attr_type_checking.swift b/test/AutoDiff/Sema/differentiable_attr_type_checking.swift index 0cd6fa5b1bdb1..03b313b47a74e 100644 --- a/test/AutoDiff/Sema/differentiable_attr_type_checking.swift +++ b/test/AutoDiff/Sema/differentiable_attr_type_checking.swift @@ -528,7 +528,7 @@ func two9(x: Float, y: Float) -> Float { func inout1(x: Float, y: inout Float) -> Void { let _ = x + y } -// expected-error @+1 {{cannot differentiate functions with both an 'inout' parameter and a result}} +// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} @differentiable(reverse, wrt: y) func inout2(x: Float, y: inout Float) -> Float { let _ = x + y @@ -670,11 +670,11 @@ final class FinalClass: Differentiable { @differentiable(reverse, wrt: y) func inoutVoid(x: Float, y: inout Float) {} -// expected-error @+1 {{cannot differentiate functions with both an 'inout' parameter and a result}} +// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} @differentiable(reverse) func multipleSemanticResults(_ x: inout Float) -> Float { x } -// expected-error @+1 {{cannot differentiate functions with both an 'inout' parameter and a result}} +// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} @differentiable(reverse, wrt: y) func swap(x: inout Float, y: inout Float) {} @@ -687,7 +687,7 @@ extension InoutParameters { @differentiable(reverse) static func staticMethod(_ lhs: inout Self, rhs: Self) {} - // expected-error @+1 {{cannot differentiate functions with both an 'inout' parameter and a result}} + // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} @differentiable(reverse) static func multipleSemanticResults(_ lhs: inout Self, rhs: Self) -> Self {} } @@ -696,7 +696,7 @@ extension InoutParameters { @differentiable(reverse) mutating func mutatingMethod(_ other: Self) {} - // expected-error @+1 {{cannot differentiate functions with both an 'inout' parameter and a result}} + // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} @differentiable(reverse) mutating func mutatingMethod(_ other: Self) -> Self {} } diff --git a/test/AutoDiff/Sema/differentiable_func_type.swift b/test/AutoDiff/Sema/differentiable_func_type.swift index 7012c46bf3b2a..ba8091d9bdf05 100644 --- a/test/AutoDiff/Sema/differentiable_func_type.swift +++ b/test/AutoDiff/Sema/differentiable_func_type.swift @@ -40,10 +40,10 @@ let _: @differentiable(_linear) (Float) -> NonDiffType let _: @differentiable(_linear) (Float) -> Float -// expected-error @+1 {{'@differentiable' function type cannot have both an 'inout' parameter and a differentiable result}} +// expected-error @+1 {{'@differentiable' function type cannot have both a differentiable 'inout' parameter and a result}} let _: @differentiable(reverse) (inout Float) -> Float -// expected-error @+1 {{'@differentiable' function type cannot have both an 'inout' parameter and a differentiable result}} +// expected-error @+1 {{'@differentiable' function type cannot have both a differentiable 'inout' parameter and a result}} let _: @differentiable(_linear) (inout Float) -> Float // expected-error @+1 {{result type '@differentiable(reverse) (U) -> Float' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} diff --git a/test/AutoDiff/compiler_crashers_fixed/sr15818-inout-noderivative-closure-parameter.swift b/test/AutoDiff/compiler_crashers_fixed/sr15818-inout-noderivative-closure-parameter.swift new file mode 100644 index 0000000000000..97f028e0ba7da --- /dev/null +++ b/test/AutoDiff/compiler_crashers_fixed/sr15818-inout-noderivative-closure-parameter.swift @@ -0,0 +1,55 @@ +// RUN: %target-swift-frontend -emit-sil -verify %s + +import _Differentiation + +// expected-error @+1 {{result type 'Void' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} +typealias MyType = @differentiable(reverse) (inout @noDerivative Float, Float) -> Void + +@differentiable(reverse) +func myFunc(_ x: inout @noDerivative Float, _ q: Float) -> Void {} + +print(myFunc as MyType) + +// Original crash: +// Assertion failed: (Index < Length && "Invalid index!"), function operator[], file ArrayRef.h, line 257. +// Stack dump: +// ... +// 1. Swift version 5.7-dev (LLVM a9a5fb525c61dd0, Swift f69d528185a8bfe) +// 2. Compiling with the current language version +// 3. While evaluating request ExecuteSILPipelineRequest(Run pipelines { Mandatory Diagnostic Passes + Enabling Optimization Passes } on SIL for file) +// 4. While running pass #46 SILModuleTransform "Differentiation". +// 5. While canonicalizing `differentiable_function` SIL node %12 = differentiable_function [parameters 1] [results 0] %9 : $@callee_guaranteed (@inout Float, Float, Int) -> () // users: %23, %18, %13 +// 6. While ...in SIL function "@main". +// Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it): +// 0 swift-frontend 0x0000000105719dc0 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56 +// 1 swift-frontend 0x0000000105718ef0 llvm::sys::RunSignalHandlers() + 128 +// 2 swift-frontend 0x000000010571a424 SignalHandler(int) + 304 +// 3 libsystem_platform.dylib 0x00000001bb5304e4 _sigtramp + 56 +// 4 libsystem_pthread.dylib 0x00000001bb518eb0 pthread_kill + 288 +// 5 libsystem_c.dylib 0x00000001bb456314 abort + 164 +// 6 libsystem_c.dylib 0x00000001bb45572c err + 0 +// 7 swift-frontend 0x0000000105a1bab8 swift::SILFunctionConventions::getSILArgumentConvention(unsigned int) const (.cold.4) + 0 +// 8 swift-frontend 0x00000001016a1f9c swift::SILFunctionConventions::getSILArgumentConvention(unsigned int) const + 192 +// 9 swift-frontend 0x0000000100ebc888 (anonymous namespace)::OperandOwnershipClassifier::visitFullApply(swift::FullApplySite) + 244 +// 10 swift-frontend 0x0000000100ebae70 swift::Operand::getOperandOwnership() const + 148 +// 11 swift-frontend 0x0000000100ebada0 swift::checkOperandOwnershipInvariants(swift::Operand const*) + 28 +// 12 swift-frontend 0x0000000100fe2cc8 swift::SILInstruction::verifyOperandOwnership() const + 444 +// 13 swift-frontend 0x00000001014f32f4 swift::autodiff::getOrCreateSubsetParametersThunkForLinearMap(swift::SILOptFunctionBuilder&, swift::SILFunction*, swift::CanTypeWrapper, swift::CanTypeWrapper, swift::CanTypeWrapper, swift::AutoDiffDerivativeFunctionKind, swift::AutoDiffConfig const&, swift::AutoDiffConfig const&, swift::autodiff::ADContext&) + 3800 +// 14 swift-frontend 0x00000001014f455c swift::autodiff::getOrCreateSubsetParametersThunkForDerivativeFunction(swift::SILOptFunctionBuilder&, swift::SILValue, swift::SILValue, swift::AutoDiffDerivativeFunctionKind, swift::AutoDiffConfig const&, swift::AutoDiffConfig const&, swift::autodiff::ADContext&) + 2828 +// 15 swift-frontend 0x00000001015f012c (anonymous namespace)::DifferentiationTransformer::promoteToDifferentiableFunction(swift::DifferentiableFunctionInst*, swift::SILBuilder&, swift::SILLocation, swift::autodiff::DifferentiationInvoker) + 7120 +// 16 swift-frontend 0x00000001015ecae0 (anonymous namespace)::DifferentiationTransformer::processDifferentiableFunctionInst(swift::DifferentiableFunctionInst*) + 452 +// 17 swift-frontend 0x00000001015eab14 (anonymous namespace)::Differentiation::run() + 1152 +// 18 swift-frontend 0x0000000101659548 swift::SILPassManager::runModulePass(unsigned int) + 840 +// 19 swift-frontend 0x000000010165eaa4 swift::SILPassManager::execute() + 628 +// 20 swift-frontend 0x0000000101656428 swift::SILPassManager::executePassPipelinePlan(swift::SILPassPipelinePlan const&) + 68 +// 21 swift-frontend 0x00000001016563c8 swift::ExecuteSILPipelineRequest::evaluate(swift::Evaluator&, swift::SILPipelineExecutionDescriptor) const + 52 +// 22 swift-frontend 0x000000010167c574 swift::SimpleRequest (swift::SILPipelineExecutionDescriptor), (swift::RequestFlags)1>::evaluateRequest(swift::ExecuteSILPipelineRequest const&, swift::Evaluator&) + 28 +// 23 swift-frontend 0x0000000101664c2c llvm::Expected swift::Evaluator::getResultUncached(swift::ExecuteSILPipelineRequest const&) + 252 +// 24 swift-frontend 0x0000000101656618 swift::executePassPipelinePlan(swift::SILModule*, swift::SILPassPipelinePlan const&, bool, swift::irgen::IRGenModule*) + 68 +// 25 swift-frontend 0x0000000101669014 swift::runSILDiagnosticPasses(swift::SILModule&) + 92 +// 26 swift-frontend 0x0000000100e81634 swift::CompilerInstance::performSILProcessing(swift::SILModule*) + 72 +// 27 swift-frontend 0x0000000100e273cc performCompileStepsPostSILGen(swift::CompilerInstance&, std::__1::unique_ptr >, llvm::PointerUnion, swift::PrimarySpecificPaths const&, int&, swift::FrontendObserver*) + 676 +// 28 swift-frontend 0x0000000100e26db8 swift::performCompileStepsPostSema(swift::CompilerInstance&, int&, swift::FrontendObserver*) + 1028 +// 29 swift-frontend 0x0000000100e28870 swift::performFrontend(llvm::ArrayRef, char const*, void*, swift::FrontendObserver*) + 3012 +// 30 swift-frontend 0x0000000100d62830 swift::mainEntry(int, char const**) + 484 +// 31 dyld 0x00000001179d90f4 start + 520 From c11f5cef401d1f9ca0eb5b03034793ff0a7c217d Mon Sep 17 00:00:00 2001 From: Philip Turner Date: Wed, 20 Apr 2022 23:18:30 -0400 Subject: [PATCH 11/12] Migrate changes from PR #41422 --- include/swift/AST/AutoDiff.h | 4 ++- include/swift/AST/DiagnosticsSema.def | 12 +++++--- lib/AST/AutoDiff.cpp | 7 ----- lib/AST/Type.cpp | 3 +- lib/Sema/TypeChecker.cpp | 30 ++++++++++++++----- .../Sema/derivative_attr_type_checking.swift | 6 ++-- .../differentiable_attr_type_checking.swift | 10 +++---- .../Sema/differentiable_func_type.swift | 10 +++++-- ...on-differentiable-closure-parameters.swift | 9 ++---- ...inout-noderivative-closure-parameter.swift | 7 ++--- 10 files changed, 56 insertions(+), 42 deletions(-) diff --git a/include/swift/AST/AutoDiff.h b/include/swift/AST/AutoDiff.h index 45c74263ff9f1..8f9edd7be695c 100644 --- a/include/swift/AST/AutoDiff.h +++ b/include/swift/AST/AutoDiff.h @@ -364,7 +364,9 @@ class TangentSpace { static TangentSpace getTangentVector(Type tangentVectorType) { return {Kind::TangentVector, tangentVectorType}; } - static TangentSpace getTuple(TupleType *tupleTy); + static TangentSpace getTuple(TupleType *tupleTy) { + return {Kind::Tuple, tupleTy}; + } bool isTangentVector() const { return kind == Kind::TangentVector; } bool isTuple() const { return kind == Kind::Tuple; } diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 7c96656c21f24..ae157b397cabf 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -3463,7 +3463,7 @@ ERROR(autodiff_attr_original_void_result,none, "cannot differentiate void function %0", (DeclName)) ERROR(autodiff_attr_original_multiple_semantic_results,none, "cannot differentiate functions with both a differentiable 'inout' " - "parameter and a result", ()) + "parameter and a differentiable result", ()) ERROR(autodiff_attr_result_not_differentiable,none, "can only differentiate functions with results that conform to " "'Differentiable', but %0 does not conform to 'Differentiable'", (Type)) @@ -5042,13 +5042,17 @@ ERROR(differentiable_function_type_invalid_result,none, (StringRef, bool)) ERROR(differentiable_function_type_multiple_semantic_results,none, "'@differentiable' function type cannot have both a differentiable " - "'inout' parameter and a result", ()) -ERROR(differentiable_function_type_no_differentiability_parameters, - none, + "'inout' parameter and a differentiable result", ()) +ERROR(differentiable_function_type_no_differentiability_parameters,none, "'@differentiable' function type requires at least one differentiability " "parameter, i.e. a non-'@noDerivative' parameter whose type conforms to " "'Differentiable'%select{| with its 'TangentVector' equal to itself}0", (/*isLinear*/ bool)) +ERROR(differentiable_function_type_no_differentiable_result,none, + "'@differentiable' function type requires a differentiable result, i.e. " + "a non-'Void' type that conforms to 'Differentiable'%select{| with its " + "'TangentVector' equal to itself}0", + (/*isLinear*/ bool)) // SIL ERROR(opened_non_protocol,none, diff --git a/lib/AST/AutoDiff.cpp b/lib/AST/AutoDiff.cpp index db13456d546bc..60a49b43e304f 100644 --- a/lib/AST/AutoDiff.cpp +++ b/lib/AST/AutoDiff.cpp @@ -366,13 +366,6 @@ GenericSignature autodiff::getDifferentiabilityWitnessGenericSignature( return derivativeGenSig; } -TangentSpace TangentSpace::getTuple(TupleType *tupleTy) { - assert(!tupleTy->isVoid() && - "Attempted to get tangent space of 'Void', which cannot be " - "differentiated."); - return {Kind::Tuple, tupleTy}; -} - Type TangentSpace::getType() const { switch (kind) { case Kind::TangentVector: diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 641a3dbc91c21..6a89204a7551a 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -6189,7 +6189,8 @@ TypeBase::getAutoDiffTangentSpace(LookupConformanceFn lookupConformance) { newElts.push_back(elt.getWithType(eltSpace->getType())); } if (newElts.empty()) - return cache(None); + return cache( + TangentSpace::getTuple(ctx.TheEmptyTupleType->castTo())); if (newElts.size() == 1) return cache(TangentSpace::getTangentVector(newElts.front().getType())); auto *tupleType = TupleType::get(newElts, ctx)->castTo(); diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 1f9e4beb01562..709cd3d326bf5 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -619,7 +619,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, dc, stage); }) != params.end(); bool alreadyDiagnosedOneParam = false; - bool hasInoutDiffParameter = false; + bool hasInoutDifferentiableParameter = false; for (unsigned i = 0, end = fnTy->getNumParams(); i != end; ++i) { auto param = params[i]; if (param.isNoDerivative()) @@ -627,7 +627,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, auto paramType = param.getPlainType(); if (TypeChecker::isDifferentiable(paramType, isLinear, dc, stage)) { if (param.isInOut()) - hasInoutDiffParameter = true; + hasInoutDifferentiableParameter = true; continue; } auto diagLoc = @@ -657,12 +657,13 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, } // Check the result. - bool resultIsDifferentiable = - isDifferentiable(result, /*tangentVectorEqualsSelf*/ isLinear, dc, - stage); + bool resultExists = !(result->isVoid()); + bool resultIsDifferentiable = TypeChecker::isDifferentiable( + result, /*tangentVectorEqualsSelf*/ isLinear, dc, stage); + bool differentiableResultExists = resultExists && resultIsDifferentiable; // Reject the case where there are multiple semantic results. - if (resultIsDifferentiable && hasInoutDiffParameter) { + if (differentiableResultExists && hasInoutDifferentiableParameter) { auto diagLoc = repr ? (*repr)->getArgsTypeRepr()->getLoc() : loc; auto diag = ctx.Diags.diagnose( diagLoc, @@ -674,8 +675,8 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, } } - // Reject the case where there are no semantic results. - if (!resultIsDifferentiable && !hasInoutDiffParameter) { + // Reject the case where the semantic result is not differentiable. + if (!resultIsDifferentiable && !hasInoutDifferentiableParameter) { auto diagLoc = repr ? (*repr)->getResultTypeRepr()->getLoc() : loc; auto resultStr = fnTy->getResult()->getString(); auto diag = ctx.Diags.diagnose( @@ -687,6 +688,19 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, diag.highlight((*repr)->getResultTypeRepr()->getSourceRange()); } } + + // Reject the case where there are no semantic results. + if (!resultExists && !hasInoutDifferentiableParameter) { + auto diagLoc = repr ? (*repr)->getResultTypeRepr()->getLoc() : loc; + auto diag = ctx.Diags.diagnose( + diagLoc, diag::differentiable_function_type_no_differentiable_result, + isLinear); + hadAnyError = true; + + if (repr) { + diag.highlight((*repr)->getResultTypeRepr()->getSourceRange()); + } + } } return hadAnyError; diff --git a/test/AutoDiff/Sema/derivative_attr_type_checking.swift b/test/AutoDiff/Sema/derivative_attr_type_checking.swift index f2be21ef64bcc..ef9ac521028b2 100644 --- a/test/AutoDiff/Sema/derivative_attr_type_checking.swift +++ b/test/AutoDiff/Sema/derivative_attr_type_checking.swift @@ -746,7 +746,7 @@ extension ProtocolRequirementDerivative { func multipleSemanticResults(_ x: inout Float) -> Float { return x } -// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} +// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a differentiable result}} @derivative(of: multipleSemanticResults) func vjpMultipleSemanticResults(x: inout Float) -> ( value: Float, pullback: (Float) -> Float @@ -885,14 +885,14 @@ func vjpNoSemanticResults(_ x: Float) -> (value: Void, pullback: Void) {} extension InoutParameters { func multipleSemanticResults(_ x: inout Float) -> Float { x } - // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} + // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a differentiable result}} @derivative(of: multipleSemanticResults) func vjpMultipleSemanticResults(_ x: inout Float) -> ( value: Float, pullback: (inout Float) -> Void ) { fatalError() } func inoutVoid(_ x: Float, _ void: inout Void) -> Float {} - // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} + // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a differentiable result}} @derivative(of: inoutVoid) func vjpInoutVoidParameter(_ x: Float, _ void: inout Void) -> ( value: Float, pullback: (inout Float) -> Void diff --git a/test/AutoDiff/Sema/differentiable_attr_type_checking.swift b/test/AutoDiff/Sema/differentiable_attr_type_checking.swift index 03b313b47a74e..484beb3af4153 100644 --- a/test/AutoDiff/Sema/differentiable_attr_type_checking.swift +++ b/test/AutoDiff/Sema/differentiable_attr_type_checking.swift @@ -528,7 +528,7 @@ func two9(x: Float, y: Float) -> Float { func inout1(x: Float, y: inout Float) -> Void { let _ = x + y } -// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} +// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a differentiable result}} @differentiable(reverse, wrt: y) func inout2(x: Float, y: inout Float) -> Float { let _ = x + y @@ -670,11 +670,11 @@ final class FinalClass: Differentiable { @differentiable(reverse, wrt: y) func inoutVoid(x: Float, y: inout Float) {} -// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} +// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a differentiable result}} @differentiable(reverse) func multipleSemanticResults(_ x: inout Float) -> Float { x } -// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} +// expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a differentiable result}} @differentiable(reverse, wrt: y) func swap(x: inout Float, y: inout Float) {} @@ -687,7 +687,7 @@ extension InoutParameters { @differentiable(reverse) static func staticMethod(_ lhs: inout Self, rhs: Self) {} - // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} + // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a differentiable result}} @differentiable(reverse) static func multipleSemanticResults(_ lhs: inout Self, rhs: Self) -> Self {} } @@ -696,7 +696,7 @@ extension InoutParameters { @differentiable(reverse) mutating func mutatingMethod(_ other: Self) {} - // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a result}} + // expected-error @+1 {{cannot differentiate functions with both a differentiable 'inout' parameter and a differentiable result}} @differentiable(reverse) mutating func mutatingMethod(_ other: Self) -> Self {} } diff --git a/test/AutoDiff/Sema/differentiable_func_type.swift b/test/AutoDiff/Sema/differentiable_func_type.swift index ba8091d9bdf05..a0fd596e94234 100644 --- a/test/AutoDiff/Sema/differentiable_func_type.swift +++ b/test/AutoDiff/Sema/differentiable_func_type.swift @@ -28,6 +28,12 @@ let _: @differentiable(reverse) (Float, NonDiffType) -> Float // expected-error @+1 {{result type 'NonDiffType' does not conform to 'Differentiable' and satisfy 'NonDiffType == NonDiffType.TangentVector', but the enclosing function type is '@differentiable(_linear)'}} let _: @differentiable(_linear) (Float) -> NonDiffType +// expected-error @+1 {{'@differentiable' function type cannot have both a differentiable 'inout' parameter and a differentiable result}} +let _: @differentiable(reverse) (inout Float) -> Float + +// expected-error @+1 {{'@differentiable' function type cannot have both a differentiable 'inout' parameter and a differentiable result}} +let _: @differentiable(_linear) (inout Float) -> Float + // Emit `@noDerivative` fixit iff there is at least one valid linearity parameter. // expected-error @+1 {{parameter type 'NonDiffType' does not conform to 'Differentiable' and satisfy 'NonDiffType == NonDiffType.TangentVector', but the enclosing function type is '@differentiable(_linear)'; did you want to add '@noDerivative' to this parameter?}} {{41-41=@noDerivative }} let _: @differentiable(_linear) (Float, NonDiffType) -> Float @@ -40,10 +46,10 @@ let _: @differentiable(_linear) (Float) -> NonDiffType let _: @differentiable(_linear) (Float) -> Float -// expected-error @+1 {{'@differentiable' function type cannot have both a differentiable 'inout' parameter and a result}} +// expected-error @+1 {{'@differentiable' function type cannot have both a differentiable 'inout' parameter and a differentiable result}} let _: @differentiable(reverse) (inout Float) -> Float -// expected-error @+1 {{'@differentiable' function type cannot have both a differentiable 'inout' parameter and a result}} +// expected-error @+1 {{'@differentiable' function type cannot have both a differentiable 'inout' parameter and a differentiable result}} let _: @differentiable(_linear) (inout Float) -> Float // expected-error @+1 {{result type '@differentiable(reverse) (U) -> Float' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} diff --git a/test/AutoDiff/compiler_crashers_fixed/sr15808-non-differentiable-closure-parameters.swift b/test/AutoDiff/compiler_crashers_fixed/sr15808-non-differentiable-closure-parameters.swift index e203868e37baa..35420d059f090 100644 --- a/test/AutoDiff/compiler_crashers_fixed/sr15808-non-differentiable-closure-parameters.swift +++ b/test/AutoDiff/compiler_crashers_fixed/sr15808-non-differentiable-closure-parameters.swift @@ -1,23 +1,18 @@ // RUN: %target-swift-frontend -emit-sil -verify %s - // SR-15808: In AST, type checking skips a closure with non-differentiable input // where `Void` is included as a parameter without being marked `@noDerivative`. // It also crashes when the output is `Void` and no input is `inout`. As a // result, the compiler crashes during Sema. - import _Differentiation -// expected-error @+2 {{parameter type '()' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} -// expected-error @+1 {{result type 'Void' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} +// expected-error @+1 {{'@differentiable' function type requires a differentiable result, i.e. a non-'Void' type that conforms to 'Differentiable'}} func helloWorld(_ x: @differentiable(reverse) (()) -> Void) {} -// expected-error @+1 {{parameter type '()' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} func helloWorld(_ x: @differentiable(reverse) (()) -> Float) {} -// expected-error @+1 {{result type 'Void' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} +// expected-error @+1 {{'@differentiable' function type requires a differentiable result, i.e. a non-'Void' type that conforms to 'Differentiable'}} func helloWorld(_ x: @differentiable(reverse) (Float) -> Void) {} -// expected-error @+1 {{parameter type 'Void' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} func helloWorld(_ x: @differentiable(reverse) (@noDerivative Float, Void) -> Float) {} // Original crash: diff --git a/test/AutoDiff/compiler_crashers_fixed/sr15818-inout-noderivative-closure-parameter.swift b/test/AutoDiff/compiler_crashers_fixed/sr15818-inout-noderivative-closure-parameter.swift index 97f028e0ba7da..e123b4082c03d 100644 --- a/test/AutoDiff/compiler_crashers_fixed/sr15818-inout-noderivative-closure-parameter.swift +++ b/test/AutoDiff/compiler_crashers_fixed/sr15818-inout-noderivative-closure-parameter.swift @@ -1,14 +1,13 @@ // RUN: %target-swift-frontend -emit-sil -verify %s - import _Differentiation -// expected-error @+1 {{result type 'Void' does not conform to 'Differentiable', but the enclosing function type is '@differentiable'}} +// expected-error @+1 {{@differentiable' function type requires a differentiable result, i.e. a non-'Void' type that conforms to 'Differentiable'}} typealias MyType = @differentiable(reverse) (inout @noDerivative Float, Float) -> Void @differentiable(reverse) -func myFunc(_ x: inout @noDerivative Float, _ q: Float) -> Void {} +func myFunc(_ x: inout @noDerivative Float, _ q: Float) -> Void {} -print(myFunc as MyType) +let castedFunc = myFunc as MyType // Original crash: // Assertion failed: (Index < Length && "Invalid index!"), function operator[], file ArrayRef.h, line 257. From 4b8312d9d7901e442b01646c179c9972b4fe61af Mon Sep 17 00:00:00 2001 From: Philip Turner Date: Wed, 20 Apr 2022 23:23:31 -0400 Subject: [PATCH 12/12] Modify spelling and whitespace --- include/swift/AST/AutoDiff.h | 4 ++-- lib/Sema/TypeChecker.cpp | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/swift/AST/AutoDiff.h b/include/swift/AST/AutoDiff.h index 8f9edd7be695c..3bcdc5dc0852e 100644 --- a/include/swift/AST/AutoDiff.h +++ b/include/swift/AST/AutoDiff.h @@ -365,8 +365,8 @@ class TangentSpace { return {Kind::TangentVector, tangentVectorType}; } static TangentSpace getTuple(TupleType *tupleTy) { - return {Kind::Tuple, tupleTy}; - } + return {Kind::Tuple, tupleTy}; + } bool isTangentVector() const { return kind == Kind::TangentVector; } bool isTuple() const { return kind == Kind::Tuple; } diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp index 709cd3d326bf5..1f3213f871347 100644 --- a/lib/Sema/TypeChecker.cpp +++ b/lib/Sema/TypeChecker.cpp @@ -619,7 +619,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, dc, stage); }) != params.end(); bool alreadyDiagnosedOneParam = false; - bool hasInoutDifferentiableParameter = false; + bool hasDifferentiableInoutParameter = false; for (unsigned i = 0, end = fnTy->getNumParams(); i != end; ++i) { auto param = params[i]; if (param.isNoDerivative()) @@ -627,7 +627,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, auto paramType = param.getPlainType(); if (TypeChecker::isDifferentiable(paramType, isLinear, dc, stage)) { if (param.isInOut()) - hasInoutDifferentiableParameter = true; + hasDifferentiableInoutParameter = true; continue; } auto diagLoc = @@ -663,7 +663,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, bool differentiableResultExists = resultExists && resultIsDifferentiable; // Reject the case where there are multiple semantic results. - if (differentiableResultExists && hasInoutDifferentiableParameter) { + if (differentiableResultExists && hasDifferentiableInoutParameter) { auto diagLoc = repr ? (*repr)->getArgsTypeRepr()->getLoc() : loc; auto diag = ctx.Diags.diagnose( diagLoc, @@ -676,7 +676,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, } // Reject the case where the semantic result is not differentiable. - if (!resultIsDifferentiable && !hasInoutDifferentiableParameter) { + if (!resultIsDifferentiable && !hasDifferentiableInoutParameter) { auto diagLoc = repr ? (*repr)->getResultTypeRepr()->getLoc() : loc; auto resultStr = fnTy->getResult()->getString(); auto diag = ctx.Diags.diagnose( @@ -690,7 +690,7 @@ bool TypeChecker::diagnoseInvalidFunctionType(FunctionType *fnTy, SourceLoc loc, } // Reject the case where there are no semantic results. - if (!resultExists && !hasInoutDifferentiableParameter) { + if (!resultExists && !hasDifferentiableInoutParameter) { auto diagLoc = repr ? (*repr)->getResultTypeRepr()->getLoc() : loc; auto diag = ctx.Diags.diagnose( diagLoc, diag::differentiable_function_type_no_differentiable_result,