Skip to content

Commit 7851a74

Browse files
committed
Improve access level mismatch diagnostics.
Use a single consistent error message stating "derivative function must have same access level as original function". Add access level fix-it on the derivative function.
1 parent da1e398 commit 7851a74

File tree

3 files changed

+48
-47
lines changed

3 files changed

+48
-47
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3054,22 +3054,18 @@ ERROR(derivative_attr_original_already_has_derivative,none,
30543054
"a derivative already exists for %0", (DeclName))
30553055
NOTE(derivative_attr_duplicate_note,none,
30563056
"other attribute declared here", ())
3057-
ERROR(derivative_attr_access_level_lower_than_original,none,
3058-
"derivative functions for "
3059-
"%select{private|fileprivate|internal|public or '@usableFromInline'|open}1 "
3060-
"original function %0 must also be "
3061-
"%select{private|fileprivate|internal|public or '@usableFromInline'|open}1, "
3062-
"but %2 is %select{private|fileprivate|internal|public|open}3",
3063-
(/*original*/ DeclName, /*original*/ AccessLevel,
3064-
/*derivative*/ DeclName, /*derivative*/ AccessLevel))
3065-
ERROR(derivative_attr_access_level_higher_than_original,none,
3066-
"the original function of "
3067-
"%select{a private|a fileprivate|an internal|a public or '@usableFromInline'|an open}3 "
3068-
"derivative function must also be "
3069-
"%select{private|fileprivate|internal|public or '@usableFromInline'|open}3, "
3070-
"but %0 is %select{private|fileprivate|internal|public|open}1",
3057+
ERROR(derivative_attr_access_level_mismatch,none,
3058+
"derivative function must have same access level as original function; "
3059+
"derivative function %2 is "
3060+
"%select{private|fileprivate|internal|public|open}3, "
3061+
"but original function %0 is "
3062+
"%select{private|fileprivate|internal|public|open}1",
30713063
(/*original*/ DeclName, /*original*/ AccessLevel,
30723064
/*derivative*/ DeclName, /*derivative*/ AccessLevel))
3065+
NOTE(derivative_attr_fix_access,none,
3066+
"mark the derivative function as "
3067+
"'%select{private|fileprivate|internal|public|open}0' to match the "
3068+
"original function", (AccessLevel))
30733069

30743070
// @transpose
30753071
ERROR(transpose_attr_invalid_linearity_parameter_or_result,none,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4541,7 +4541,7 @@ static bool typeCheckDerivativeAttr(ASTContext &Ctx, Decl *D,
45414541
attr->setOriginalFunction(originalAFD);
45424542

45434543
// Returns true if:
4544-
// - Original function and derivative function has the same access level.
4544+
// - Original function and derivative function have the same access level.
45454545
// - Original function is public and derivative function is internal
45464546
// `@usableFromInline`. This is the only special case.
45474547
auto compatibleAccessLevels = [&]() {
@@ -4553,21 +4553,16 @@ static bool typeCheckDerivativeAttr(ASTContext &Ctx, Decl *D,
45534553

45544554
// Check access level compatibility for original and derivative functions.
45554555
if (!compatibleAccessLevels()) {
4556-
auto diagID = diag::derivative_attr_access_level_higher_than_original;
4557-
AccessLevel originalAccess;
4558-
AccessLevel derivativeAccess;
4559-
if (originalAFD->getEffectiveAccess() < derivative->getEffectiveAccess()) {
4560-
originalAccess =
4561-
originalAFD->getFormalAccessScope().accessLevelForDiagnostics();
4562-
derivativeAccess = derivative->getEffectiveAccess();
4563-
} else {
4564-
diagID = diag::derivative_attr_access_level_lower_than_original;
4565-
originalAccess = originalAFD->getEffectiveAccess();
4566-
derivativeAccess =
4567-
derivative->getFormalAccessScope().accessLevelForDiagnostics();
4568-
}
4569-
diags.diagnose(originalName.Loc, diagID, originalAFD->getName(),
4570-
originalAccess, derivative->getName(), derivativeAccess);
4556+
auto originalAccess = originalAFD->getFormalAccess();
4557+
auto derivativeAccess =
4558+
derivative->getFormalAccessScope().accessLevelForDiagnostics();
4559+
diags.diagnose(originalName.Loc,
4560+
diag::derivative_attr_access_level_mismatch,
4561+
originalAFD->getName(), originalAccess,
4562+
derivative->getName(), derivativeAccess);
4563+
auto fixItDiag =
4564+
derivative->diagnose(diag::derivative_attr_fix_access, originalAccess);
4565+
fixItAccess(fixItDiag, derivative, originalAccess);
45714566
return true;
45724567
}
45734568

test/AutoDiff/Sema/derivative_attr_type_checking.swift

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -819,14 +819,6 @@ func _public_original_usablefrominline_derivative(_ x: Float) -> (value: Float,
819819
fatalError()
820820
}
821821

822-
@usableFromInline
823-
func usablefrominline_original_public_derivative(_ x: Float) -> Float { x }
824-
// expected-error @+1 {{derivative functions for public or '@usableFromInline' original function 'usablefrominline_original_public_derivative' must also be public or '@usableFromInline', but '_usablefrominline_original_public_derivative' is public}}
825-
@derivative(of: usablefrominline_original_public_derivative)
826-
public func _usablefrominline_original_public_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
827-
fatalError()
828-
}
829-
830822
func internal_original_internal_derivative(_ x: Float) -> Float { x }
831823
@derivative(of: internal_original_internal_derivative)
832824
func _internal_original_internal_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
@@ -846,69 +838,87 @@ fileprivate func _fileprivate_original_fileprivate_derivative(_ x: Float) -> (va
846838
}
847839

848840
fileprivate func fileprivate_original_private_derivative(_ x: Float) -> Float { x }
849-
// expected-error @+1 {{derivative functions for fileprivate original function 'fileprivate_original_private_derivative' must also be fileprivate, but '_fileprivate_original_private_derivative' is private}}
841+
// expected-error @+1 {{derivative function must have same access level as original function; derivative function '_fileprivate_original_private_derivative' is private, but original function 'fileprivate_original_private_derivative' is fileprivate}}
850842
@derivative(of: fileprivate_original_private_derivative)
843+
// expected-note @+1 {{mark the derivative function as 'fileprivate' to match the original function}}
851844
private func _fileprivate_original_private_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
852845
fatalError()
853846
}
854847

855848
private func private_original_fileprivate_derivative(_ x: Float) -> Float { x }
856-
// expected-error @+1 {{derivative functions for fileprivate original function 'private_original_fileprivate_derivative' must also be fileprivate, but '_private_original_fileprivate_derivative' is fileprivate}}
849+
// expected-error @+1 {{derivative function must have same access level as original function; derivative function '_private_original_fileprivate_derivative' is fileprivate, but original function 'private_original_fileprivate_derivative' is private}}
857850
@derivative(of: private_original_fileprivate_derivative)
851+
// expected-note @+1 {{mark the derivative function as 'private' to match the original function}}
858852
fileprivate func _private_original_fileprivate_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
859853
fatalError()
860854
}
861855

862856
// MARK: - Original function visibility < derivative function visibility
863857

858+
@usableFromInline
859+
func usablefrominline_original_public_derivative(_ x: Float) -> Float { x }
860+
// expected-error @+1 {{derivative function must have same access level as original function; derivative function '_usablefrominline_original_public_derivative' is public, but original function 'usablefrominline_original_public_derivative' is internal}}
861+
@derivative(of: usablefrominline_original_public_derivative)
862+
// expected-note @+1 {{mark the derivative function as 'internal' to match the original function}}
863+
public func _usablefrominline_original_public_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
864+
fatalError()
865+
}
866+
864867
func internal_original_public_derivative(_ x: Float) -> Float { x }
865-
// expected-error @+1 {{the original function of a public or '@usableFromInline' derivative function must also be public or '@usableFromInline', but 'internal_original_public_derivative' is internal}}
868+
// expected-error @+1 {{derivative function must have same access level as original function; derivative function '_internal_original_public_derivative' is public, but original function 'internal_original_public_derivative' is internal}}
866869
@derivative(of: internal_original_public_derivative)
870+
// expected-note @+1 {{mark the derivative function as 'internal' to match the original function}}
867871
public func _internal_original_public_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
868872
fatalError()
869873
}
870874

871875
private func private_original_usablefrominline_derivative(_ x: Float) -> Float { x }
872-
// expected-error @+1 {{the original function of a public or '@usableFromInline' derivative function must also be public or '@usableFromInline', but 'private_original_usablefrominline_derivative' is private}}
876+
// expected-error @+1 {{derivative function must have same access level as original function; derivative function '_private_original_usablefrominline_derivative' is internal, but original function 'private_original_usablefrominline_derivative' is private}}
873877
@derivative(of: private_original_usablefrominline_derivative)
874878
@usableFromInline
879+
// expected-note @+1 {{mark the derivative function as 'private' to match the original function}}
875880
func _private_original_usablefrominline_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
876881
fatalError()
877882
}
878883

879884
private func private_original_public_derivative(_ x: Float) -> Float { x }
880-
// expected-error @+1 {{the original function of a public or '@usableFromInline' derivative function must also be public or '@usableFromInline', but 'private_original_public_derivative' is private}}
885+
// expected-error @+1 {{derivative function must have same access level as original function; derivative function '_private_original_public_derivative' is public, but original function 'private_original_public_derivative' is private}}
881886
@derivative(of: private_original_public_derivative)
887+
// expected-note @+1 {{mark the derivative function as 'private' to match the original function}}
882888
public func _private_original_public_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
883889
fatalError()
884890
}
885891

886892
private func private_original_internal_derivative(_ x: Float) -> Float { x }
887-
// expected-error @+1 {{the original function of an internal derivative function must also be internal, but 'private_original_internal_derivative' is private}}
893+
// expected-error @+1 {{derivative function must have same access level as original function; derivative function '_private_original_internal_derivative' is internal, but original function 'private_original_internal_derivative' is private}}
888894
@derivative(of: private_original_internal_derivative)
895+
// expected-note @+1 {{mark the derivative function as 'private' to match the original function}}
889896
func _private_original_internal_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
890897
fatalError()
891898
}
892899

893900
// MARK: - Original function visibility > derivative function visibility
894901

895902
public func public_original_private_derivative(_ x: Float) -> Float { x }
896-
// expected-error @+1 {{derivative functions for public or '@usableFromInline' original function 'public_original_private_derivative' must also be public or '@usableFromInline', but '_public_original_private_derivative' is fileprivate}}
903+
// expected-error @+1 {{derivative function must have same access level as original function; derivative function '_public_original_private_derivative' is fileprivate, but original function 'public_original_private_derivative' is public}}
897904
@derivative(of: public_original_private_derivative)
905+
// expected-note @+1 {{mark the derivative function as 'public' to match the original function}}
898906
fileprivate func _public_original_private_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
899907
fatalError()
900908
}
901909

902910
public func public_original_internal_derivative(_ x: Float) -> Float { x }
903-
// expected-error @+1 {{derivative functions for public or '@usableFromInline' original function 'public_original_internal_derivative' must also be public or '@usableFromInline', but '_public_original_internal_derivative' is internal}}
911+
// expected-error @+1 {{derivative function must have same access level as original function; derivative function '_public_original_internal_derivative' is internal, but original function 'public_original_internal_derivative' is public}}
904912
@derivative(of: public_original_internal_derivative)
913+
// expected-note @+1 {{mark the derivative function as 'public' to match the original function}}
905914
func _public_original_internal_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
906915
fatalError()
907916
}
908917

909918
func internal_original_fileprivate_derivative(_ x: Float) -> Float { x }
910-
// expected-error @+1 {{derivative functions for internal original function 'internal_original_fileprivate_derivative' must also be internal, but '_internal_original_fileprivate_derivative' is fileprivate}}
919+
// expected-error @+1 {{derivative function must have same access level as original function; derivative function '_internal_original_fileprivate_derivative' is fileprivate, but original function 'internal_original_fileprivate_derivative' is internal}}
911920
@derivative(of: internal_original_fileprivate_derivative)
921+
// expected-note @+1 {{mark the derivative function as 'internal' to match the original function}}
912922
fileprivate func _internal_original_fileprivate_derivative(_ x: Float) -> (value: Float, pullback: (Float) -> Float) {
913923
fatalError()
914924
}

0 commit comments

Comments
 (0)