[swift-dev] Categorization of warnings in Swift

Kate Stone k8stone at apple.com
Wed Jan 13 12:20:20 CST 2016


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 at apple.com <mailto:k8stone at apple.com>
 Xcode Low Level Tools

> On Jan 12, 2016, at 5:15 PM, Michael Ilseman via swift-dev <swift-dev at 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 at apple.com <mailto:mgottesman at apple.com>> wrote:
>> 
>> 
>>> On Jan 12, 2016, at 9:44 AM, Michael Ilseman via swift-dev <swift-dev at swift.org <mailto: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. 
>> 
>> 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 at swift.org <mailto:swift-dev at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-dev <https://lists.swift.org/mailman/listinfo/swift-dev>
>> 
> 
> 
> _______________________________________________
> 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/7d37caaa/attachment.html>


More information about the swift-dev mailing list