Skip to content

[5.9🍒] polish up the noncopyable diagnostics #66124

New issue

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

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

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/SIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2805,7 +2805,7 @@ canonical SIL that the value was never copied and thus is a "move only value"
even though the actual underlying wrapped type is copyable. As an example of
this, consider the following Swift::

func doSomething(@_noImplicitCopy _ x: Klass) -> () { // expected-error {{'x' has guaranteed ownership but was consumed}}
func doSomething(@_noImplicitCopy _ x: Klass) -> () { // expected-error {{'x' is borrowed and cannot be consumed}}
x.doSomething()
let x2 = x // expected-note {{consuming use}}
x2.doSomething()
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/DiagnosticsClangImporter.def
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ ERROR(conforms_to_not_protocol,none,
"%0 %1 referenced in protocol conformance '%2' is not a protocol", (DescriptiveDeclKind, ValueDecl *, StringRef))

ERROR(move_only_requires_move_only,none,
"use of move-only C++ type '%0' requires -enable-experimental-move-only",
"use of noncopyable C++ type '%0' requires -enable-experimental-move-only",
(StringRef))

NOTE(unsupported_builtin_type, none, "built-in type '%0' not supported", (StringRef))
Expand Down
139 changes: 56 additions & 83 deletions include/swift/AST/DiagnosticsSIL.def
Original file line number Diff line number Diff line change
Expand Up @@ -747,97 +747,70 @@ NOTE(discard_nontrivial_implicit_storage_note,none,
"type %0 implicitly contains %1 which cannot be trivially destroyed",
(Type, Type))

// move only checker diagnostics
ERROR(sil_moveonlychecker_owned_value_consumed_more_than_once, none,

/// Move Checking / Noncopyable types diagnostics

ERROR(sil_movechecking_owned_value_consumed_more_than_once, none,
"'%0' consumed more than once", (StringRef))
ERROR(sil_moveonlychecker_owned_value_consumed_and_used_at_same_time, none,
ERROR(sil_movechecking_owned_value_consumed_and_used_at_same_time, none,
"'%0' consumed and used at the same time", (StringRef))
ERROR(sil_moveonlychecker_value_used_after_consume, none,
ERROR(sil_movechecking_value_used_after_consume, none,
"'%0' used after consume", (StringRef))
ERROR(sil_moveonlychecker_guaranteed_value_consumed, none,
"'%0' has guaranteed ownership but was consumed", (StringRef))
ERROR(sil_moveonlychecker_guaranteed_value_captured_by_closure, none,
"'%0' has guaranteed ownership but was consumed due to being captured by a closure", (StringRef))
ERROR(sil_moveonlychecker_let_value_consumed_in_closure, none,
"'%0' consumed in closure. This is illegal since if the closure is invoked more than once the binding will be uninitialized on later invocations", (StringRef))
ERROR(sil_moveonlychecker_inout_not_reinitialized_before_end_of_function, none,
"'%0' consumed but not reinitialized before end of function", (StringRef))
ERROR(sil_moveonlychecker_inout_not_reinitialized_before_end_of_closure, none,
"'%0' consumed in closure but not reinitialized before end of closure", (StringRef))
ERROR(sil_moveonlychecker_value_consumed_in_a_loop, none,
"'%0' consumed by a use in a loop", (StringRef))
ERROR(sil_moveonlychecker_exclusivity_violation, none,
"'%0' has consuming use that cannot be eliminated due to a tight exclusivity scope", (StringRef))
ERROR(sil_moveonlychecker_moveonly_field_consumed, none,
"'%0' has a move only field that was consumed before later uses", (StringRef))

ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_classfield_let, none,
"'%0' was consumed but it is illegal to consume a noncopyable class let field. One can only read from it",
(StringRef))
ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_classfield_var, none,
"'%0' was consumed but it is illegal to consume a noncopyable class var field. One can only read from it or assign to it",
(StringRef))
ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_global_var, none,
"'%0' was consumed but it is illegal to consume a noncopyable global var. One can only read from it or assign to it",
(StringRef))
ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_global_let, none,
"'%0' was consumed but it is illegal to consume a noncopyable global let. One can only read from it",
(StringRef))
ERROR(sil_moveonlychecker_notconsumable_but_assignable_was_consumed_escaping_var, none,
"'%0' was consumed but it is illegal to consume a noncopyable mutable capture of an escaping closure. One can only read from it or assign over it",
(StringRef))
ERROR(sil_moveonlychecker_let_capture_consumed, none,
"'%0' was consumed but it is illegal to consume a noncopyable immutable capture of an escaping closure. One can only read from it", (StringRef))
ERROR(sil_moveonlychecker_cannot_destructure_deinit_nominal_type_self, none,
"Cannot partially consume '%0' since it has a user defined deinit",
ERROR(sil_movechecking_guaranteed_value_consumed, none,
"'%0' is borrowed and cannot be consumed", (StringRef))

// FIXME: this diagnostic shouldn't ever be emitted now. rdar://109742587 (closures may still try to consume captures, e.g., borrowed parameters)
ERROR(sil_movechecking_guaranteed_value_captured_by_closure, none,
"'%0' is borrowed and cannot be consumed by closure capture", (StringRef))

ERROR(sil_movechecking_capture_consumed, none,
"noncopyable '%0' cannot be consumed when captured by a closure", (StringRef))
ERROR(sil_movechecking_inout_not_reinitialized_before_end_of_function, none,
"missing reinitialization of inout parameter '%0' after consume", (StringRef))
ERROR(sil_movechecking_value_consumed_in_a_loop, none,
"'%0' consumed in a loop", (StringRef))
ERROR(sil_movechecking_use_after_partial_consume, none,
"cannot use '%0' after partial consume", (StringRef))
ERROR(sil_movechecking_notconsumable_but_assignable_was_consumed, none,
"cannot consume noncopyable stored property '%0' %select{of a class|that is global}1",
(StringRef, bool))
ERROR(sil_movechecking_cannot_destructure_has_deinit, none,
"cannot partially consume '%0' when it has a deinitializer",
(StringRef))
ERROR(sil_moveonlychecker_cannot_destructure_deinit_nominal_type_field, none,
"Cannot partially consume '%0' since it contains field '%1.%2' whose type %3 has a user defined deinit",
(StringRef, StringRef, StringRef, DeclBaseName))

NOTE(sil_moveonlychecker_moveonly_field_consumed_here, none,
"move only field consumed here", ())
NOTE(sil_moveonlychecker_boundary_use, none,
"boundary use here", ())
NOTE(sil_moveonlychecker_consuming_use_here, none,
"consuming use here", ())
NOTE(sil_moveonlychecker_other_consuming_use_here, none,
"other consuming use here", ())
NOTE(sil_moveonlychecker_two_consuming_uses_here, none,
"two consuming uses here", ())
NOTE(sil_moveonlychecker_consuming_and_non_consuming_uses_here, none,
"consuming and non-consuming uses here", ())
NOTE(sil_moveonlychecker_consuming_closure_use_here, none,
"closure capture here", ())
NOTE(sil_moveonlychecker_nonconsuming_use_here, none,
"non-consuming use here", ())
NOTE(sil_movekillscopyablevalue_value_cyclic_consumed_in_loop_here, none,
"consuming in loop use here", ())
NOTE(sil_moveonlychecker_deinit_here, none,
"deinit declared here", ())

ERROR(sil_moveonlychecker_not_understand_consumable_and_assignable, none,
"Usage of @noImplicitCopy that the move checker does not know how to "
"check!", ())
ERROR(sil_moveonlychecker_not_understand_moveonly, none,
"Usage of a move only type that the move checker does not know how to "
"check!", ())
ERROR(sil_moveonlychecker_missed_copy, none,
"copy of noncopyable typed value. This is a compiler bug. Please file a bug with a small example of the bug", ())

// move kills copyable values checker diagnostics
ERROR(sil_movekillscopyablevalue_value_consumed_more_than_once, none,
"'%0' used after being consumed", (StringRef))
NOTE(sil_movekillscopyablevalue_move_here, none,
"consume here", ())
NOTE(sil_movekillscopyablevalue_use_here, none,
"use here", ())
NOTE(sil_movekillscopyablevalue_value_consumed_in_loop, none,
"consume here would occur multiple times in loop", ())
NOTE(sil_movechecking_partial_consume_here, none,
"partially consumed here", ())
NOTE(sil_movechecking_consuming_use_here, none,
"consumed here", ())
NOTE(sil_movechecking_consumed_again_here, none,
"consumed again here", ())
NOTE(sil_movechecking_two_consuming_uses_here, none,
"multiple consumes here", ())
NOTE(sil_movechecking_consuming_and_non_consuming_uses_here, none,
"consumed and used here", ())
NOTE(sil_movechecking_consuming_closure_use_here, none,
"closure capturing '%0' here", (StringRef))
NOTE(sil_movechecking_nonconsuming_use_here, none,
"used here", ())
NOTE(sil_movechecking_consumed_in_loop_here, none,
"consumed in loop here", ())
NOTE(sil_movechecking_deinit_here, none,
"deinitializer declared here", ())

// errors involving noncopyables that are considered to be bugs in the compiler
ERROR(sil_movechecking_not_understand_consumable_and_assignable, none,
"usage of no-implicit-copy value that the compiler can't verify. This is a compiler bug. Please file a bug with a small example of the bug", ())
ERROR(sil_movechecking_not_understand_moveonly, none,
"usage of a noncopyable type that compiler can't verify. This is a compiler bug. Please file a bug with a small example of the bug", ())
ERROR(sil_movechecking_bug_missed_copy, none,
"copy of noncopyable typed value. This is a compiler bug. Please file a bug with a small example of the bug", ())
ERROR(sil_movechecking_bug_exclusivity_violation, none,
"'%0' has an unexpected exclusivity violation. This is a compiler bug. Please file a bug with a small example of the bug", (StringRef))
ERROR(sil_movekillscopyablevalue_move_applied_to_unsupported_move, none,
"'consume' applied to value that the compiler does not support checking",
"'consume' applied to value that the compiler does not support. This is a compiler bug. Please file a bug with a small example of the bug",
())


// Implicit inout-to-UnsafeRawPointer conversions
WARNING(nontrivial_to_rawpointer_conversion,none,
"forming %1 to a variable of type %0; this is likely incorrect because %2 may contain "
Expand Down
102 changes: 50 additions & 52 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -1697,7 +1697,7 @@ ERROR(expose_enum_case_tuple_to_cxx,none,
ERROR(expose_protocol_to_cxx_unsupported,none,
"protocol %0 can not yet be represented in C++", (ValueDecl *))
ERROR(expose_move_only_to_cxx,none,
"move-only %0 %1 can not yet be represented in C++", (DescriptiveDeclKind, ValueDecl *))
"noncopyable %0 %1 can not yet be represented in C++", (DescriptiveDeclKind, ValueDecl *))
ERROR(unexposed_other_decl_in_cxx,none,
"%0 %1 is not yet exposed to C++", (DescriptiveDeclKind, ValueDecl *))
ERROR(unsupported_other_decl_in_cxx,none,
Expand Down Expand Up @@ -6907,30 +6907,6 @@ ERROR(wrap_invalid_attr_added_by_access_note, none,

#undef WHICH_ACCESS_NOTE

// Move Only diagnostics

ERROR(experimental_moveonly_feature_can_only_be_used_when_enabled,
none, "Can not use feature when experimental move only is disabled! Pass"
" the frontend flag -enable-experimental-move-only to swift to enable "
"the usage of this language feature", ())
ERROR(noimplicitcopy_attr_valid_only_on_local_let_params,
none, "'@_noImplicitCopy' attribute can only be applied to local lets and params", ())
ERROR(noimplicitcopy_attr_invalid_in_generic_context,
none, "'@_noImplicitCopy' attribute cannot be applied to entities in generic contexts", ())
ERROR(moveonly_generics, none, "move-only type %0 cannot be used with generics yet", (Type))
ERROR(moveonly_effectful_getter,none,
"%0 of move-only type cannot be 'async' or 'throws'", (DescriptiveDeclKind))
ERROR(noimplicitcopy_attr_not_allowed_on_moveonlytype,none,
"'@_noImplicitCopy' has no effect when applied to a move only type", ())
ERROR(moveonly_enums_do_not_support_indirect,none,
"move-only enum %0 cannot be marked indirect or have indirect cases yet", (Identifier))
ERROR(moveonly_cast,none,
"move-only types cannot be conditionally cast", ())
ERROR(moveonly_failable_init,none,
"move-only types cannot have failable initializers yet", ())
ERROR(moveonly_objc_enum_banned, none,
"@objc enums cannot be marked as move-only", ())

//------------------------------------------------------------------------------
// MARK: Type inference from default expressions
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -6988,21 +6964,6 @@ ERROR(concurrency_task_to_thread_model_global_actor_annotation,none,
"annotating a type with a global actor %0 is not permitted within %1",
(TypeRepr*, StringRef))

ERROR(moveOnly_not_allowed_here,none,
"'moveOnly' only applies to structs or enums", ())
ERROR(consume_expression_not_passed_lvalue,none,
"'consume' can only be applied to lvalues", ())
ERROR(borrow_expression_not_passed_lvalue,none,
"'borrow' can only be applied to lvalues", ())
ERROR(copy_expression_not_passed_lvalue,none,
"'copy' can only be applied to lvalues", ())
ERROR(copy_expression_cannot_be_used_with_noncopyable_types,none,
"'copy' cannot be applied to noncopyable types", ())

ERROR(moveOnly_requires_lexical_lifetimes,none,
"noncopyable types require lexical borrow scopes "
"(add -enable-lexical-borrow-scopes=true)", ())

//------------------------------------------------------------------------------
// MARK: #_hasSymbol
//------------------------------------------------------------------------------
Expand Down Expand Up @@ -7135,31 +7096,68 @@ NOTE(macro_expand_circular_reference_unnamed_through, none,
"circular reference expanding %0 macros", (StringRef))

//------------------------------------------------------------------------------
// MARK: Move Only Errors
// MARK: Noncopyable Types Diagnostics
//------------------------------------------------------------------------------

ERROR(moveonly_copyable_type_that_contains_moveonly_type, none,
"%0 %1 cannot contain a move-only type without also being move-only",
ERROR(noncopyable_within_copyable, none,
"%0 %1 cannot contain a noncopyable type without also being noncopyable",
(DescriptiveDeclKind, DeclName))
NOTE(moveonly_copyable_type_that_contains_moveonly_type_location, none,
"contained move-only %0 '%1.%2'",
NOTE(noncopyable_within_copyable_location, none,
"contained noncopyable %0 '%1.%2'",
(DescriptiveDeclKind, StringRef, StringRef))
ERROR(moveonly_cannot_conform_to_type, none,
"move-only %0 %1 cannot conform to %2",
ERROR(noncopyable_cannot_conform_to_type, none,
"noncopyable %0 %1 cannot conform to %2",
(DescriptiveDeclKind, DeclName, Type))
ERROR(moveonly_parameter_missing_ownership, none,
ERROR(noncopyable_parameter_requires_ownership, none,
"noncopyable parameter must specify its ownership", ())
ERROR(moveonly_parameter_subscript_unsupported, none,
ERROR(noncopyable_parameter_subscript_unsupported, none,
"subscripts cannot have noncopyable parameters yet", ())
NOTE(moveonly_parameter_ownership_suggestion, none,
NOTE(noncopyable_parameter_ownership_suggestion, none,
"add '%0' %1", (StringRef, StringRef))
ERROR(ownership_specifier_copyable,none,
"Copyable types cannot be 'consuming' or 'borrowing' yet", ())
"copyable types cannot be 'consuming' or 'borrowing' yet", ())
ERROR(self_ownership_specifier_copyable,none,
"%0 is not yet valid on %1s in a Copyable type",
"%0 is not yet valid on %1s of a copyable type",
(SelfAccessKind, DescriptiveDeclKind))
ERROR(ownership_specifier_nonescaping_closure,none,
"'%0' cannot be applied to nonescaping closure", (StringRef))
ERROR(noncopyable_generics, none, "noncopyable type %0 cannot be used with generics yet", (Type))
ERROR(noncopyable_effectful_getter,none,
"%0 of noncopyable type cannot be 'async' or 'throws'", (DescriptiveDeclKind))
ERROR(noncopyable_enums_do_not_support_indirect,none,
"noncopyable enum %0 cannot be marked indirect or have indirect cases yet", (Identifier))
ERROR(noncopyable_cast,none,
"noncopyable types cannot be conditionally cast", ())
ERROR(noncopyable_failable_init,none,
"noncopyable types cannot have failable initializers yet", ())
ERROR(noncopyable_objc_enum, none,
"noncopyable enums cannot be marked '@objc'", ())
ERROR(moveOnly_not_allowed_here,none,
"'@_moveOnly' attribute is only valid on structs or enums", ())
ERROR(consume_expression_not_passed_lvalue,none,
"'consume' can only be applied to a local binding ('let', 'var', or parameter)", ())
ERROR(borrow_expression_not_passed_lvalue,none,
"'borrow' can only be applied to a local binding ('let', 'var', or parameter)", ())
ERROR(copy_expression_not_passed_lvalue,none,
"'copy' can only be applied to a local binding ('let', 'var', or parameter)", ())
ERROR(copy_expression_cannot_be_used_with_noncopyable_types,none,
"'copy' cannot be applied to noncopyable types", ())

ERROR(moveOnly_requires_lexical_lifetimes,none,
"noncopyable types require lexical borrow scopes "
"(add -enable-lexical-borrow-scopes=true)", ())

// Experimental noncopyable feature diagnostics:
ERROR(experimental_moveonly_feature_can_only_be_used_when_enabled,
none, "Can not use feature when experimental move only is disabled! Pass"
" the frontend flag -enable-experimental-move-only to swift to enable "
"the usage of this language feature", ())
ERROR(noimplicitcopy_attr_valid_only_on_local_let_params,
none, "'@_noImplicitCopy' attribute can only be applied to local lets and params", ())
ERROR(noimplicitcopy_attr_invalid_in_generic_context,
none, "'@_noImplicitCopy' attribute cannot be applied to entities in generic contexts", ())
ERROR(noimplicitcopy_attr_not_allowed_on_moveonlytype,none,
"'@_noImplicitCopy' has no effect when applied to a noncopyable type", ())

//------------------------------------------------------------------------------
// MARK: Runtime discoverable attributes (@runtimeMetadata)
Expand Down
9 changes: 5 additions & 4 deletions lib/SIL/Utils/FieldSensitivePrunedLiveness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,19 +507,19 @@ void FieldSensitivePrunedLiveBlocks::updateForUse(

auto *bb = user->getParent();
getBlockLiveness(bb, startBitNo, endBitNo, resultingLivenessInfo);
assert(resultingLivenessInfo.size() == (endBitNo - startBitNo));

for (auto pair : llvm::enumerate(resultingLivenessInfo)) {
unsigned index = pair.index();
for (unsigned index : indices(resultingLivenessInfo)) {
unsigned specificBitNo = startBitNo + index;
switch (pair.value()) {
switch (resultingLivenessInfo[index]) {
case LiveOut:
case LiveWithin:
continue;
case Dead: {
// This use block has not yet been marked live. Mark it and its
// predecessor blocks live.
computeScalarUseBlockLiveness(bb, specificBitNo);
resultingLivenessInfo.push_back(getBlockLiveness(bb, specificBitNo));
resultingLivenessInfo[index] = getBlockLiveness(bb, specificBitNo);
continue;
}
}
Expand All @@ -537,6 +537,7 @@ FieldSensitivePrunedLiveBlocks::getStringRef(IsLive isLive) const {
case LiveOut:
return "LiveOut";
}
llvm_unreachable("Covered switch?!");
}

void FieldSensitivePrunedLiveBlocks::print(llvm::raw_ostream &OS) const {
Expand Down
Loading