Categorization of warnings in Swift

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:
Categorize based on broad language-feature/compiler-area. E.g. "Availability" or “CommandLineArguments”
Categorize based on the kind of warning. E.g. "Deprecated" or “Uninitialized"
Categorize based on severity or specificity of warnings. E.g. "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example, there's
a handful of warnings that makes less sense in a REPL or rapid experimentation
environment, such as variable_never_mutated.

Here's a straw-man proposal of some categorization. Of course, one developer's
annoying pedantic warning is another's life-saving code-smell detector. I am not
personally tied to these categorizations at all, I'm just interested in there
being something simple and basic. Below is a list of every warning in Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will "
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"
    required_initializer_override_keyword
        "'override' is implied when overriding a required initializer"
    if_always_true
        "'if' condition is always true"
    while_always_true
        "'while' condition is always true"
    warn_protocol_witness_optionality
        "%select{type|result|parameter|parameters|"
        "result and parameters}0 of %1 %select{has|has|has|have|have|}0"
        " different optionality than expected by protocol %2"
    optional_req_nonobjc_near_match
        "non-@objc %select{initializer %1|method %1|property %1|subscript}0 "
        "cannot satisfy optional requirement of @objc protocol %2"
    override_unnecessary_IUO
        "overriding %0 parameter of type %1 with implicitly unwrapped optional "
        "type %2",
    override_unnecessary_result_IUO
        "overriding %0 optional result type %1 with implicitly unwrapped "
        "optional type %2",
    inject_forced_downcast, sema_tce, none,
        "treating a forced downcast to %0 as optional will never produce 'nil'"
    recursive_accessor_reference, tce_sema, none,
        "attempting to %select{access|modify}1 %0 within its own "
        "%select{getter|setter}1",
    store_in_willset, tce_sema, none,
        "attempting to store to property %0 within its own willSet, which is "
        "about to be overwritten by the new value",
    isa_is_always_true
        "'%0' test is always true",
    conditional_downcast_coercion
        "conditional cast from %0 to %1 always succeeds"
    downcast_to_unrelated, sema_tcc, none,
        "cast from %0 to unrelated type %1 always fails"
    forced_downcast_noop
        "forced cast of %0 to same type has no effect"
    forced_downcast_coercion
        "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?"
    extraneous_default_args_in_call
        "call to %0 has extraneous arguments that could use defaults"
    unreachable_code
        "will never be executed"
    unreachable_code_after_stmt
        "code after '%select{return|break|continue|throw}0' will never "
        "be executed"
    unreachable_case
        "%select{case|default}0 will never be executed"
    switch_on_a_constant
        "switch condition evaluates to a constant"
    integer_conversion_overflow_warn
        "integer overflows when converted from %0 to %1"
    integer_literal_overflow_warn
        "integer literal overflows when stored into %0"
    trailing_closure_excess_newlines
        "trailing closure is separated from call site by multiple newlines"
    lex_nul_character, lexing, none
        "nul character embedded in middle of file"
    unindented_code_after_return
        "expression following 'return' is treated as an argument of "
        "the 'return'"
    lex_editor_placeholder_in_playground
        "editor placeholder in source file"

Attributes:
    attr_availability_unknown_platform
        "unknown platform '%0' for attribute '%1'"
    attr_warn_unused_result_expected_name
        "expected parameter 'message' or 'mutable_variant'"
    attr_warn_unused_result_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    attr_warn_unused_result_unknown_parameter
        "unknown parameter '%0' in 'warn_unused_result' attribute"
    attr_migration_id_expected_name
        "expected parameter 'pattern'"
    attr_migration_id_unknown_parameter
        "unknown parameter '%0' in '_migration_id' attribute"
    attr_migration_id_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    invalid_swift_name_method
        "too %select{few|many}0 parameters in swift_name attribute (expected %1; "
        "got %2)"

Availability:
    availability_query_useless_min_deployment
        "unnecessary check for '%0'; minimum deployment target ensures guard "
        "will always be true"
    availability_query_useless_enclosing_scope
        "unnecessary check for '%0'; enclosing scope ensures guard "
        "will always be true"

And the below I'm either struggling to think about how to categorize them
(perhaps no category at first), or un-familiar with what they're targeting
    warning_from_clang:
        "%0"
    could_not_rewrite_bridging_header, none, none,
        "failed to serialize bridging header; "
        "target may not be debuggable outside of its original project"
    omit_needless_words
        "%0 could be named %1 [-Womit-needless-words]"
    unused_compiler_version_component
        "the second version component is not used for comparison"
    unknown_build_config
        "unknown %0 for build configuration '%1'"
    sema_import_current_module
        "this file is part of module %0; ignoring import"
    sema_import_current_module_with_file
        "file '%0' is part of module %1; ignoring import"
    access_control_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 for "
        "%select{a private|an internal|PUBLIC}2 %3"
    access_control_ext_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 in "
        "%select{a private|an internal|PUBLIC}2 extension"
    emit_reference_dependencies_without_primary_file
        "ignoring -emit-reference-dependencies (requires -primary-file)"
    warning_no_such_sdk
        "no such SDK: '%0'"
    warn_cannot_stat_input
        "unable to determine when '%0' was last modified: %1"
    warning_unnecessary_repl_mode
        "unnecessary option '%0'; this is the default for '%1' "
        "with no input files"
    incremental_requires_output_file_map
        "ignoring -incremental (currently requires an output file map)"
    incremental_requires_build_record_entry
        "ignoring -incremental; output file map has no master dependencies "
        "entry (\"%0\" under \"\")"

I haven’t gotten to how to expose this to the user, and I’ll defer to the community for suggestions in that area.

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:

   1. Categorize based on broad language-feature/compiler-area. E.g.
   "Availability" or “CommandLineArguments”
   2. Categorize based on the kind of warning. E.g. "Deprecated" or
    “Uninitialized"
   3. Categorize based on severity or specificity of warnings. E.g.
   "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example,
there's
a handful of warnings that makes less sense in a REPL or rapid
experimentation
environment, such as variable_never_mutated.

Since we try to keep warnings on-by-default, the primary usecase will
probably be disabling warnings that are somehow inappropriate for the
project.

Here's a straw-man proposal of some categorization. Of course, one

developer's
annoying pedantic warning is another's life-saving code-smell detector. I
am not
personally tied to these categorizations at all, I'm just interested in
there
being something simple and basic. Below is a list of every warning in
Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be
"
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a
future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

I think there should be separate categories for deprecated language
features and deprecated APIs.

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial
execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never
used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will
"
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do'
block"

It seems like some of these can be too pedantic in cross-platform code
bases because of if's that are not analyzable and might need more granular
suppression mechanisms. For example:

func foo() throws {}
func bar() {}

func baz() {
  do {
if os(OSX)
    try foo()
#else
    bar()
#endif
    // common code.
  } catch { // on non-OS X, warning: 'catch' block is unreachable because
no errors are thrown in 'do' block
    // ...
  }
}

I definitely remember we had some similar issues in the standard library or
tests, but don't remember the specifics.

Dmitri

···

On Tue, Jan 12, 2016 at 9:44 AM, Michael Ilseman via swift-dev < swift-dev@swift.org> wrote:

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:
Categorize based on broad language-feature/compiler-area. E.g. "Availability" or “CommandLineArguments”
Categorize based on the kind of warning. E.g. "Deprecated" or “Uninitialized"
Categorize based on severity or specificity of warnings. E.g. "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example, there's
a handful of warnings that makes less sense in a REPL or rapid experimentation
environment, such as variable_never_mutated.

Here's a straw-man proposal of some categorization. Of course, one developer's
annoying pedantic warning is another's life-saving code-smell detector. I am not
personally tied to these categorizations at all, I'm just interested in there
being something simple and basic. Below is a list of every warning in Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will "
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"
    required_initializer_override_keyword
        "'override' is implied when overriding a required initializer"
    if_always_true
        "'if' condition is always true"
    while_always_true
        "'while' condition is always true"
    warn_protocol_witness_optionality
        "%select{type|result|parameter|parameters|"
        "result and parameters}0 of %1 %select{has|has|has|have|have|}0"
        " different optionality than expected by protocol %2"
    optional_req_nonobjc_near_match
        "non-@objc %select{initializer %1|method %1|property %1|subscript}0 "
        "cannot satisfy optional requirement of @objc protocol %2"
    override_unnecessary_IUO
        "overriding %0 parameter of type %1 with implicitly unwrapped optional "
        "type %2",
    override_unnecessary_result_IUO
        "overriding %0 optional result type %1 with implicitly unwrapped "
        "optional type %2",
    inject_forced_downcast, sema_tce, none,
        "treating a forced downcast to %0 as optional will never produce 'nil'"
    recursive_accessor_reference, tce_sema, none,
        "attempting to %select{access|modify}1 %0 within its own "
        "%select{getter|setter}1",
    store_in_willset, tce_sema, none,
        "attempting to store to property %0 within its own willSet, which is "
        "about to be overwritten by the new value",
    isa_is_always_true
        "'%0' test is always true",
    conditional_downcast_coercion
        "conditional cast from %0 to %1 always succeeds"
    downcast_to_unrelated, sema_tcc, none,
        "cast from %0 to unrelated type %1 always fails"
    forced_downcast_noop
        "forced cast of %0 to same type has no effect"
    forced_downcast_coercion
        "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?"
    extraneous_default_args_in_call
        "call to %0 has extraneous arguments that could use defaults"
    unreachable_code
        "will never be executed"
    unreachable_code_after_stmt
        "code after '%select{return|break|continue|throw}0' will never "
        "be executed"
    unreachable_case
        "%select{case|default}0 will never be executed"
    switch_on_a_constant
        "switch condition evaluates to a constant"
    integer_conversion_overflow_warn
        "integer overflows when converted from %0 to %1"
    integer_literal_overflow_warn
        "integer literal overflows when stored into %0"
    trailing_closure_excess_newlines
        "trailing closure is separated from call site by multiple newlines"
    lex_nul_character, lexing, none
        "nul character embedded in middle of file"
    unindented_code_after_return
        "expression following 'return' is treated as an argument of "
        "the 'return'"
    lex_editor_placeholder_in_playground
        "editor placeholder in source file"

Attributes:
    attr_availability_unknown_platform
        "unknown platform '%0' for attribute '%1'"
    attr_warn_unused_result_expected_name
        "expected parameter 'message' or 'mutable_variant'"
    attr_warn_unused_result_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    attr_warn_unused_result_unknown_parameter
        "unknown parameter '%0' in 'warn_unused_result' attribute"
    attr_migration_id_expected_name
        "expected parameter 'pattern'"
    attr_migration_id_unknown_parameter
        "unknown parameter '%0' in '_migration_id' attribute"
    attr_migration_id_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    invalid_swift_name_method
        "too %select{few|many}0 parameters in swift_name attribute (expected %1; "
        "got %2)"

Availability:
    availability_query_useless_min_deployment
        "unnecessary check for '%0'; minimum deployment target ensures guard "
        "will always be true"
    availability_query_useless_enclosing_scope
        "unnecessary check for '%0'; enclosing scope ensures guard "
        "will always be true"

And the below I'm either struggling to think about how to categorize them
(perhaps no category at first), or un-familiar with what they're targeting
    warning_from_clang:
        "%0"
    could_not_rewrite_bridging_header, none, none,
        "failed to serialize bridging header; "
        "target may not be debuggable outside of its original project"
    omit_needless_words
        "%0 could be named %1 [-Womit-needless-words]"
    unused_compiler_version_component
        "the second version component is not used for comparison"
    unknown_build_config
        "unknown %0 for build configuration '%1'"
    sema_import_current_module
        "this file is part of module %0; ignoring import"
    sema_import_current_module_with_file
        "file '%0' is part of module %1; ignoring import"
    access_control_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 for "
        "%select{a private|an internal|PUBLIC}2 %3"
    access_control_ext_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 in "
        "%select{a private|an internal|PUBLIC}2 extension"
    emit_reference_dependencies_without_primary_file
        "ignoring -emit-reference-dependencies (requires -primary-file)"
    warning_no_such_sdk
        "no such SDK: '%0'"
    warn_cannot_stat_input
        "unable to determine when '%0' was last modified: %1"
    warning_unnecessary_repl_mode
        "unnecessary option '%0'; this is the default for '%1' "
        "with no input files"
    incremental_requires_output_file_map
        "ignoring -incremental (currently requires an output file map)"
    incremental_requires_build_record_entry
        "ignoring -incremental; output file map has no master dependencies "
        "entry (\"%0\" under \"\")"

I haven’t gotten to how to expose this to the user, and I’ll defer to the community for suggestions in that area.

Just an FYI: We have also talked about performance related warnings at the SIL level (that could potentially be a hard error). We do not have any such thing implemented right now, but keep it in mind.

Michael

···

On Jan 12, 2016, at 9:44 AM, Michael Ilseman via swift-dev <swift-dev@swift.org> wrote:

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Hi, Michael. As one of the people who's been a strong believer of "warning flags result in style dialects", I think it's important to establish a use case here. What will people actually do with warning categories? What warnings will we allow turning off? Under what contexts?

For the "variable never mutated" warning, you mentioned that this doesn't make sense in a rapid experimentation environment. I'd say more specifically that it doesn't make sense in code you're actively changing. But Live Issues should be able to know what code you're actively changing, and only suppress the warning there.

(We do have some ad hoc categorization today, including "REPL mode" as you mentioned. I'm fine with making that something more general.)

I guess I'd rather avoid eagerly classifying warnings, and I'll continue to argue against -W* and -Wno-* flags for the time being.

Jordan

···

On Jan 12, 2016, at 9:44, Michael Ilseman via swift-dev <swift-dev@swift.org> wrote:

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:
Categorize based on broad language-feature/compiler-area. E.g. "Availability" or “CommandLineArguments”
Categorize based on the kind of warning. E.g. "Deprecated" or “Uninitialized"
Categorize based on severity or specificity of warnings. E.g. "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example, there's
a handful of warnings that makes less sense in a REPL or rapid experimentation
environment, such as variable_never_mutated.

Here's a straw-man proposal of some categorization. Of course, one developer's
annoying pedantic warning is another's life-saving code-smell detector. I am not
personally tied to these categorizations at all, I'm just interested in there
being something simple and basic. Below is a list of every warning in Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will "
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"
    required_initializer_override_keyword
        "'override' is implied when overriding a required initializer"
    if_always_true
        "'if' condition is always true"
    while_always_true
        "'while' condition is always true"
    warn_protocol_witness_optionality
        "%select{type|result|parameter|parameters|"
        "result and parameters}0 of %1 %select{has|has|has|have|have|}0"
        " different optionality than expected by protocol %2"
    optional_req_nonobjc_near_match
        "non-@objc %select{initializer %1|method %1|property %1|subscript}0 "
        "cannot satisfy optional requirement of @objc protocol %2"
    override_unnecessary_IUO
        "overriding %0 parameter of type %1 with implicitly unwrapped optional "
        "type %2",
    override_unnecessary_result_IUO
        "overriding %0 optional result type %1 with implicitly unwrapped "
        "optional type %2",
    inject_forced_downcast, sema_tce, none,
        "treating a forced downcast to %0 as optional will never produce 'nil'"
    recursive_accessor_reference, tce_sema, none,
        "attempting to %select{access|modify}1 %0 within its own "
        "%select{getter|setter}1",
    store_in_willset, tce_sema, none,
        "attempting to store to property %0 within its own willSet, which is "
        "about to be overwritten by the new value",
    isa_is_always_true
        "'%0' test is always true",
    conditional_downcast_coercion
        "conditional cast from %0 to %1 always succeeds"
    downcast_to_unrelated, sema_tcc, none,
        "cast from %0 to unrelated type %1 always fails"
    forced_downcast_noop
        "forced cast of %0 to same type has no effect"
    forced_downcast_coercion
        "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?"
    extraneous_default_args_in_call
        "call to %0 has extraneous arguments that could use defaults"
    unreachable_code
        "will never be executed"
    unreachable_code_after_stmt
        "code after '%select{return|break|continue|throw}0' will never "
        "be executed"
    unreachable_case
        "%select{case|default}0 will never be executed"
    switch_on_a_constant
        "switch condition evaluates to a constant"
    integer_conversion_overflow_warn
        "integer overflows when converted from %0 to %1"
    integer_literal_overflow_warn
        "integer literal overflows when stored into %0"
    trailing_closure_excess_newlines
        "trailing closure is separated from call site by multiple newlines"
    lex_nul_character, lexing, none
        "nul character embedded in middle of file"
    unindented_code_after_return
        "expression following 'return' is treated as an argument of "
        "the 'return'"
    lex_editor_placeholder_in_playground
        "editor placeholder in source file"

Attributes:
    attr_availability_unknown_platform
        "unknown platform '%0' for attribute '%1'"
    attr_warn_unused_result_expected_name
        "expected parameter 'message' or 'mutable_variant'"
    attr_warn_unused_result_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    attr_warn_unused_result_unknown_parameter
        "unknown parameter '%0' in 'warn_unused_result' attribute"
    attr_migration_id_expected_name
        "expected parameter 'pattern'"
    attr_migration_id_unknown_parameter
        "unknown parameter '%0' in '_migration_id' attribute"
    attr_migration_id_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    invalid_swift_name_method
        "too %select{few|many}0 parameters in swift_name attribute (expected %1; "
        "got %2)"

Availability:
    availability_query_useless_min_deployment
        "unnecessary check for '%0'; minimum deployment target ensures guard "
        "will always be true"
    availability_query_useless_enclosing_scope
        "unnecessary check for '%0'; enclosing scope ensures guard "
        "will always be true"

And the below I'm either struggling to think about how to categorize them
(perhaps no category at first), or un-familiar with what they're targeting
    warning_from_clang:
        "%0"
    could_not_rewrite_bridging_header, none, none,
        "failed to serialize bridging header; "
        "target may not be debuggable outside of its original project"
    omit_needless_words
        "%0 could be named %1 [-Womit-needless-words]"
    unused_compiler_version_component
        "the second version component is not used for comparison"
    unknown_build_config
        "unknown %0 for build configuration '%1'"
    sema_import_current_module
        "this file is part of module %0; ignoring import"
    sema_import_current_module_with_file
        "file '%0' is part of module %1; ignoring import"
    access_control_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 for "
        "%select{a private|an internal|PUBLIC}2 %3"
    access_control_ext_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 in "
        "%select{a private|an internal|PUBLIC}2 extension"
    emit_reference_dependencies_without_primary_file
        "ignoring -emit-reference-dependencies (requires -primary-file)"
    warning_no_such_sdk
        "no such SDK: '%0'"
    warn_cannot_stat_input
        "unable to determine when '%0' was last modified: %1"
    warning_unnecessary_repl_mode
        "unnecessary option '%0'; this is the default for '%1' "
        "with no input files"
    incremental_requires_output_file_map
        "ignoring -incremental (currently requires an output file map)"
    incremental_requires_build_record_entry
        "ignoring -incremental; output file map has no master dependencies "
        "entry (\"%0\" under \"\")"

I haven’t gotten to how to expose this to the user, and I’ll defer to the community for suggestions in that area.

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:
Categorize based on broad language-feature/compiler-area. E.g. "Availability" or “CommandLineArguments”
Categorize based on the kind of warning. E.g. "Deprecated" or “Uninitialized"
Categorize based on severity or specificity of warnings. E.g. "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example, there's
a handful of warnings that makes less sense in a REPL or rapid experimentation
environment, such as variable_never_mutated.

Since we try to keep warnings on-by-default, the primary usecase will probably be disabling warnings that are somehow inappropriate for the project.

That makes sense.

Here's a straw-man proposal of some categorization. Of course, one developer's
annoying pedantic warning is another's life-saving code-smell detector. I am not
personally tied to these categorizations at all, I'm just interested in there
being something simple and basic. Below is a list of every warning in Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

I think there should be separate categories for deprecated language features and deprecated APIs.

It might also make sense for there to be a DeprecatedTooling or some such for deprecated command line flags, etc. Here’s it broken down some more:

DeprecatedLanguage:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        “instead"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

DeprecatedAPI:
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"

DeprecatedTooling:
  TBD

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will "
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"

It seems like some of these can be too pedantic in cross-platform code bases because of if's that are not analyzable and might need more granular suppression mechanisms. For example:

func foo() throws {}
func bar() {}

func baz() {
  do {
if os(OSX)
    try foo()
#else
    bar()
#endif
    // common code.
  } catch { // on non-OS X, warning: 'catch' block is unreachable because no errors are thrown in 'do' block
    // ...
  }
}

I definitely remember we had some similar issues in the standard library or tests, but don't remember the specifics.

Ah, I didn’t think about that. I suppose classification is even more of a gray area than I thought. Do you think that certain ones are more likely than others to come up as a result of platform differences?

no_throw_in_do_with_catch, no_throw_in_try seem like prime examples. How often is it that platform differences yield always-true conditions or unreachable code?

···

On Jan 12, 2016, at 1:24 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote:
On Tue, Jan 12, 2016 at 9:44 AM, Michael Ilseman via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

Dmitri

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com <mailto:gribozavr@gmail.com>>*/

By keeping it in mind, do you mean to allow for more categories to be added in the future, or does this affect the fundamental design?

···

On Jan 12, 2016, at 5:06 PM, Michael Gottesman <mgottesman@apple.com> wrote:

On Jan 12, 2016, at 9:44 AM, Michael Ilseman via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:
Categorize based on broad language-feature/compiler-area. E.g. "Availability" or “CommandLineArguments”
Categorize based on the kind of warning. E.g. "Deprecated" or “Uninitialized"
Categorize based on severity or specificity of warnings. E.g. "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example, there's
a handful of warnings that makes less sense in a REPL or rapid experimentation
environment, such as variable_never_mutated.

Here's a straw-man proposal of some categorization. Of course, one developer's
annoying pedantic warning is another's life-saving code-smell detector. I am not
personally tied to these categorizations at all, I'm just interested in there
being something simple and basic. Below is a list of every warning in Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will "
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"
    required_initializer_override_keyword
        "'override' is implied when overriding a required initializer"
    if_always_true
        "'if' condition is always true"
    while_always_true
        "'while' condition is always true"
    warn_protocol_witness_optionality
        "%select{type|result|parameter|parameters|"
        "result and parameters}0 of %1 %select{has|has|has|have|have|}0"
        " different optionality than expected by protocol %2"
    optional_req_nonobjc_near_match
        "non-@objc %select{initializer %1|method %1|property %1|subscript}0 "
        "cannot satisfy optional requirement of @objc protocol %2"
    override_unnecessary_IUO
        "overriding %0 parameter of type %1 with implicitly unwrapped optional "
        "type %2",
    override_unnecessary_result_IUO
        "overriding %0 optional result type %1 with implicitly unwrapped "
        "optional type %2",
    inject_forced_downcast, sema_tce, none,
        "treating a forced downcast to %0 as optional will never produce 'nil'"
    recursive_accessor_reference, tce_sema, none,
        "attempting to %select{access|modify}1 %0 within its own "
        "%select{getter|setter}1",
    store_in_willset, tce_sema, none,
        "attempting to store to property %0 within its own willSet, which is "
        "about to be overwritten by the new value",
    isa_is_always_true
        "'%0' test is always true",
    conditional_downcast_coercion
        "conditional cast from %0 to %1 always succeeds"
    downcast_to_unrelated, sema_tcc, none,
        "cast from %0 to unrelated type %1 always fails"
    forced_downcast_noop
        "forced cast of %0 to same type has no effect"
    forced_downcast_coercion
        "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?"
    extraneous_default_args_in_call
        "call to %0 has extraneous arguments that could use defaults"
    unreachable_code
        "will never be executed"
    unreachable_code_after_stmt
        "code after '%select{return|break|continue|throw}0' will never "
        "be executed"
    unreachable_case
        "%select{case|default}0 will never be executed"
    switch_on_a_constant
        "switch condition evaluates to a constant"
    integer_conversion_overflow_warn
        "integer overflows when converted from %0 to %1"
    integer_literal_overflow_warn
        "integer literal overflows when stored into %0"
    trailing_closure_excess_newlines
        "trailing closure is separated from call site by multiple newlines"
    lex_nul_character, lexing, none
        "nul character embedded in middle of file"
    unindented_code_after_return
        "expression following 'return' is treated as an argument of "
        "the 'return'"
    lex_editor_placeholder_in_playground
        "editor placeholder in source file"

Attributes:
    attr_availability_unknown_platform
        "unknown platform '%0' for attribute '%1'"
    attr_warn_unused_result_expected_name
        "expected parameter 'message' or 'mutable_variant'"
    attr_warn_unused_result_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    attr_warn_unused_result_unknown_parameter
        "unknown parameter '%0' in 'warn_unused_result' attribute"
    attr_migration_id_expected_name
        "expected parameter 'pattern'"
    attr_migration_id_unknown_parameter
        "unknown parameter '%0' in '_migration_id' attribute"
    attr_migration_id_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    invalid_swift_name_method
        "too %select{few|many}0 parameters in swift_name attribute (expected %1; "
        "got %2)"

Availability:
    availability_query_useless_min_deployment
        "unnecessary check for '%0'; minimum deployment target ensures guard "
        "will always be true"
    availability_query_useless_enclosing_scope
        "unnecessary check for '%0'; enclosing scope ensures guard "
        "will always be true"

And the below I'm either struggling to think about how to categorize them
(perhaps no category at first), or un-familiar with what they're targeting
    warning_from_clang:
        "%0"
    could_not_rewrite_bridging_header, none, none,
        "failed to serialize bridging header; "
        "target may not be debuggable outside of its original project"
    omit_needless_words
        "%0 could be named %1 [-Womit-needless-words]"
    unused_compiler_version_component
        "the second version component is not used for comparison"
    unknown_build_config
        "unknown %0 for build configuration '%1'"
    sema_import_current_module
        "this file is part of module %0; ignoring import"
    sema_import_current_module_with_file
        "file '%0' is part of module %1; ignoring import"
    access_control_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 for "
        "%select{a private|an internal|PUBLIC}2 %3"
    access_control_ext_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 in "
        "%select{a private|an internal|PUBLIC}2 extension"
    emit_reference_dependencies_without_primary_file
        "ignoring -emit-reference-dependencies (requires -primary-file)"
    warning_no_such_sdk
        "no such SDK: '%0'"
    warn_cannot_stat_input
        "unable to determine when '%0' was last modified: %1"
    warning_unnecessary_repl_mode
        "unnecessary option '%0'; this is the default for '%1' "
        "with no input files"
    incremental_requires_output_file_map
        "ignoring -incremental (currently requires an output file map)"
    incremental_requires_build_record_entry
        "ignoring -incremental; output file map has no master dependencies "
        "entry (\"%0\" under \"\")"

I haven’t gotten to how to expose this to the user, and I’ll defer to the community for suggestions in that area.

Just an FYI: We have also talked about performance related warnings at the SIL level (that could potentially be a hard error). We do not have any such thing implemented right now, but keep it in mind.

Michael

_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev

Hi, Michael. As one of the people who's been a strong believer of "warning flags result in style dialects", I think it's important to establish a use case here. What will people actually do with warning categories? What warnings will we allow turning off? Under what contexts?

For the "variable never mutated" warning, you mentioned that this doesn't make sense in a rapid experimentation environment. I'd say more specifically that it doesn't make sense in code you're actively changing. But Live Issues should be able to know what code you're actively changing, and only suppress the warning there.

(We do have some ad hoc categorization today, including "REPL mode" as you mentioned. I'm fine with making that something more general.)

I’ll look more at REPL mode and see how to better generalize that. It’s more in line with what I’m trying to accomplish, and it may not make sense to categorize all the warnings in Swift so much as call out limited sub-sets. If that’s the case, and doing so is more so the exception than the rule, then I’m more amenable to tags and/or Kate’s suggestions.

I guess I'd rather avoid eagerly classifying warnings, and I'll continue to argue against -W* and -Wno-* flags for the time being.

What about global flags, such as “-Werr” or equivalent? Do you have any thoughts about Dmitri’s point on multi-platform libraries and how they sometimes can trigger strict stylistic warnings excessively?

···

On Jan 13, 2016, at 1:43 PM, Jordan Rose <jordan_rose@apple.com> wrote:

Jordan

On Jan 12, 2016, at 9:44, Michael Ilseman via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:
Categorize based on broad language-feature/compiler-area. E.g. "Availability" or “CommandLineArguments”
Categorize based on the kind of warning. E.g. "Deprecated" or “Uninitialized"
Categorize based on severity or specificity of warnings. E.g. "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example, there's
a handful of warnings that makes less sense in a REPL or rapid experimentation
environment, such as variable_never_mutated.

Here's a straw-man proposal of some categorization. Of course, one developer's
annoying pedantic warning is another's life-saving code-smell detector. I am not
personally tied to these categorizations at all, I'm just interested in there
being something simple and basic. Below is a list of every warning in Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will "
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"
    required_initializer_override_keyword
        "'override' is implied when overriding a required initializer"
    if_always_true
        "'if' condition is always true"
    while_always_true
        "'while' condition is always true"
    warn_protocol_witness_optionality
        "%select{type|result|parameter|parameters|"
        "result and parameters}0 of %1 %select{has|has|has|have|have|}0"
        " different optionality than expected by protocol %2"
    optional_req_nonobjc_near_match
        "non-@objc %select{initializer %1|method %1|property %1|subscript}0 "
        "cannot satisfy optional requirement of @objc protocol %2"
    override_unnecessary_IUO
        "overriding %0 parameter of type %1 with implicitly unwrapped optional "
        "type %2",
    override_unnecessary_result_IUO
        "overriding %0 optional result type %1 with implicitly unwrapped "
        "optional type %2",
    inject_forced_downcast, sema_tce, none,
        "treating a forced downcast to %0 as optional will never produce 'nil'"
    recursive_accessor_reference, tce_sema, none,
        "attempting to %select{access|modify}1 %0 within its own "
        "%select{getter|setter}1",
    store_in_willset, tce_sema, none,
        "attempting to store to property %0 within its own willSet, which is "
        "about to be overwritten by the new value",
    isa_is_always_true
        "'%0' test is always true",
    conditional_downcast_coercion
        "conditional cast from %0 to %1 always succeeds"
    downcast_to_unrelated, sema_tcc, none,
        "cast from %0 to unrelated type %1 always fails"
    forced_downcast_noop
        "forced cast of %0 to same type has no effect"
    forced_downcast_coercion
        "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?"
    extraneous_default_args_in_call
        "call to %0 has extraneous arguments that could use defaults"
    unreachable_code
        "will never be executed"
    unreachable_code_after_stmt
        "code after '%select{return|break|continue|throw}0' will never "
        "be executed"
    unreachable_case
        "%select{case|default}0 will never be executed"
    switch_on_a_constant
        "switch condition evaluates to a constant"
    integer_conversion_overflow_warn
        "integer overflows when converted from %0 to %1"
    integer_literal_overflow_warn
        "integer literal overflows when stored into %0"
    trailing_closure_excess_newlines
        "trailing closure is separated from call site by multiple newlines"
    lex_nul_character, lexing, none
        "nul character embedded in middle of file"
    unindented_code_after_return
        "expression following 'return' is treated as an argument of "
        "the 'return'"
    lex_editor_placeholder_in_playground
        "editor placeholder in source file"

Attributes:
    attr_availability_unknown_platform
        "unknown platform '%0' for attribute '%1'"
    attr_warn_unused_result_expected_name
        "expected parameter 'message' or 'mutable_variant'"
    attr_warn_unused_result_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    attr_warn_unused_result_unknown_parameter
        "unknown parameter '%0' in 'warn_unused_result' attribute"
    attr_migration_id_expected_name
        "expected parameter 'pattern'"
    attr_migration_id_unknown_parameter
        "unknown parameter '%0' in '_migration_id' attribute"
    attr_migration_id_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    invalid_swift_name_method
        "too %select{few|many}0 parameters in swift_name attribute (expected %1; "
        "got %2)"

Availability:
    availability_query_useless_min_deployment
        "unnecessary check for '%0'; minimum deployment target ensures guard "
        "will always be true"
    availability_query_useless_enclosing_scope
        "unnecessary check for '%0'; enclosing scope ensures guard "
        "will always be true"

And the below I'm either struggling to think about how to categorize them
(perhaps no category at first), or un-familiar with what they're targeting
    warning_from_clang:
        "%0"
    could_not_rewrite_bridging_header, none, none,
        "failed to serialize bridging header; "
        "target may not be debuggable outside of its original project"
    omit_needless_words
        "%0 could be named %1 [-Womit-needless-words]"
    unused_compiler_version_component
        "the second version component is not used for comparison"
    unknown_build_config
        "unknown %0 for build configuration '%1'"
    sema_import_current_module
        "this file is part of module %0; ignoring import"
    sema_import_current_module_with_file
        "file '%0' is part of module %1; ignoring import"
    access_control_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 for "
        "%select{a private|an internal|PUBLIC}2 %3"
    access_control_ext_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 in "
        "%select{a private|an internal|PUBLIC}2 extension"
    emit_reference_dependencies_without_primary_file
        "ignoring -emit-reference-dependencies (requires -primary-file)"
    warning_no_such_sdk
        "no such SDK: '%0'"
    warn_cannot_stat_input
        "unable to determine when '%0' was last modified: %1"
    warning_unnecessary_repl_mode
        "unnecessary option '%0'; this is the default for '%1' "
        "with no input files"
    incremental_requires_output_file_map
        "ignoring -incremental (currently requires an output file map)"
    incremental_requires_build_record_entry
        "ignoring -incremental; output file map has no master dependencies "
        "entry (\"%0\" under \"\")"

I haven’t gotten to how to expose this to the user, and I’ll defer to the community for suggestions in that area.

_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev

FWIW, one of the reasons we build an AST for disabled if regions is so we can be smart about this sort of thing. The fact that we don’t for this warning is a bug in the warning, not something we should use warning suppression to fix.

To give you an example of this in action, we currently warn on this:

func f() -> Int {
  var x = 42 // warning: variable 'x' was never mutated; consider changing to 'let' constant
  return x
}

but are smart enough to not warn on this:

func f() -> Int {
  var x = 42
if false
  x = 12
#endif
  return x
}

We should do the same for catch blocks that have a try in a disabled region.

-Chris

···

On Jan 12, 2016, at 1:24 PM, Dmitri Gribenko via swift-dev <swift-dev@swift.org> wrote:

        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"

It seems like some of these can be too pedantic in cross-platform code bases because of if's that are not analyzable and might need more granular suppression mechanisms. For example:

func foo() throws {}
func bar() {}

func baz() {
  do {
if os(OSX)
    try foo()
#else
    bar()
#endif
    // common code.
  } catch { // on non-OS X, warning: 'catch' block is unreachable because no errors are thrown in 'do' block
    // ...
  }
}

I definitely remember we had some similar issues in the standard library or tests, but don't remember the specifics.

Jordan, there is a class of warnings that we want to disable in Playgrounds, simply because they don’t make sense for that use case.

You could argue that the IDE should just ignore certain errors in this case, but that leads to tight coupling and fragility, this is better managed by having there be a -Wno-playgrounds sort of flag, so we can manage it on the compiler side.

-Chris

···

On Jan 13, 2016, at 1:43 PM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:

Hi, Michael. As one of the people who's been a strong believer of "warning flags result in style dialects", I think it's important to establish a use case here. What will people actually do with warning categories? What warnings will we allow turning off? Under what contexts?

For the "variable never mutated" warning, you mentioned that this doesn't make sense in a rapid experimentation environment. I'd say more specifically that it doesn't make sense in code you're actively changing. But Live Issues should be able to know what code you're actively changing, and only suppress the warning there.

Perhaps I'm the outlier here, but I personally think that "warning flags result in style dialects" is not an anathema. There is some code where stylistic enforcements need to be stricter for a variety of reasons. While I think we should aim for a common set of warnings that are enabled to establish good hygiene in Swift code, I do think there will be cases where more warnings/errors are desired beyond what the core language defines.

I agree we don't need to eagerly classify warnings, but I'd also like to understand your criteria for why -W flags are bad thing in general and what you'd prefer to see as a better direction. I certainly don't see it that way. My fear is that if we are overly conservative about not having precise control over warnings is that we may hold back on adding useful warnings to the compiler because they will not be appropriate for everyone.

I also don't see if as a solution for warning control, as you indicated in another message, as I see legitimate cases where more aggressive warnings may be desirable to enable in certain contexts. There is also Chris's comments about other contents, like Playgrounds, where some pedantic warnings that may be on by default provide less value.

···

On Jan 13, 2016, at 1:43 PM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:

Hi, Michael. As one of the people who's been a strong believer of "warning flags result in style dialects", I think it's important to establish a use case here. What will people actually do with warning categories? What warnings will we allow turning off? Under what contexts?

By keeping it in mind, do you mean to allow for more categories to be added in the future, or does this affect the fundamental design?

Not that I have much opinion here but to answer your question, the motivation for suppressing them would be unique, so they would simply go under a new category.

Likewise, the more arcane warnings could go uncategorized until there’s a need to suppress them as a separate group. Although at first glance it looks like several of those fall under “command line user interface”.

Andy

···

On Jan 12, 2016, at 5:15 PM, Michael Ilseman via swift-dev <swift-dev@swift.org> wrote:

On Jan 12, 2016, at 5:06 PM, Michael Gottesman <mgottesman@apple.com <mailto:mgottesman@apple.com>> wrote:

On Jan 12, 2016, at 9:44 AM, Michael Ilseman via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:
Categorize based on broad language-feature/compiler-area. E.g. "Availability" or “CommandLineArguments”
Categorize based on the kind of warning. E.g. "Deprecated" or “Uninitialized"
Categorize based on severity or specificity of warnings. E.g. "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example, there's
a handful of warnings that makes less sense in a REPL or rapid experimentation
environment, such as variable_never_mutated.

Here's a straw-man proposal of some categorization. Of course, one developer's
annoying pedantic warning is another's life-saving code-smell detector. I am not
personally tied to these categorizations at all, I'm just interested in there
being something simple and basic. Below is a list of every warning in Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will "
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"
    required_initializer_override_keyword
        "'override' is implied when overriding a required initializer"
    if_always_true
        "'if' condition is always true"
    while_always_true
        "'while' condition is always true"
    warn_protocol_witness_optionality
        "%select{type|result|parameter|parameters|"
        "result and parameters}0 of %1 %select{has|has|has|have|have|}0"
        " different optionality than expected by protocol %2"
    optional_req_nonobjc_near_match
        "non-@objc %select{initializer %1|method %1|property %1|subscript}0 "
        "cannot satisfy optional requirement of @objc protocol %2"
    override_unnecessary_IUO
        "overriding %0 parameter of type %1 with implicitly unwrapped optional "
        "type %2",
    override_unnecessary_result_IUO
        "overriding %0 optional result type %1 with implicitly unwrapped "
        "optional type %2",
    inject_forced_downcast, sema_tce, none,
        "treating a forced downcast to %0 as optional will never produce 'nil'"
    recursive_accessor_reference, tce_sema, none,
        "attempting to %select{access|modify}1 %0 within its own "
        "%select{getter|setter}1",
    store_in_willset, tce_sema, none,
        "attempting to store to property %0 within its own willSet, which is "
        "about to be overwritten by the new value",
    isa_is_always_true
        "'%0' test is always true",
    conditional_downcast_coercion
        "conditional cast from %0 to %1 always succeeds"
    downcast_to_unrelated, sema_tcc, none,
        "cast from %0 to unrelated type %1 always fails"
    forced_downcast_noop
        "forced cast of %0 to same type has no effect"
    forced_downcast_coercion
        "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?"
    extraneous_default_args_in_call
        "call to %0 has extraneous arguments that could use defaults"
    unreachable_code
        "will never be executed"
    unreachable_code_after_stmt
        "code after '%select{return|break|continue|throw}0' will never "
        "be executed"
    unreachable_case
        "%select{case|default}0 will never be executed"
    switch_on_a_constant
        "switch condition evaluates to a constant"
    integer_conversion_overflow_warn
        "integer overflows when converted from %0 to %1"
    integer_literal_overflow_warn
        "integer literal overflows when stored into %0"
    trailing_closure_excess_newlines
        "trailing closure is separated from call site by multiple newlines"
    lex_nul_character, lexing, none
        "nul character embedded in middle of file"
    unindented_code_after_return
        "expression following 'return' is treated as an argument of "
        "the 'return'"
    lex_editor_placeholder_in_playground
        "editor placeholder in source file"

Attributes:
    attr_availability_unknown_platform
        "unknown platform '%0' for attribute '%1'"
    attr_warn_unused_result_expected_name
        "expected parameter 'message' or 'mutable_variant'"
    attr_warn_unused_result_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    attr_warn_unused_result_unknown_parameter
        "unknown parameter '%0' in 'warn_unused_result' attribute"
    attr_migration_id_expected_name
        "expected parameter 'pattern'"
    attr_migration_id_unknown_parameter
        "unknown parameter '%0' in '_migration_id' attribute"
    attr_migration_id_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    invalid_swift_name_method
        "too %select{few|many}0 parameters in swift_name attribute (expected %1; "
        "got %2)"

Availability:
    availability_query_useless_min_deployment
        "unnecessary check for '%0'; minimum deployment target ensures guard "
        "will always be true"
    availability_query_useless_enclosing_scope
        "unnecessary check for '%0'; enclosing scope ensures guard "
        "will always be true"

And the below I'm either struggling to think about how to categorize them
(perhaps no category at first), or un-familiar with what they're targeting
    warning_from_clang:
        "%0"
    could_not_rewrite_bridging_header, none, none,
        "failed to serialize bridging header; "
        "target may not be debuggable outside of its original project"
    omit_needless_words
        "%0 could be named %1 [-Womit-needless-words]"
    unused_compiler_version_component
        "the second version component is not used for comparison"
    unknown_build_config
        "unknown %0 for build configuration '%1'"
    sema_import_current_module
        "this file is part of module %0; ignoring import"
    sema_import_current_module_with_file
        "file '%0' is part of module %1; ignoring import"
    access_control_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 for "
        "%select{a private|an internal|PUBLIC}2 %3"
    access_control_ext_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 in "
        "%select{a private|an internal|PUBLIC}2 extension"
    emit_reference_dependencies_without_primary_file
        "ignoring -emit-reference-dependencies (requires -primary-file)"
    warning_no_such_sdk
        "no such SDK: '%0'"
    warn_cannot_stat_input
        "unable to determine when '%0' was last modified: %1"
    warning_unnecessary_repl_mode
        "unnecessary option '%0'; this is the default for '%1' "
        "with no input files"
    incremental_requires_output_file_map
        "ignoring -incremental (currently requires an output file map)"
    incremental_requires_build_record_entry
        "ignoring -incremental; output file map has no master dependencies "
        "entry (\"%0\" under \"\")"

I haven’t gotten to how to expose this to the user, and I’ll defer to the community for suggestions in that area.

Just an FYI: We have also talked about performance related warnings at the SIL level (that could potentially be a hard error). We do not have any such thing implemented right now, but keep it in mind.

Michael

_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev

_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev

Ideally I can see wanting to have multiple overlapping categorization schemes. It’s pretty much axiomatic than any classification strategy involves tradeoffs, so allowing more than one is the only approach that makes sense. I may well want to turn off all warnings introduced after Swift 2.2, or enable only warnings for which Fix-It improvements are provided, or any other orthogonal conceptual collection.

Not that every conceivable collection should be supported, but the general notion that there could be overlapping categories seems worth considering.

Kate Stone k8stone@apple.com <mailto:k8stone@apple.com>
 Xcode Low Level Tools

···

On Jan 12, 2016, at 5:15 PM, Michael Ilseman via swift-dev <swift-dev@swift.org> wrote:

By keeping it in mind, do you mean to allow for more categories to be added in the future, or does this affect the fundamental design?

On Jan 12, 2016, at 5:06 PM, Michael Gottesman <mgottesman@apple.com <mailto:mgottesman@apple.com>> wrote:

On Jan 12, 2016, at 9:44 AM, Michael Ilseman via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:
Categorize based on broad language-feature/compiler-area. E.g. "Availability" or “CommandLineArguments”
Categorize based on the kind of warning. E.g. "Deprecated" or “Uninitialized"
Categorize based on severity or specificity of warnings. E.g. "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example, there's
a handful of warnings that makes less sense in a REPL or rapid experimentation
environment, such as variable_never_mutated.

Here's a straw-man proposal of some categorization. Of course, one developer's
annoying pedantic warning is another's life-saving code-smell detector. I am not
personally tied to these categorizations at all, I'm just interested in there
being something simple and basic. Below is a list of every warning in Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will "
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"
    required_initializer_override_keyword
        "'override' is implied when overriding a required initializer"
    if_always_true
        "'if' condition is always true"
    while_always_true
        "'while' condition is always true"
    warn_protocol_witness_optionality
        "%select{type|result|parameter|parameters|"
        "result and parameters}0 of %1 %select{has|has|has|have|have|}0"
        " different optionality than expected by protocol %2"
    optional_req_nonobjc_near_match
        "non-@objc %select{initializer %1|method %1|property %1|subscript}0 "
        "cannot satisfy optional requirement of @objc protocol %2"
    override_unnecessary_IUO
        "overriding %0 parameter of type %1 with implicitly unwrapped optional "
        "type %2",
    override_unnecessary_result_IUO
        "overriding %0 optional result type %1 with implicitly unwrapped "
        "optional type %2",
    inject_forced_downcast, sema_tce, none,
        "treating a forced downcast to %0 as optional will never produce 'nil'"
    recursive_accessor_reference, tce_sema, none,
        "attempting to %select{access|modify}1 %0 within its own "
        "%select{getter|setter}1",
    store_in_willset, tce_sema, none,
        "attempting to store to property %0 within its own willSet, which is "
        "about to be overwritten by the new value",
    isa_is_always_true
        "'%0' test is always true",
    conditional_downcast_coercion
        "conditional cast from %0 to %1 always succeeds"
    downcast_to_unrelated, sema_tcc, none,
        "cast from %0 to unrelated type %1 always fails"
    forced_downcast_noop
        "forced cast of %0 to same type has no effect"
    forced_downcast_coercion
        "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?"
    extraneous_default_args_in_call
        "call to %0 has extraneous arguments that could use defaults"
    unreachable_code
        "will never be executed"
    unreachable_code_after_stmt
        "code after '%select{return|break|continue|throw}0' will never "
        "be executed"
    unreachable_case
        "%select{case|default}0 will never be executed"
    switch_on_a_constant
        "switch condition evaluates to a constant"
    integer_conversion_overflow_warn
        "integer overflows when converted from %0 to %1"
    integer_literal_overflow_warn
        "integer literal overflows when stored into %0"
    trailing_closure_excess_newlines
        "trailing closure is separated from call site by multiple newlines"
    lex_nul_character, lexing, none
        "nul character embedded in middle of file"
    unindented_code_after_return
        "expression following 'return' is treated as an argument of "
        "the 'return'"
    lex_editor_placeholder_in_playground
        "editor placeholder in source file"

Attributes:
    attr_availability_unknown_platform
        "unknown platform '%0' for attribute '%1'"
    attr_warn_unused_result_expected_name
        "expected parameter 'message' or 'mutable_variant'"
    attr_warn_unused_result_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    attr_warn_unused_result_unknown_parameter
        "unknown parameter '%0' in 'warn_unused_result' attribute"
    attr_migration_id_expected_name
        "expected parameter 'pattern'"
    attr_migration_id_unknown_parameter
        "unknown parameter '%0' in '_migration_id' attribute"
    attr_migration_id_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    invalid_swift_name_method
        "too %select{few|many}0 parameters in swift_name attribute (expected %1; "
        "got %2)"

Availability:
    availability_query_useless_min_deployment
        "unnecessary check for '%0'; minimum deployment target ensures guard "
        "will always be true"
    availability_query_useless_enclosing_scope
        "unnecessary check for '%0'; enclosing scope ensures guard "
        "will always be true"

And the below I'm either struggling to think about how to categorize them
(perhaps no category at first), or un-familiar with what they're targeting
    warning_from_clang:
        "%0"
    could_not_rewrite_bridging_header, none, none,
        "failed to serialize bridging header; "
        "target may not be debuggable outside of its original project"
    omit_needless_words
        "%0 could be named %1 [-Womit-needless-words]"
    unused_compiler_version_component
        "the second version component is not used for comparison"
    unknown_build_config
        "unknown %0 for build configuration '%1'"
    sema_import_current_module
        "this file is part of module %0; ignoring import"
    sema_import_current_module_with_file
        "file '%0' is part of module %1; ignoring import"
    access_control_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 for "
        "%select{a private|an internal|PUBLIC}2 %3"
    access_control_ext_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 in "
        "%select{a private|an internal|PUBLIC}2 extension"
    emit_reference_dependencies_without_primary_file
        "ignoring -emit-reference-dependencies (requires -primary-file)"
    warning_no_such_sdk
        "no such SDK: '%0'"
    warn_cannot_stat_input
        "unable to determine when '%0' was last modified: %1"
    warning_unnecessary_repl_mode
        "unnecessary option '%0'; this is the default for '%1' "
        "with no input files"
    incremental_requires_output_file_map
        "ignoring -incremental (currently requires an output file map)"
    incremental_requires_build_record_entry
        "ignoring -incremental; output file map has no master dependencies "
        "entry (\"%0\" under \"\")"

I haven’t gotten to how to expose this to the user, and I’ll defer to the community for suggestions in that area.

Just an FYI: We have also talked about performance related warnings at the SIL level (that could potentially be a hard error). We do not have any such thing implemented right now, but keep it in mind.

Michael

_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev

_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

I'd rather come up with good answers to if and/or easy, idiomatic ways to silence most warnings (like assigning to _) over flags and diagnostic regions (Clang's pragmas).

Jordan

···

On Jan 13, 2016, at 13:51, Michael Ilseman <milseman@apple.com> wrote:

On Jan 13, 2016, at 1:43 PM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

Hi, Michael. As one of the people who's been a strong believer of "warning flags result in style dialects", I think it's important to establish a use case here. What will people actually do with warning categories? What warnings will we allow turning off? Under what contexts?

For the "variable never mutated" warning, you mentioned that this doesn't make sense in a rapid experimentation environment. I'd say more specifically that it doesn't make sense in code you're actively changing. But Live Issues should be able to know what code you're actively changing, and only suppress the warning there.

(We do have some ad hoc categorization today, including "REPL mode" as you mentioned. I'm fine with making that something more general.)

I’ll look more at REPL mode and see how to better generalize that. It’s more in line with what I’m trying to accomplish, and it may not make sense to categorize all the warnings in Swift so much as call out limited sub-sets. If that’s the case, and doing so is more so the exception than the rule, then I’m more amenable to tags and/or Kate’s suggestions.

I guess I'd rather avoid eagerly classifying warnings, and I'll continue to argue against -W* and -Wno-* flags for the time being.

What about global flags, such as “-Werr” or equivalent? Do you have any thoughts about Dmitri’s point on multi-platform libraries and how they sometimes can trigger strict stylistic warnings excessively?

Yes, I understand that -- the fix is very simple, we just need to find
a 'try' in disabled code. My point is though, currently we are not
implementing this (nor fixing other false positives), and we are
producing warnings that developers in
the field can't do anything about, even as a workaround for the broken
compiler. Another point is that especially with dataflow-based
warnings there will be edge cases that will be impractical to fix.

I think it is important to give developers in the field a tool to mark
false positives (either on a category, or a per-warning level), to
work around an imperfect compiler. I totally agree that we should try
to fix the compiler, but engineers working with the today's imperfect
compiler need a tool to be effective with what they can use.

Dmitri

···

On Mon, Jan 18, 2016 at 10:34 PM, Chris Lattner <clattner@apple.com> wrote:

On Jan 12, 2016, at 1:24 PM, Dmitri Gribenko via swift-dev > <swift-dev@swift.org> wrote:

        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do'
block"

It seems like some of these can be too pedantic in cross-platform code bases
because of if's that are not analyzable and might need more granular
suppression mechanisms. For example:

func foo() throws {}
func bar() {}

func baz() {
  do {
if os(OSX)
    try foo()
#else
    bar()
#endif
    // common code.
  } catch { // on non-OS X, warning: 'catch' block is unreachable because no
errors are thrown in 'do' block
    // ...
  }
}

I definitely remember we had some similar issues in the standard library or
tests, but don't remember the specifics.

FWIW, one of the reasons we build an AST for disabled if regions is so we
can be smart about this sort of thing. The fact that we don’t for this
warning is a bug in the warning, not something we should use warning
suppression to fix.

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/

So far I haven't heard any warnings that make sense to disable globally in playgrounds. I can understand this as a stop-gap measure, but not a long-term one, and there's no real reason to expose a flag for it separate than the existing "playground mode".

Doug's point about migration warnings makes sense, though.

Jordan

···

On Jan 18, 2016, at 22:39 , Chris Lattner <clattner@apple.com> wrote:

On Jan 13, 2016, at 1:43 PM, Jordan Rose via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

Hi, Michael. As one of the people who's been a strong believer of "warning flags result in style dialects", I think it's important to establish a use case here. What will people actually do with warning categories? What warnings will we allow turning off? Under what contexts?

For the "variable never mutated" warning, you mentioned that this doesn't make sense in a rapid experimentation environment. I'd say more specifically that it doesn't make sense in code you're actively changing. But Live Issues should be able to know what code you're actively changing, and only suppress the warning there.

Jordan, there is a class of warnings that we want to disable in Playgrounds, simply because they don’t make sense for that use case.

You could argue that the IDE should just ignore certain errors in this case, but that leads to tight coupling and fragility, this is better managed by having there be a -Wno-playgrounds sort of flag, so we can manage it on the compiler side.

Michael and I spoke about this offline. The main things that I wanted to make sure was that it would be extensible and that warnings from SIL would be first class citizens in terms of API, etc. Overall, I was more just trying to give him food for thought.

Michael

···

On Jan 12, 2016, at 9:42 PM, Andrew Trick <atrick@apple.com> wrote:

On Jan 12, 2016, at 5:15 PM, Michael Ilseman via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

By keeping it in mind, do you mean to allow for more categories to be added in the future, or does this affect the fundamental design?

Not that I have much opinion here but to answer your question, the motivation for suppressing them would be unique, so they would simply go under a new category.

Likewise, the more arcane warnings could go uncategorized until there’s a need to suppress them as a separate group. Although at first glance it looks like several of those fall under “command line user interface”.

Andy

On Jan 12, 2016, at 5:06 PM, Michael Gottesman <mgottesman@apple.com <mailto:mgottesman@apple.com>> wrote:

On Jan 12, 2016, at 9:44 AM, Michael Ilseman via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:
Categorize based on broad language-feature/compiler-area. E.g. "Availability" or “CommandLineArguments”
Categorize based on the kind of warning. E.g. "Deprecated" or “Uninitialized"
Categorize based on severity or specificity of warnings. E.g. "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example, there's
a handful of warnings that makes less sense in a REPL or rapid experimentation
environment, such as variable_never_mutated.

Here's a straw-man proposal of some categorization. Of course, one developer's
annoying pedantic warning is another's life-saving code-smell detector. I am not
personally tied to these categorizations at all, I'm just interested in there
being something simple and basic. Below is a list of every warning in Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will "
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"
    required_initializer_override_keyword
        "'override' is implied when overriding a required initializer"
    if_always_true
        "'if' condition is always true"
    while_always_true
        "'while' condition is always true"
    warn_protocol_witness_optionality
        "%select{type|result|parameter|parameters|"
        "result and parameters}0 of %1 %select{has|has|has|have|have|}0"
        " different optionality than expected by protocol %2"
    optional_req_nonobjc_near_match
        "non-@objc %select{initializer %1|method %1|property %1|subscript}0 "
        "cannot satisfy optional requirement of @objc protocol %2"
    override_unnecessary_IUO
        "overriding %0 parameter of type %1 with implicitly unwrapped optional "
        "type %2",
    override_unnecessary_result_IUO
        "overriding %0 optional result type %1 with implicitly unwrapped "
        "optional type %2",
    inject_forced_downcast, sema_tce, none,
        "treating a forced downcast to %0 as optional will never produce 'nil'"
    recursive_accessor_reference, tce_sema, none,
        "attempting to %select{access|modify}1 %0 within its own "
        "%select{getter|setter}1",
    store_in_willset, tce_sema, none,
        "attempting to store to property %0 within its own willSet, which is "
        "about to be overwritten by the new value",
    isa_is_always_true
        "'%0' test is always true",
    conditional_downcast_coercion
        "conditional cast from %0 to %1 always succeeds"
    downcast_to_unrelated, sema_tcc, none,
        "cast from %0 to unrelated type %1 always fails"
    forced_downcast_noop
        "forced cast of %0 to same type has no effect"
    forced_downcast_coercion
        "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?"
    extraneous_default_args_in_call
        "call to %0 has extraneous arguments that could use defaults"
    unreachable_code
        "will never be executed"
    unreachable_code_after_stmt
        "code after '%select{return|break|continue|throw}0' will never "
        "be executed"
    unreachable_case
        "%select{case|default}0 will never be executed"
    switch_on_a_constant
        "switch condition evaluates to a constant"
    integer_conversion_overflow_warn
        "integer overflows when converted from %0 to %1"
    integer_literal_overflow_warn
        "integer literal overflows when stored into %0"
    trailing_closure_excess_newlines
        "trailing closure is separated from call site by multiple newlines"
    lex_nul_character, lexing, none
        "nul character embedded in middle of file"
    unindented_code_after_return
        "expression following 'return' is treated as an argument of "
        "the 'return'"
    lex_editor_placeholder_in_playground
        "editor placeholder in source file"

Attributes:
    attr_availability_unknown_platform
        "unknown platform '%0' for attribute '%1'"
    attr_warn_unused_result_expected_name
        "expected parameter 'message' or 'mutable_variant'"
    attr_warn_unused_result_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    attr_warn_unused_result_unknown_parameter
        "unknown parameter '%0' in 'warn_unused_result' attribute"
    attr_migration_id_expected_name
        "expected parameter 'pattern'"
    attr_migration_id_unknown_parameter
        "unknown parameter '%0' in '_migration_id' attribute"
    attr_migration_id_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    invalid_swift_name_method
        "too %select{few|many}0 parameters in swift_name attribute (expected %1; "
        "got %2)"

Availability:
    availability_query_useless_min_deployment
        "unnecessary check for '%0'; minimum deployment target ensures guard "
        "will always be true"
    availability_query_useless_enclosing_scope
        "unnecessary check for '%0'; enclosing scope ensures guard "
        "will always be true"

And the below I'm either struggling to think about how to categorize them
(perhaps no category at first), or un-familiar with what they're targeting
    warning_from_clang:
        "%0"
    could_not_rewrite_bridging_header, none, none,
        "failed to serialize bridging header; "
        "target may not be debuggable outside of its original project"
    omit_needless_words
        "%0 could be named %1 [-Womit-needless-words]"
    unused_compiler_version_component
        "the second version component is not used for comparison"
    unknown_build_config
        "unknown %0 for build configuration '%1'"
    sema_import_current_module
        "this file is part of module %0; ignoring import"
    sema_import_current_module_with_file
        "file '%0' is part of module %1; ignoring import"
    access_control_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 for "
        "%select{a private|an internal|PUBLIC}2 %3"
    access_control_ext_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 in "
        "%select{a private|an internal|PUBLIC}2 extension"
    emit_reference_dependencies_without_primary_file
        "ignoring -emit-reference-dependencies (requires -primary-file)"
    warning_no_such_sdk
        "no such SDK: '%0'"
    warn_cannot_stat_input
        "unable to determine when '%0' was last modified: %1"
    warning_unnecessary_repl_mode
        "unnecessary option '%0'; this is the default for '%1' "
        "with no input files"
    incremental_requires_output_file_map
        "ignoring -incremental (currently requires an output file map)"
    incremental_requires_build_record_entry
        "ignoring -incremental; output file map has no master dependencies "
        "entry (\"%0\" under \"\")"

I haven’t gotten to how to expose this to the user, and I’ll defer to the community for suggestions in that area.

Just an FYI: We have also talked about performance related warnings at the SIL level (that could potentially be a hard error). We do not have any such thing implemented right now, but keep it in mind.

Michael

_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev

_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev

Ideally I can see wanting to have multiple overlapping categorization schemes. It’s pretty much axiomatic than any classification strategy involves tradeoffs, so allowing more than one is the only approach that makes sense. I may well want to turn off all warnings introduced after Swift 2.2, or enable only warnings for which Fix-It improvements are provided, or any other orthogonal conceptual collection.

Not that every conceivable collection should be supported, but the general notion that there could be overlapping categories seems worth considering.

I had considered a tag-based mechanism rather than strict categories, but it seems to complicate both the user story and compiler maintenance.

With strict categories, the underlying mechanism for deciding how to present a warning can proceed as follows:
Honor local state (e.g. no more diagnostics after fatal), else
Honor specific warning specification, else
Honor categorical specification (e.g. ignore all pedantic language warnings), else
Honor global specification (e.g. all warnings are errors), else
Go with the default, declared handing (i.e. warn!)

This is easy and intuitive to communicate to the user on how to control it. If they bothered to single out a single warning, they probably care that it gets honored even if they gave a contradictory handling to its category or all warnings in general. When you talk about over-lapping categories and/or tags, step #3 become a much more complicated story to expose to the user.

When it comes to compiler maintenance, new warnings will need to undergo scrutiny not just about their overall category, but whether any existing tags apply to them (including tags relating to when it is introduced/modified). Given that we want to allow ourselves the ability to flexibly refine, redefine, or extend warnings, we may find ourselves in a less flexible position if we start to no longer adhere to every tag present. It seems like a recipe for over-engineering, at least at this stage in the project. The worse case is that the user has to specify at the individual level.

I’m not opposed to this, but after talking it over a bit it seemed hard to envision the benefits making the complexity worth it. When I implement the categories, I will try to take this potential future direction into account, and not needlessly paint us into a corner. It is certainly an interesting direction to investigate further along.

···

On Jan 13, 2016, at 10:20 AM, Kate Stone <k8stone@apple.com> wrote:

Kate Stone k8stone@apple.com <mailto:k8stone@apple.com>
 Xcode Low Level Tools

On Jan 12, 2016, at 5:15 PM, Michael Ilseman via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

By keeping it in mind, do you mean to allow for more categories to be added in the future, or does this affect the fundamental design?

On Jan 12, 2016, at 5:06 PM, Michael Gottesman <mgottesman@apple.com <mailto:mgottesman@apple.com>> wrote:

On Jan 12, 2016, at 9:44 AM, Michael Ilseman via swift-dev <swift-dev@swift.org <mailto:swift-dev@swift.org>> wrote:

Hello, I'm interested in enabling finer-grained control over warning/error
reporting ala Clang. I've started to put in some infrastructure to
DiagnosticEngine, and now I'm at the point of determining categorization.

I'd like some input (and maybe even some bikeshedding!) on the community's
thoughts and preferences here. Here's my take on the issue:

When it comes to defining the categorization, I can see a few approaches:
Categorize based on broad language-feature/compiler-area. E.g. "Availability" or “CommandLineArguments”
Categorize based on the kind of warning. E.g. "Deprecated" or “Uninitialized"
Categorize based on severity or specificity of warnings. E.g. "Pedantic" or "UnusedValue" or "NullDereference"

And, of course, I think that preference should be given to how people would
actively like to use the categories to control warnings. For example, there's
a handful of warnings that makes less sense in a REPL or rapid experimentation
environment, such as variable_never_mutated.

Here's a straw-man proposal of some categorization. Of course, one developer's
annoying pedantic warning is another's life-saving code-smell detector. I am not
personally tied to these categorizations at all, I'm just interested in there
being something simple and basic. Below is a list of every warning in Swift with
an attempt to put it under a category.

Deprecated:
    var_not_allowed_in_pattern
        "Use of '%select{var|let}0' binding here is deprecated and will be "
        "removed in a future version of Swift"
    deprecated_c_style_for_stmt
        "C-style for statement is deprecated and will be removed in a future "
        "version of Swift"
    deprecated_convention_attribute
        "'@%0' attribute is deprecated; '@convention(%1)' should be used "
        "instead"
    availability_deprecated
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1"
    availability_deprecated_msg
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: %5"
    availability_deprecated_rename
        "%0 %select{is|%select{is|was}3}1 deprecated"
        "%select{| %select{on|in}3 %2%select{| %4}3}1: renamed to '%5'"
    parameter_curry_syntax_removed
        "curried function declaration syntax will be removed in a future "
        "version of Swift; use a single parameter list"

Unsupported:
    warning_parallel_execution_not_supported
        "parallel execution not supported; falling back to serial execution"
    unsupported_synthesize_init_variadic
        "synthesizing a variadic inherited initializer for subclass %0 is "
        "unsupported"

Stylistic/Pedantic/Cleanliness:
    pbd_never_used_stmtcond
        "value %0 was defined but never used; consider replacing "
        "with boolean test"
    pbd_never_used
        "initialization of %select{variable|immutable value}1 %0 was never used"
        "; consider replacing with assignment to '_' or removing it"
    capture_never_used
        "capture %0 was never used",
    variable_never_used
        "%select{variable|immutable value}1 %0 was never used; "
        "consider replacing with '_' or removing it"
    variable_never_mutated
        "%select{variable|parameter}1 %0 was never mutated; "
        "consider changing to 'let' constant"
    variable_never_read
        "%select{variable|parameter}1 %0 was written to, but never read"
    expression_unused_result
        "result of call to %0 is unused"
    expression_unused_init_result
        "result of initializer is unused", ())
    expression_unused_result_message
        "result of call to %0 is unused: %1"
    expression_unused_result_nonmutating
        "result of call to non-mutating function %0 is unused; "
        "use %1 to mutate in-place"
    expression_unused_optional_try
        "result of 'try?' is unused"
    non_trailing_closure_before_default_args
        "closure parameter prior to parameters with default arguments will "
        "not be treated as a trailing closure"
    parameter_extraneous_double_up
        "extraneous duplicate parameter name; %0 already has an argument "
        "label"
    parameter_extraneous_empty_name
        "extraneous '_' in parameter: %0 has no keyword argument name"
    escaped_parameter_name
        "keyword '%0' does not need to be escaped in argument list"

CodeSmell/StrongStylisticHints:
    guard_always_succeeds
        "'guard' condition is always true, body is unreachable"
    warn_unqualified_access
        "use of %0 treated as a reference to %1 in %2 %3"
    var_pattern_didnt_bind_variables
        "'%0' pattern has no effect; sub-pattern didn't bind any variables"
    type_inferred_to_undesirable_type
        "%select{variable|constant}2 %0 inferred to have type %1, "
        "which may be unexpected"
    no_throw_in_try
        "no calls to throwing functions occur within 'try' expression"
    no_throw_in_do_with_catch
        "'catch' block is unreachable because no errors are thrown in 'do' block"
    required_initializer_override_keyword
        "'override' is implied when overriding a required initializer"
    if_always_true
        "'if' condition is always true"
    while_always_true
        "'while' condition is always true"
    warn_protocol_witness_optionality
        "%select{type|result|parameter|parameters|"
        "result and parameters}0 of %1 %select{has|has|has|have|have|}0"
        " different optionality than expected by protocol %2"
    optional_req_nonobjc_near_match
        "non-@objc %select{initializer %1|method %1|property %1|subscript}0 "
        "cannot satisfy optional requirement of @objc protocol %2"
    override_unnecessary_IUO
        "overriding %0 parameter of type %1 with implicitly unwrapped optional "
        "type %2",
    override_unnecessary_result_IUO
        "overriding %0 optional result type %1 with implicitly unwrapped "
        "optional type %2",
    inject_forced_downcast, sema_tce, none,
        "treating a forced downcast to %0 as optional will never produce 'nil'"
    recursive_accessor_reference, tce_sema, none,
        "attempting to %select{access|modify}1 %0 within its own "
        "%select{getter|setter}1",
    store_in_willset, tce_sema, none,
        "attempting to store to property %0 within its own willSet, which is "
        "about to be overwritten by the new value",
    isa_is_always_true
        "'%0' test is always true",
    conditional_downcast_coercion
        "conditional cast from %0 to %1 always succeeds"
    downcast_to_unrelated, sema_tcc, none,
        "cast from %0 to unrelated type %1 always fails"
    forced_downcast_noop
        "forced cast of %0 to same type has no effect"
    forced_downcast_coercion
        "forced cast from %0 to %1 always succeeds; did you mean to use 'as'?"
    extraneous_default_args_in_call
        "call to %0 has extraneous arguments that could use defaults"
    unreachable_code
        "will never be executed"
    unreachable_code_after_stmt
        "code after '%select{return|break|continue|throw}0' will never "
        "be executed"
    unreachable_case
        "%select{case|default}0 will never be executed"
    switch_on_a_constant
        "switch condition evaluates to a constant"
    integer_conversion_overflow_warn
        "integer overflows when converted from %0 to %1"
    integer_literal_overflow_warn
        "integer literal overflows when stored into %0"
    trailing_closure_excess_newlines
        "trailing closure is separated from call site by multiple newlines"
    lex_nul_character, lexing, none
        "nul character embedded in middle of file"
    unindented_code_after_return
        "expression following 'return' is treated as an argument of "
        "the 'return'"
    lex_editor_placeholder_in_playground
        "editor placeholder in source file"

Attributes:
    attr_availability_unknown_platform
        "unknown platform '%0' for attribute '%1'"
    attr_warn_unused_result_expected_name
        "expected parameter 'message' or 'mutable_variant'"
    attr_warn_unused_result_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    attr_warn_unused_result_unknown_parameter
        "unknown parameter '%0' in 'warn_unused_result' attribute"
    attr_migration_id_expected_name
        "expected parameter 'pattern'"
    attr_migration_id_unknown_parameter
        "unknown parameter '%0' in '_migration_id' attribute"
    attr_migration_id_duplicate_parameter
        "duplicate '%0' parameter; previous value will be ignored"
    invalid_swift_name_method
        "too %select{few|many}0 parameters in swift_name attribute (expected %1; "
        "got %2)"

Availability:
    availability_query_useless_min_deployment
        "unnecessary check for '%0'; minimum deployment target ensures guard "
        "will always be true"
    availability_query_useless_enclosing_scope
        "unnecessary check for '%0'; enclosing scope ensures guard "
        "will always be true"

And the below I'm either struggling to think about how to categorize them
(perhaps no category at first), or un-familiar with what they're targeting
    warning_from_clang:
        "%0"
    could_not_rewrite_bridging_header, none, none,
        "failed to serialize bridging header; "
        "target may not be debuggable outside of its original project"
    omit_needless_words
        "%0 could be named %1 [-Womit-needless-words]"
    unused_compiler_version_component
        "the second version component is not used for comparison"
    unknown_build_config
        "unknown %0 for build configuration '%1'"
    sema_import_current_module
        "this file is part of module %0; ignoring import"
    sema_import_current_module_with_file
        "file '%0' is part of module %1; ignoring import"
    access_control_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 for "
        "%select{a private|an internal|PUBLIC}2 %3"
    access_control_ext_member_more
        "declaring %select{PRIVATE|an internal|a public}0 %1 in "
        "%select{a private|an internal|PUBLIC}2 extension"
    emit_reference_dependencies_without_primary_file
        "ignoring -emit-reference-dependencies (requires -primary-file)"
    warning_no_such_sdk
        "no such SDK: '%0'"
    warn_cannot_stat_input
        "unable to determine when '%0' was last modified: %1"
    warning_unnecessary_repl_mode
        "unnecessary option '%0'; this is the default for '%1' "
        "with no input files"
    incremental_requires_output_file_map
        "ignoring -incremental (currently requires an output file map)"
    incremental_requires_build_record_entry
        "ignoring -incremental; output file map has no master dependencies "
        "entry (\"%0\" under \"\")"

I haven’t gotten to how to expose this to the user, and I’ll defer to the community for suggestions in that area.

Just an FYI: We have also talked about performance related warnings at the SIL level (that could potentially be a hard error). We do not have any such thing implemented right now, but keep it in mind.

Michael

_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev

_______________________________________________
swift-dev mailing list
swift-dev@swift.org <mailto:swift-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-dev

Upon further discussion with Jordan and others offline, I’m not sure it makes sense at this point in Swift to go about doing categorization. Before wrapping up in this area, I’m going to pursue:

Clean up some existing code, where we have unused categories assigned to all diagnostics (and those categories are arguably useless)
Expose frontend options to treat all warnings as errors as well as options to ignore all warnings

Interesting future work could be along the lines of addressing https://bugs.swift.org/browse/SR-529\. After there’s unique identifiers, then we can re-explore finer grained control.

As far as front-end options, any preferences on the command-line switches? I don’t see a need to keep consistency with GCC/Clang here, so perhaps “-suppress-warnings” and “-warnings-as-errors”?

···

On Jan 13, 2016, at 2:28 PM, Jordan Rose <jordan_rose@apple.com> wrote:

On Jan 13, 2016, at 13:51, Michael Ilseman <milseman@apple.com <mailto:milseman@apple.com>> wrote:

On Jan 13, 2016, at 1:43 PM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

Hi, Michael. As one of the people who's been a strong believer of "warning flags result in style dialects", I think it's important to establish a use case here. What will people actually do with warning categories? What warnings will we allow turning off? Under what contexts?

For the "variable never mutated" warning, you mentioned that this doesn't make sense in a rapid experimentation environment. I'd say more specifically that it doesn't make sense in code you're actively changing. But Live Issues should be able to know what code you're actively changing, and only suppress the warning there.

(We do have some ad hoc categorization today, including "REPL mode" as you mentioned. I'm fine with making that something more general.)

I’ll look more at REPL mode and see how to better generalize that. It’s more in line with what I’m trying to accomplish, and it may not make sense to categorize all the warnings in Swift so much as call out limited sub-sets. If that’s the case, and doing so is more so the exception than the rule, then I’m more amenable to tags and/or Kate’s suggestions.

I guess I'd rather avoid eagerly classifying warnings, and I'll continue to argue against -W* and -Wno-* flags for the time being.

What about global flags, such as “-Werr” or equivalent? Do you have any thoughts about Dmitri’s point on multi-platform libraries and how they sometimes can trigger strict stylistic warnings excessively?

I'd rather come up with good answers to if and/or easy, idiomatic ways to silence most warnings (like assigning to _) over flags and diagnostic regions (Clang's pragmas).

Jordan

Our crop of migration-to-Swift-3 warnings is a perfect example of a case where these approaches don’t work well. For example, it is completely reasonable to want to suppress the just-committed ‘typealias’ to ‘associatedtype' warning if you want to keep your code base compiling with Swift 2.[01]. There’s no sensible idiom there, and having to use diagnostic regions would be annoying at best.

  - Doug

···

On Jan 13, 2016, at 2:28 PM, Jordan Rose via swift-dev <swift-dev@swift.org> wrote:

On Jan 13, 2016, at 13:51, Michael Ilseman <milseman@apple.com <mailto:milseman@apple.com>> wrote:

On Jan 13, 2016, at 1:43 PM, Jordan Rose <jordan_rose@apple.com <mailto:jordan_rose@apple.com>> wrote:

Hi, Michael. As one of the people who's been a strong believer of "warning flags result in style dialects", I think it's important to establish a use case here. What will people actually do with warning categories? What warnings will we allow turning off? Under what contexts?

For the "variable never mutated" warning, you mentioned that this doesn't make sense in a rapid experimentation environment. I'd say more specifically that it doesn't make sense in code you're actively changing. But Live Issues should be able to know what code you're actively changing, and only suppress the warning there.

(We do have some ad hoc categorization today, including "REPL mode" as you mentioned. I'm fine with making that something more general.)

I’ll look more at REPL mode and see how to better generalize that. It’s more in line with what I’m trying to accomplish, and it may not make sense to categorize all the warnings in Swift so much as call out limited sub-sets. If that’s the case, and doing so is more so the exception than the rule, then I’m more amenable to tags and/or Kate’s suggestions.

I guess I'd rather avoid eagerly classifying warnings, and I'll continue to argue against -W* and -Wno-* flags for the time being.

What about global flags, such as “-Werr” or equivalent? Do you have any thoughts about Dmitri’s point on multi-platform libraries and how they sometimes can trigger strict stylistic warnings excessively?

I'd rather come up with good answers to if and/or easy, idiomatic ways to silence most warnings (like assigning to _) over flags and diagnostic regions (Clang's pragmas).

FWIW, one of the reasons we build an AST for disabled if regions is so we
can be smart about this sort of thing. The fact that we don’t for this
warning is a bug in the warning, not something we should use warning
suppression to fix.

Yes, I understand that -- the fix is very simple, we just need to find
a 'try' in disabled code. My point is though, currently we are not
implementing this (nor fixing other false positives),

Uh, yes, we are fixing these things. I could find zero reports complaining about this in either radar or Jira, which is why I didn’t know that this was an issue affecting people.

I fixed this in 2f5af05, if you know of other similar issues, please let me know.

and we are producing warnings that developers in
the field can't do anything about, even as a workaround for the broken
compiler.

I would rather that we fix the broken compiler. We do care about QoI in fact.

Another point is that especially with dataflow-based
warnings there will be edge cases that will be impractical to fix.

Please provide some specific details here. The design of our dataflow warnings is specifically intended to make sure they are actionable and do not have false positives that cannot be solved in a reasonable way.

I think it is important to give developers in the field a tool to mark
false positives (either on a category, or a per-warning level), to
work around an imperfect compiler. I totally agree that we should try
to fix the compiler, but engineers working with the today's imperfect
compiler need a tool to be effective with what they can use.

Despite my pushback, I agree with you that local control over warnings is a useful thing to have. However, I don’t find the argument of “the compiler generates bogus warnings sometimes and users should silence them instead of having us fix the compiler” to be the right motivator.

-Chris

···

On Jan 18, 2016, at 10:42 PM, Dmitri Gribenko <gribozavr@gmail.com> wrote: