[swift-dev] Categorization of warnings in Swift

Jordan Rose jordan_rose at apple.com
Wed Jan 13 15:43:48 CST 2016


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 at 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- at 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 at swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20160113/4f4759f1/attachment.html>


More information about the swift-dev mailing list