Skip to content

AST: Quote attributes more consistently in diagnostics #80593

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions docs/Diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,23 @@ Clang also has a kind of diagnostic called a "remark", which represents informat

- When applicable, phrase diagnostics as rules rather than reporting that the compiler failed to do something. Example:

- Normal: "cannot call 'super.init' outside of an initializer"
- Better: "'super.init' cannot be called outside of an initializer"
- Normal: `cannot call 'super.init' outside of an initializer`
- Better: `'super.init' cannot be called outside of an initializer`

- Use `'` to quote attributes, symbol names, and any other text that is
referred to as code or a token.
Some idiomatic Swift tokens, such as `protocol`, by themselves are or appear
in Swift terms of art.
Terms of art are written in plain text and must not be quoted.
If you are not certain whether a Swift token has an associated term of art,
consult the [book].
For example:
- `'mutating' is only valid on methods`, but
`cannot call mutating method on immutable value`.
- `'@autoclosure' only applies to function types`.
- `subscript access can throw but is not marked with 'try'`.
- `expected '{' after 'defer'`.
- `type 'S' does not conform to protocol 'Sequence'`.

- When referring to attributes by name, use *either* `attribute 'foo'` or
`'@foo'`, rather than `attribute '@foo'`.
Expand All @@ -54,6 +69,8 @@ Clang also has a kind of diagnostic called a "remark", which represents informat

- If possible, it is best to include the name of the type or function that has the error, e.g. "non-actor type 'Nope' cannot ..." is better than "non-actor type cannot ...". It helps developers relate the error message to the specific type the error is about, even if the error would highlight the appropriate line / function in other ways.

[book]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language

### Locations and Highlights ###

- Diagnostics are always emitted at a particular line and column. Try to be specific.
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/DiagnosticsCommon.def
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ ERROR(require_literal_initializer_for_literal,none,
"_const let should be initialized with a literal value", ())

ERROR(require_const_initializer_for_const,none,
"@const value should be initialized with a compile-time value", ())
"'@const' value should be initialized with a compile-time value", ())

ERROR(require_const_arg_for_parameter,none,
"expected a compile-time value argument for a '@const' parameter", ())
Expand Down
6 changes: 3 additions & 3 deletions include/swift/AST/DiagnosticsIRGen.def
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ ERROR(no_input_files_for_mt,none,
"no swift input files for multi-threaded compilation", ())

ERROR(alignment_dynamic_type_layout_unsupported,none,
"@_alignment is not supported on types with dynamic layout", ())
"'@_alignment' is not supported on types with dynamic layout", ())
ERROR(alignment_less_than_natural,none,
"@_alignment cannot decrease alignment below natural alignment of %0",
"'@_alignment' cannot decrease alignment below natural alignment of %0",
(unsigned))
ERROR(alignment_more_than_maximum,none,
"@_alignment cannot increase alignment above maximum alignment of %0",
"'@_alignment' cannot increase alignment above maximum alignment of %0",
(unsigned))

ERROR(temporary_allocation_size_negative,none,
Expand Down
4 changes: 2 additions & 2 deletions include/swift/AST/DiagnosticsModuleDiffer.def
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ ERROR(optional_req_changed,APIDigesterBreakage,"%0 is %select{now|no longer}1 an

ERROR(no_longer_open,APIDigesterBreakage,"%0 is no longer open for subclassing", (StringRef))

ERROR(func_type_escaping_changed,APIDigesterBreakage,"%0 has %select{removed|added}2 @escaping in %1", (StringRef, StringRef, bool))
ERROR(func_type_escaping_changed,APIDigesterBreakage,"%0 has %select{removed|added}2 '@escaping' in %1", (StringRef, StringRef, bool))

ERROR(func_self_access_change,APIDigesterBreakage,"%0 has self access kind changing from %1 to %2", (StringRef, StringRef, StringRef))

Expand All @@ -78,7 +78,7 @@ ERROR(decl_new_witness_table_entry,APIDigesterBreakage,"%0 now requires%select{|

ERROR(class_member_moved_to_extension,APIDigesterBreakage,"Non-final class member %0 is moved to extension", (StringRef))

WARNING(new_decl_without_intro,APIDigesterBreakage,"%0 is a new API without @available attribute", (StringRef))
WARNING(new_decl_without_intro,APIDigesterBreakage,"%0 is a new API without '@available'", (StringRef))

ERROR(objc_name_change,APIDigesterBreakage,"%0 has ObjC name change from %1 to %2", (StringRef, StringRef, StringRef))

Expand Down
69 changes: 35 additions & 34 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ ERROR(expected_precedencegroup_relation,none,
ERROR(expected_sil_keyword,none,
"expected SIL keyword", ())
ERROR(inout_not_attribute, none,
"@inout is no longer an attribute", ())
"'inout' is no longer an attribute", ())
ERROR(only_allowed_in_sil,none,
"'%0' only allowed in SIL modules", (StringRef))
ERROR(expected_sil_type,none,
Expand All @@ -520,7 +520,7 @@ ERROR(silfunc_and_silarg_have_incompatible_sil_value_ownership,none,
"Function type specifies: '@%0'. SIL argument specifies: '@%1'.",
(StringRef, StringRef))
ERROR(sil_arg_both_lexical_and_eagerMove,none,
"Function argument is annotated both @_eagerMove and @_noEagerMove, "
"Function argument is annotated both '@_eagerMove' and '@_noEagerMove', "
"but these are incompatible alternatives", ())
ERROR(expected_sil_colon,none,
"expected ':' before %0", (StringRef))
Expand Down Expand Up @@ -1632,14 +1632,14 @@ ERROR(attr_availability_duplicate,none,

// originallyDefinedIn
ERROR(originally_defined_in_missing_rparen,none,
"expected ')' in @_originallyDefinedIn argument list", ())
"expected ')' in '@_originallyDefinedIn' argument list", ())

ERROR(originally_defined_in_need_original_module_name,none,
"expected 'module: \"original\"' in the first argument to "
"@_originallyDefinedIn", ())
"'@_originallyDefinedIn'", ())

ERROR(originally_defined_in_need_nonempty_module_name,none,
"original module name cannot be empty in @_originallyDefinedIn", ())
"original module name cannot be empty in '@_originallyDefinedIn'", ())

// backDeploy
ERROR(attr_back_deploy_expected_before_label,none,
Expand Down Expand Up @@ -1670,25 +1670,25 @@ ERROR(convention_attribute_witness_method_expected_protocol,none,

// objc
ERROR(attr_objc_missing_colon,none,
"missing ':' after selector piece in @objc attribute", ())
"missing ':' after selector piece in '@objc'", ())
ERROR(attr_objc_expected_rparen,none,
"expected ')' after name for @objc", ())
"expected ')' after name for '@objc'", ())
ERROR(attr_objc_empty_name,none,
"expected name within parentheses of @objc attribute", ())
"expected name within parentheses of '@objc'", ())

ERROR(attr_dynamic_replacement_expected_rparen,none,
"expected ')' after function name for @_dynamicReplacement", ())
"expected ')' after function name for '@_dynamicReplacement'", ())
ERROR(attr_dynamic_replacement_expected_function,none,
"expected a function name in @_dynamicReplacement(for:)", ())
"expected a function name in '@_dynamicReplacement(for:)'", ())
ERROR(attr_dynamic_replacement_expected_for,none,
"expected 'for' in '_dynamicReplacement' attribute", ())
ERROR(attr_dynamic_replacement_expected_colon,none,
"expected ':' after @_dynamicReplacement(for", ())
"expected ':' after '@_dynamicReplacement(for'", ())

ERROR(attr_type_eraser_expected_type_name,none,
"expected a type name in @_typeEraser()", ())
"expected a type name in '@_typeEraser()'", ())
ERROR(attr_type_eraser_expected_rparen,none,
"expected ')' after type name for @_typeEraser", ())
"expected ')' after type name for '@_typeEraser'", ())

ERROR(expected_thrown_error_type,none,
"expected thrown error type after 'throws('", ())
Expand All @@ -1706,13 +1706,13 @@ ERROR(attr_isolated_expected_kind,none,
"expected 'any' as the isolation kind", ())

ERROR(attr_private_import_expected_rparen,none,
"expected ')' after function name for @_private", ())
"expected ')' after function name for '@_private'", ())
ERROR(attr_private_import_expected_sourcefile, none,
"expected 'sourceFile' in '_private' attribute", ())
ERROR(attr_private_import_expected_sourcefile_name,none,
"expected a source file name in @_private(sourceFile:)", ())
"expected a source file name in '@_private(sourceFile:)'", ())
ERROR(attr_private_import_expected_colon,none,
"expected ':' after @_private(sourceFile", ())
"expected ':' after '@_private(sourceFile'", ())

// opened
ERROR(opened_attribute_expected_lparen,none,
Expand Down Expand Up @@ -1833,45 +1833,45 @@ ERROR(sil_inst_autodiff_expected_differentiability_witness_kind,PointsToFirstBad
"'[vjp]', or '[transpose]'", ())

WARNING(warn_attr_unsafe_removed,none,
"'%0' attribute has been removed in favor of @preconcurrency",
"'%0' attribute has been removed in favor of '@preconcurrency'",
(StringRef))

// _documentation
ERROR(documentation_attr_expected_argument,none,
"@_documentation attribute expected 'visibility' or 'metadata' argument",
"'_documentation' attribute expected 'visibility' or 'metadata' argument",
())
ERROR(documentation_attr_unknown_argument,none,
"unknown argument '%0', expected 'visibility' or 'metadata'",
(StringRef))
ERROR(documentation_attr_expected_access_level,none,
"@_documentation attribute's 'visibility' argument expected an access level",
"'_documentation' attribute's 'visibility' argument expected an access level",
())
ERROR(documentation_attr_unknown_access_level,none,
"unknown visibility '%0', expected an access level keyword",
(StringRef))
ERROR(documentation_attr_duplicate_visibility,none,
"cannot give more than one visibility to the same item", ())
ERROR(documentation_attr_metadata_expected_text,none,
"@_documentation attribute's 'metadata' argument expected an identifier or "
"'_documentation' attribute's 'metadata' argument expected an identifier or "
"quoted string",
())
ERROR(documentation_attr_duplicate_metadata,none,
"cannot give more than one metadata argument to the same item", ())

ERROR(attr_rawlayout_expected_label,none,
"expected %0 argument to @_rawLayout attribute", (StringRef))
"expected %0 argument to '@_rawLayout'", (StringRef))
ERROR(attr_rawlayout_expected_integer_size,none,
"expected integer literal size in @_rawLayout attribute", ())
"expected integer literal size in '@_rawLayout'", ())
ERROR(attr_rawlayout_expected_integer_alignment,none,
"expected integer literal alignment in @_rawLayout attribute", ())
"expected integer literal alignment in '@_rawLayout'", ())
ERROR(attr_rawlayout_expected_params,none,
"expected %1 argument after %0 argument in @_rawLayout attribute", (StringRef, StringRef))
"expected %1 argument after %0 argument in '@_rawLayout'", (StringRef, StringRef))

ERROR(attr_extern_expected_label,none,
"expected %0 argument to @_extern attribute", (StringRef))
"expected %0 argument to '@_extern'", (StringRef))

ERROR(attr_expected_feature_name,none,
"expected feature name in @%0 attribute", (StringRef))
"expected feature name in '@%0'", (StringRef))

//------------------------------------------------------------------------------
// MARK: Generics parsing diagnostics
Expand Down Expand Up @@ -2064,13 +2064,13 @@ ERROR(macro_role_syntax_mismatch,PointsToFirstBadToken,
"%select{a freestanding|an attached}0 macro cannot have the %1 role",
(bool, Identifier))
ERROR(macro_attribute_unknown_label,PointsToFirstBadToken,
"@%select{freestanding|attached}0 has no argument with label %1",
"'@%select{freestanding|attached}0' has no argument with label %1",
(bool, Identifier))
ERROR(macro_attribute_duplicate_label,PointsToFirstBadToken,
"@%select{freestanding|attached}0 already has an argument with "
"'@%select{freestanding|attached}0' already has an argument with "
"label %1", (bool, StringRef))
ERROR(macro_attribute_missing_label,none,
"@%select{freestanding|attached}0 argument is missing label '%1'",
"'@%select{freestanding|attached}0' argument is missing label '%1'",
(bool, StringRef))
ERROR(macro_attribute_unknown_name_kind,PointsToFirstBadToken,
"unknown introduced name kind %0", (Identifier))
Expand All @@ -2081,7 +2081,8 @@ ERROR(macro_attribute_introduced_name_requires_argument,PointsToFirstBadToken,
ERROR(macro_attribute_introduced_name_requires_no_argument,PointsToFirstBadToken,
"introduced name kind %0 must not have an argument", (Identifier))
WARNING(macro_expression_attribute_removed,PointsToFirstBadToken,
"@expression has been removed in favor of @freestanding(expression)", ())
"'@expression' has been removed in favor of '@freestanding(expression)'",
())

ERROR(unexpected_attribute_expansion,PointsToFirstBadToken,
"unexpected token '%0' in expanded attribute list",
Expand Down Expand Up @@ -2117,16 +2118,16 @@ ERROR(init_accessor_is_not_in_the_primary_declaration,none,
())

ERROR(missing_storage_restrictions_attr_label,none,
"missing label in @storageRestrictions attribute", ())
"missing label in '@storageRestrictions'", ())

ERROR(invalid_storage_restrictions_attr_label,none,
"unexpected label %0 in @storageRestrictions attribute", (Identifier))
"unexpected label %0 in '@storageRestrictions'", (Identifier))

ERROR(duplicate_storage_restrictions_attr_label,none,
"duplicate label %0 in @storageRestrictions attribute", (Identifier))
"duplicate label %0 in '@storageRestrictions'", (Identifier))

ERROR(storage_restrictions_attr_expected_name,none,
"expected property name in @storageRestrictions list", ())
"expected property name in '@storageRestrictions' list", ())

ERROR(requires_experimental_feature, none,
"'%0' %select{attribute|parameter specifier}1 is only valid when experimental feature "
Expand Down
14 changes: 8 additions & 6 deletions include/swift/AST/DiagnosticsSIL.def
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ ERROR(deserialize_function_type_mismatch,Fatal,
(StringRef, Type, Type))

ERROR(without_actually_escaping_on_isolated_any,none,
"withoutActuallyEscaping is currently unimplemented for @isolated(any) "
"withoutActuallyEscaping is currently unimplemented for '@isolated(any)' "
"function values", ())

// Capture before declaration diagnostics.
Expand Down Expand Up @@ -391,9 +391,9 @@ ERROR(embedded_swift_existential_protocol,none,
ERROR(embedded_swift_existential,none,
"cannot use a value of protocol type in embedded Swift", ())
ERROR(perf_diag_existential_type,none,
"cannot use a value of protocol type %0 in @_noExistential function", (Type))
"cannot use a value of protocol type %0 in '@_noExistential' function", (Type))
ERROR(perf_diag_existential,none,
"cannot use a value of protocol type in @_noExistential function", ())
"cannot use a value of protocol type in '@_noExistential' function", ())
ERROR(embedded_swift_value_deinit,none,
"cannot de-virtualize deinit of type %0", (Type))
ERROR(embedded_swift_metatype_type,none,
Expand Down Expand Up @@ -824,7 +824,7 @@ NOTE(capturepromotion_variable_defined_here,none,

// noimplicitcopy on generic or existential binding
ERROR(noimplicitcopy_used_on_generic_or_existential, none,
"@_noImplicitCopy can not be used on a generic or existential typed "
"'@_noImplicitCopy' can not be used on a generic or existential typed "
"binding or a nominal type containing such typed things", ())

// discard statement
Expand Down Expand Up @@ -879,7 +879,8 @@ ERROR(sil_movechecking_cannot_destructure_imported_nonfrozen, none,
"cannot partially consume '%0' of non-frozen type %1 imported from %2",
(StringRef, Type, const ModuleDecl*))
ERROR(sil_movechecking_cannot_destructure_exported_usableFromInline_alwaysEmitIntoClient, none,
"cannot partially consume '%0' of non-frozen usableFromInline type %1 within a function annotated @_alwaysEmitIntoClient",
"cannot partially consume '%0' of non-frozen usableFromInline type %1 "
"within a function annotated '@_alwaysEmitIntoClient'",
(StringRef, Type))
ERROR(sil_movechecking_cannot_destructure, none,
"cannot partially consume '%0'",
Expand All @@ -891,7 +892,8 @@ ERROR(sil_movechecking_cannot_partially_reinit_nonfrozen, none,
"cannot partially reinitialize '%0' of non-frozen type %1 imported from %2; only full reinitialization is allowed",
(StringRef, Type, const ModuleDecl*))
ERROR(sil_movechecking_cannot_partially_reinit_exported_usableFromInline_alwaysEmitIntoClient, none,
"cannot partially reinitialize '%0' of non-frozen usableFromInline type %1 within a function annotated @_alwaysEmitIntoClient",
"cannot partially reinitialize '%0' of non-frozen usableFromInline type "
"%1 within a function annotated '@_alwaysEmitIntoClient'",
(StringRef, Type))
ERROR(sil_movechecking_cannot_partially_reinit, none,
"cannot partially reinitialize '%0' after it has been consumed; only full reinitialization is allowed",
Expand Down
Loading