diff --git a/Cargo.lock b/Cargo.lock index 23abc6626aaba..9db63aafb4951 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3571,7 +3571,6 @@ dependencies = [ "rustc_abi", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_graphviz", "rustc_hir", "rustc_index", @@ -3771,7 +3770,6 @@ dependencies = [ "rustc_abi", "rustc_ast", "rustc_ast_pretty", - "rustc_borrowck", "rustc_codegen_ssa", "rustc_const_eval", "rustc_data_structures", @@ -3797,7 +3795,6 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "rustc_trait_selection", "serde_json", "shlex", "tracing", @@ -4724,7 +4721,6 @@ dependencies = [ "rustc_ast", "rustc_data_structures", "rustc_errors", - "rustc_fluent_macro", "rustc_hir", "rustc_infer", "rustc_macros", diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 051bebfbec00c..d9bf6b52f31f7 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -966,14 +966,14 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); this.arena.alloc(this.expr(gen_future_span, expr_break)) }); - self.arm(ready_pat, break_x) + self.arm(ready_pat, break_x, span) }; // `::std::task::Poll::Pending => {}` let pending_arm = { let pending_pat = self.pat_lang_item_variant(span, hir::LangItem::PollPending, &[]); let empty_block = self.expr_block_empty(span); - self.arm(pending_pat, empty_block) + self.arm(pending_pat, empty_block, span) }; let inner_match_stmt = { @@ -1027,7 +1027,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }); // mut __awaitee => loop { ... } - let awaitee_arm = self.arm(awaitee_pat, loop_expr); + let awaitee_arm = self.arm(awaitee_pat, loop_expr, span); // `match ::std::future::IntoFuture::into_future() { ... }` let into_future_expr = match await_kind { @@ -1817,7 +1817,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let break_expr = self.with_loop_scope(loop_hir_id, |this| this.expr_break_alloc(for_span)); let pat = self.pat_none(for_span); - self.arm(pat, break_expr) + self.arm(pat, break_expr, for_span) }; // Some() => , @@ -1826,7 +1826,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let body_block = self.with_loop_scope(loop_hir_id, |this| this.lower_block(body, false)); let body_expr = self.arena.alloc(self.expr_block(body_block)); - self.arm(some_pat, body_expr) + self.arm(some_pat, body_expr, for_span) }; // `mut iter` @@ -1885,7 +1885,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let loop_expr = self.arena.alloc(hir::Expr { hir_id: loop_hir_id, kind, span: for_span }); // `mut iter => { ... }` - let iter_arm = self.arm(iter_pat, loop_expr); + let iter_arm = self.arm(iter_pat, loop_expr, for_span); let match_expr = match loop_kind { ForLoopKind::For => { @@ -1930,7 +1930,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::LangItem::IntoAsyncIterIntoIter, arena_vec![self; head], ); - let iter_arm = self.arm(async_iter_pat, inner_match_expr); + let iter_arm = self.arm(async_iter_pat, inner_match_expr, for_span); self.arena.alloc(self.expr_match( for_span, iter, @@ -1997,7 +1997,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let val_expr = self.expr_ident(span, val_ident, val_pat_nid); self.lower_attrs(val_expr.hir_id, &attrs, span, Target::Expression); let continue_pat = self.pat_cf_continue(unstable_span, val_pat); - self.arm(continue_pat, val_expr) + self.arm(continue_pat, val_expr, try_span) }; // `ControlFlow::Break(residual) => @@ -2040,7 +2040,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_attrs(ret_expr.hir_id, &attrs, span, Target::Expression); let break_pat = self.pat_cf_break(try_span, residual_local); - self.arm(break_pat, ret_expr) + self.arm(break_pat, ret_expr, try_span) }; hir::ExprKind::Match( @@ -2368,12 +2368,13 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>, + span: Span, ) -> hir::Arm<'hir> { hir::Arm { hir_id: self.next_id(), pat, guard: None, - span: self.lower_span(expr.span), + span: self.lower_span(span), body: expr, } } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 348882dc59fcd..bde4904e9655d 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -721,3 +721,42 @@ impl CombineAttributeParser for RustcThenThisWouldNeedParser { Some(ident) } } + +pub(crate) struct RustcEffectiveVisibilityParser; + +impl NoArgsAttributeParser for RustcEffectiveVisibilityParser { + const PATH: &'static [Symbol] = &[sym::rustc_effective_visibility]; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Use), + Allow(Target::Static), + Allow(Target::Const), + Allow(Target::Fn), + Allow(Target::Closure), + Allow(Target::Mod), + Allow(Target::ForeignMod), + Allow(Target::TyAlias), + Allow(Target::Enum), + Allow(Target::Variant), + Allow(Target::Struct), + Allow(Target::Field), + Allow(Target::Union), + Allow(Target::Trait), + Allow(Target::TraitAlias), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::AssocConst), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::AssocTy), + Allow(Target::ForeignFn), + Allow(Target::ForeignStatic), + Allow(Target::ForeignTy), + Allow(Target::MacroDef), + Allow(Target::PatField), + Allow(Target::Crate), + ]); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 5abf299ec618c..eb9ae158abb79 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -258,6 +258,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 9e7d55180a233..55a09dbf1d724 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -11,7 +11,6 @@ polonius-engine = "0.13.0" rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_graphviz = { path = "../rustc_graphviz" } rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl deleted file mode 100644 index f59e106c7ac3c..0000000000000 --- a/compiler/rustc_borrowck/messages.ftl +++ /dev/null @@ -1,296 +0,0 @@ -borrowck_assign_due_to_use_closure = - assignment occurs due to use in closure - -borrowck_assign_due_to_use_coroutine = - assign occurs due to use in coroutine - -borrowck_assign_part_due_to_use_closure = - assignment to part occurs due to use in closure - -borrowck_assign_part_due_to_use_coroutine = - assign to part occurs due to use in coroutine - -borrowck_borrow_due_to_use_closure = - borrow occurs due to use in closure - -borrowck_borrow_due_to_use_coroutine = - borrow occurs due to use in coroutine - -borrowck_calling_operator_moves = - calling this operator moves the value - -borrowck_calling_operator_moves_lhs = - calling this operator moves the left-hand side - -borrowck_cannot_move_when_borrowed = - cannot move out of {$place -> - [value] value - *[other] {$place} - } because it is borrowed - .label = borrow of {$borrow_place -> - [value] value - *[other] {$borrow_place} - } occurs here - .move_label = move out of {$value_place -> - [value] value - *[other] {$value_place} - } occurs here - -borrowck_capture_immute = - capture is immutable because of use here - -borrowck_capture_move = - capture is moved because of use here - -borrowck_capture_mut = - capture is mutable because of use here - -borrowck_closure_inferred_mut = inferred to be a `FnMut` closure - -borrowck_closure_invoked_twice = - closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment - -borrowck_closure_moved_twice = - closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment - -borrowck_consider_borrow_type_contents = - help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents - -borrowck_could_not_normalize = - could not normalize `{$value}` - -borrowck_could_not_prove = - could not prove `{$predicate}` - -borrowck_dereference_suggestion = - dereference the return value - -borrowck_func_take_self_moved_place = - `{$func}` takes ownership of the receiver `self`, which moves {$place_name} - -borrowck_generic_does_not_live_long_enough = - `{$kind}` does not live long enough - -borrowck_higher_ranked_lifetime_error = - higher-ranked lifetime error - -borrowck_higher_ranked_subtype_error = - higher-ranked subtype error - -borrowck_implicit_static = - this has an implicit `'static` lifetime requirement - -borrowck_implicit_static_introduced = - calling this method introduces the `impl`'s `'static` requirement - -borrowck_implicit_static_relax = - consider relaxing the implicit `'static` requirement - -borrowck_lifetime_constraints_error = - lifetime may not live long enough - -borrowck_limitations_implies_static = - due to a current limitation of the type system, this implies a `'static` lifetime - -borrowck_move_closure_suggestion = - consider adding 'move' keyword before the nested closure - -borrowck_move_out_place_here = - {$place} is moved here - -borrowck_move_unsized = - cannot move a value of type `{$ty}` - .label = the size of `{$ty}` cannot be statically determined - -borrowck_moved_a_fn_once_in_call = - this value implements `FnOnce`, which causes it to be moved when called - -borrowck_moved_a_fn_once_in_call_call = - `FnOnce` closures can only be called once - -borrowck_moved_a_fn_once_in_call_def = - `{$ty}` is made to be an `FnOnce` closure here - -borrowck_moved_due_to_await = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this {$is_loop_message -> - [true] await, in previous iteration of loop - *[false] await - } - -borrowck_moved_due_to_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this {$is_loop_message -> - [true] call, in previous iteration of loop - *[false] call - } - -borrowck_moved_due_to_implicit_into_iter_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this implicit call to {$is_loop_message -> - [true] `.into_iter()`, in previous iteration of loop - *[false] `.into_iter()` - } - -borrowck_moved_due_to_method_call = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to this method {$is_loop_message -> - [true] call, in previous iteration of loop - *[false] call - } - -borrowck_moved_due_to_usage_in_operator = - {$place_name} {$is_partial -> - [true] partially moved - *[false] moved - } due to usage in {$is_loop_message -> - [true] operator, in previous iteration of loop - *[false] operator - } - -borrowck_opaque_type_lifetime_mismatch = - opaque type used twice with different lifetimes - .label = lifetime `{$arg}` used here - .prev_lifetime_label = lifetime `{$prev}` previously used here - .note = if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - -borrowck_partial_var_move_by_use_in_closure = - variable {$is_partial -> - [true] partially moved - *[false] moved - } due to use in closure - -borrowck_partial_var_move_by_use_in_coroutine = - variable {$is_partial -> - [true] partially moved - *[false] moved - } due to use in coroutine - -borrowck_restrict_to_static = - consider restricting the type parameter to the `'static` lifetime - -borrowck_returned_async_block_escaped = - returns an `async` block that contains a reference to a captured variable, which then escapes the closure body - -borrowck_returned_closure_escaped = - returns a closure that contains a reference to a captured variable, which then escapes the closure body - -borrowck_returned_lifetime_short = - {$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}` - -borrowck_returned_lifetime_wrong = - {$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}` - -borrowck_returned_ref_escaped = - returns a reference to a captured variable which escapes the closure body - -borrowck_simd_intrinsic_arg_const = - {$arg -> - [1] 1st - [2] 2nd - [3] 3rd - *[other] {$arg}th - } argument of `{$intrinsic}` is required to be a `const` item - -borrowck_suggest_create_fresh_reborrow = - consider reborrowing the `Pin` instead of moving it - -borrowck_suggest_iterate_over_slice = - consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop - -borrowck_tail_expr_drop_order = relative drop order changing in Rust 2024 - .label = this temporary value will be dropped at the end of the block - .note = consider using a `let` binding to ensure the value will live long enough - -borrowck_ty_no_impl_copy = - {$is_partial_move -> - [true] partial move - *[false] move - } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait - -borrowck_use_due_to_use_closure = - use occurs due to use in closure - -borrowck_use_due_to_use_coroutine = - use occurs due to use in coroutine - -borrowck_used_impl_require_static = - the used `impl` has a `'static` requirement - -borrowck_value_capture_here = - value captured {$is_within -> - [true] here by coroutine - *[false] here - } - -borrowck_value_moved_here = - value {$is_partial -> - [true] partially moved - *[false] moved - } {$is_move_msg -> - [true] into closure here - *[false] here - }{$is_loop_message -> - [true] , in previous iteration of loop - *[false] {""} - } - -borrowck_var_borrow_by_use_in_closure = - borrow occurs due to use in closure - -borrowck_var_borrow_by_use_in_coroutine = - borrow occurs due to use in coroutine - -borrowck_var_borrow_by_use_place_in_closure = - {$is_single_var -> - *[true] borrow occurs - [false] borrows occur - } due to use of {$place} in closure - -borrowck_var_borrow_by_use_place_in_coroutine = - {$is_single_var -> - *[true] borrow occurs - [false] borrows occur - } due to use of {$place} in coroutine - -borrowck_var_cannot_escape_closure = - captured variable cannot escape `FnMut` closure body - .note = `FnMut` closures only have access to their captured variables while they are executing... - .cannot_escape = ...therefore, they cannot allow references to captured variables to escape - -borrowck_var_does_not_need_mut = - variable does not need to be mutable - .suggestion = remove this `mut` - -borrowck_var_first_borrow_by_use_place_in_closure = - first borrow occurs due to use of {$place} in closure - -borrowck_var_first_borrow_by_use_place_in_coroutine = - first borrow occurs due to use of {$place} in coroutine - -borrowck_var_here_captured = variable captured here - -borrowck_var_here_defined = variable defined here - -borrowck_var_move_by_use_in_closure = - move occurs due to use in closure - -borrowck_var_move_by_use_in_coroutine = - move occurs due to use in coroutine - -borrowck_var_mutable_borrow_by_use_place_in_closure = - mutable borrow occurs due to use of {$place} in closure - -borrowck_var_second_borrow_by_use_place_in_closure = - second borrow occurs due to use of {$place} in closure - -borrowck_var_second_borrow_by_use_place_in_coroutine = - second borrow occurs due to use of {$place} in coroutine diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index d8587ed81d6de..1582833bf15d4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1256,7 +1256,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning_inner(err, ty, expr); } } else if let ty::Adt(def, args) = ty.kind() - && def.did().as_local().is_some() + && let Some(local_did) = def.did().as_local() && def.variants().iter().all(|variant| { variant .fields @@ -1266,12 +1266,50 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { { let ty_span = self.infcx.tcx.def_span(def.did()); let mut span: MultiSpan = ty_span.into(); - span.push_span_label(ty_span, "consider implementing `Clone` for this type"); - span.push_span_label(expr.span, "you could clone this value"); - err.span_note( - span, - format!("if `{ty}` implemented `Clone`, you could clone the value"), + let mut derive_clone = false; + self.infcx.tcx.for_each_relevant_impl( + self.infcx.tcx.lang_items().clone_trait().unwrap(), + ty, + |def_id| { + if self.infcx.tcx.is_automatically_derived(def_id) { + derive_clone = true; + span.push_span_label( + self.infcx.tcx.def_span(def_id), + "derived `Clone` adds implicit bounds on type parameters", + ); + if let Some(generics) = self.infcx.tcx.hir_get_generics(local_did) { + for param in generics.params { + if let hir::GenericParamKind::Type { .. } = param.kind { + span.push_span_label( + param.span, + format!( + "introduces an implicit `{}: Clone` bound", + param.name.ident() + ), + ); + } + } + } + } + }, ); + let msg = if !derive_clone { + span.push_span_label( + ty_span, + format!( + "consider {}implementing `Clone` for this type", + if derive_clone { "manually " } else { "" } + ), + ); + format!("if `{ty}` implemented `Clone`, you could clone the value") + } else { + format!("if all bounds were met, you could clone the value") + }; + span.push_span_label(expr.span, "you could clone this value"); + err.span_note(span, msg); + if derive_clone { + err.help("consider manually implementing `Clone` to avoid undesired bounds"); + } } else if let ty::Param(param) = ty.kind() && let Some(_clone_trait_def) = self.infcx.tcx.lang_items().clone_trait() && let generics = self.infcx.tcx.generics_of(self.mir_def_id()) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index c15e7041c94d3..04bacd049bc97 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -4,7 +4,9 @@ use std::collections::BTreeMap; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::{Applicability, Diag, EmissionGuarantee, MultiSpan, listify}; +use rustc_errors::{ + Applicability, Diag, DiagMessage, EmissionGuarantee, MultiSpan, inline_fluent, listify, +}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{ self as hir, CoroutineKind, GenericBound, LangItem, WhereBoundPredicate, WherePredicateKind, @@ -35,7 +37,6 @@ use tracing::debug; use super::MirBorrowckCtxt; use super::borrow_set::BorrowData; use crate::constraints::OutlivesConstraint; -use crate::fluent_generated as fluent; use crate::nll::ConstraintDescription; use crate::session_diagnostics::{ CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause, @@ -700,7 +701,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id) .is_some() { - diag.span_note(pred.span, fluent::borrowck_limitations_implies_static); + diag.span_note(pred.span, LIMITATION_NOTE); return; } for bound in bounds.iter() { @@ -711,7 +712,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { .rfind(|bgp| tcx.local_def_id_to_hir_id(bgp.def_id) == gat_hir_id) .is_some() { - diag.span_note(bound.span, fluent::borrowck_limitations_implies_static); + diag.span_note(bound.span, LIMITATION_NOTE); return; } } @@ -1312,7 +1313,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let mut span: MultiSpan = spans.clone().into(); err.arg("ty", param_ty.to_string()); let msg = err.dcx.eagerly_translate_to_string( - fluent::borrowck_moved_a_fn_once_in_call_def, + inline_fluent!("`{$ty}` is made to be an `FnOnce` closure here"), err.args.iter(), ); err.remove_arg("ty"); @@ -1321,9 +1322,12 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } span.push_span_label( fn_call_span, - fluent::borrowck_moved_a_fn_once_in_call, + inline_fluent!("this value implements `FnOnce`, which causes it to be moved when called"), + ); + err.span_note( + span, + inline_fluent!("`FnOnce` closures can only be called once"), ); - err.span_note(span, fluent::borrowck_moved_a_fn_once_in_call_call); } else { err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span }); } @@ -1568,3 +1572,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.local_name(index).is_none_or(|name| name.as_str().starts_with('_')) } } + +const LIMITATION_NOTE: DiagMessage = inline_fluent!( + "due to a current limitation of the type system, this implies a `'static` lifetime" +); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 17f1988a17c40..ae389d1a6e10c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,7 +1,7 @@ //! Error reporting machinery for lifetime errors. use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, inline_fluent}; use rustc_hir as hir; use rustc_hir::GenericBound::Trait; use rustc_hir::QPath::Resolved; @@ -27,7 +27,7 @@ use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{Obligation, ObligationCtxt}; use tracing::{debug, instrument, trace}; -use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource}; +use super::{LIMITATION_NOTE, OutlivesSuggestionBuilder, RegionName, RegionNameSource}; use crate::nll::ConstraintDescription; use crate::region_infer::values::RegionElement; use crate::region_infer::{BlameConstraint, TypeTest}; @@ -36,7 +36,7 @@ use crate::session_diagnostics::{ LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote, }; use crate::universal_regions::DefiningTy; -use crate::{MirBorrowckCtxt, borrowck_errors, fluent_generated as fluent}; +use crate::{MirBorrowckCtxt, borrowck_errors}; impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { @@ -265,7 +265,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let Trait(PolyTraitRef { trait_ref, span: trait_span, .. }) = bound else { return; }; - diag.span_note(*trait_span, fluent::borrowck_limitations_implies_static); + diag.span_note(*trait_span, LIMITATION_NOTE); let Some(generics_fn) = tcx.hir_get_generics(self.body.source.def_id().expect_local()) else { return; @@ -298,7 +298,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if suggestions.len() > 0 { suggestions.dedup(); diag.multipart_suggestion_verbose( - fluent::borrowck_restrict_to_static, + inline_fluent!("consider restricting the type parameter to the `'static` lifetime"), suggestions, Applicability::MaybeIncorrect, ); @@ -966,12 +966,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { debug!("trait spans found: {:?}", traits); for span in &traits { let mut multi_span: MultiSpan = vec![*span].into(); - multi_span.push_span_label(*span, fluent::borrowck_implicit_static); - multi_span.push_span_label(ident.span, fluent::borrowck_implicit_static_introduced); + multi_span.push_span_label( + *span, + inline_fluent!("this has an implicit `'static` lifetime requirement"), + ); + multi_span.push_span_label( + ident.span, + inline_fluent!( + "calling this method introduces the `impl`'s `'static` requirement" + ), + ); err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span }); err.span_suggestion_verbose( span.shrink_to_hi(), - fluent::borrowck_implicit_static_relax, + inline_fluent!("consider relaxing the implicit `'static` requirement"), " + '_", Applicability::MaybeIncorrect, ); @@ -1134,7 +1142,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if ocx.evaluate_obligations_error_on_ambiguity().is_empty() && count > 0 { diag.span_suggestion_verbose( tcx.hir_body(*body).value.peel_blocks().span.shrink_to_lo(), - fluent::borrowck_dereference_suggestion, + inline_fluent!("dereference the return value"), "*".repeat(count), Applicability::MachineApplicable, ); @@ -1178,7 +1186,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(closure_span) = closure_span { diag.span_suggestion_verbose( closure_span, - fluent::borrowck_move_closure_suggestion, + inline_fluent!("consider adding 'move' keyword before the nested closure"), "move ", Applicability::MaybeIncorrect, ); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 7c5cbc58e25c5..9186d82974d77 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -99,8 +99,6 @@ mod used_muts; /// A public API provided for the Rust compiler consumers. pub mod consumers; -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } - /// Associate some local constants with the `'tcx` lifetime struct TyCtxtConsts<'tcx>(PhantomData<&'tcx ()>); diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 5143b2fa20598..7bde534dafd20 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -7,16 +7,16 @@ use rustc_span::Span; use crate::diagnostics::RegionName; #[derive(Diagnostic)] -#[diag(borrowck_move_unsized, code = E0161)] +#[diag("cannot move a value of type `{$ty}`", code = E0161)] pub(crate) struct MoveUnsized<'tcx> { pub ty: Ty<'tcx>, #[primary_span] - #[label] + #[label("the size of `{$ty}` cannot be statically determined")] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_higher_ranked_lifetime_error)] +#[diag("higher-ranked lifetime error")] pub(crate) struct HigherRankedLifetimeError { #[subdiagnostic] pub cause: Option, @@ -26,21 +26,21 @@ pub(crate) struct HigherRankedLifetimeError { #[derive(Subdiagnostic)] pub(crate) enum HigherRankedErrorCause { - #[note(borrowck_could_not_prove)] + #[note("could not prove `{$predicate}`")] CouldNotProve { predicate: String }, - #[note(borrowck_could_not_normalize)] + #[note("could not normalize `{$value}`")] CouldNotNormalize { value: String }, } #[derive(Diagnostic)] -#[diag(borrowck_higher_ranked_subtype_error)] +#[diag("higher-ranked subtype error")] pub(crate) struct HigherRankedSubtypeError { #[primary_span] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_generic_does_not_live_long_enough)] +#[diag("`{$kind}` does not live long enough")] pub(crate) struct GenericDoesNotLiveLongEnough { pub kind: String, #[primary_span] @@ -48,15 +48,20 @@ pub(crate) struct GenericDoesNotLiveLongEnough { } #[derive(LintDiagnostic)] -#[diag(borrowck_var_does_not_need_mut)] +#[diag("variable does not need to be mutable")] pub(crate) struct VarNeedNotMut { - #[suggestion(style = "short", applicability = "machine-applicable", code = "")] + #[suggestion( + "remove this `mut`", + style = "short", + applicability = "machine-applicable", + code = "" + )] pub span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_var_cannot_escape_closure)] -#[note] -#[note(borrowck_cannot_escape)] +#[diag("captured variable cannot escape `FnMut` closure body")] +#[note("`FnMut` closures only have access to their captured variables while they are executing...")] +#[note("...therefore, they cannot allow references to captured variables to escape")] pub(crate) struct FnMutError { #[primary_span] pub span: Span, @@ -66,17 +71,17 @@ pub(crate) struct FnMutError { #[derive(Subdiagnostic)] pub(crate) enum VarHereDenote { - #[label(borrowck_var_here_captured)] + #[label("variable captured here")] Captured { #[primary_span] span: Span, }, - #[label(borrowck_var_here_defined)] + #[label("variable defined here")] Defined { #[primary_span] span: Span, }, - #[label(borrowck_closure_inferred_mut)] + #[label("inferred to be a `FnMut` closure")] FnMutInferred { #[primary_span] span: Span, @@ -85,17 +90,21 @@ pub(crate) enum VarHereDenote { #[derive(Subdiagnostic)] pub(crate) enum FnMutReturnTypeErr { - #[label(borrowck_returned_closure_escaped)] + #[label( + "returns a closure that contains a reference to a captured variable, which then escapes the closure body" + )] ReturnClosure { #[primary_span] span: Span, }, - #[label(borrowck_returned_async_block_escaped)] + #[label( + "returns an `async` block that contains a reference to a captured variable, which then escapes the closure body" + )] ReturnAsyncBlock { #[primary_span] span: Span, }, - #[label(borrowck_returned_ref_escaped)] + #[label("returns a reference to a captured variable which escapes the closure body")] ReturnRef { #[primary_span] span: Span, @@ -103,7 +112,7 @@ pub(crate) enum FnMutReturnTypeErr { } #[derive(Diagnostic)] -#[diag(borrowck_lifetime_constraints_error)] +#[diag("lifetime may not live long enough")] pub(crate) struct LifetimeOutliveErr { #[primary_span] pub span: Span, @@ -111,7 +120,9 @@ pub(crate) struct LifetimeOutliveErr { #[derive(Subdiagnostic)] pub(crate) enum LifetimeReturnCategoryErr<'a> { - #[label(borrowck_returned_lifetime_wrong)] + #[label( + "{$mir_def_name} was supposed to return data with lifetime `{$outlived_fr_name}` but it is returning data with lifetime `{$fr_name}`" + )] WrongReturn { #[primary_span] span: Span, @@ -119,7 +130,9 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> { outlived_fr_name: RegionName, fr_name: &'a RegionName, }, - #[label(borrowck_returned_lifetime_short)] + #[label( + "{$category_desc}requires that `{$free_region_name}` must outlive `{$outlived_fr_name}`" + )] ShortReturn { #[primary_span] span: Span, @@ -131,7 +144,7 @@ pub(crate) enum LifetimeReturnCategoryErr<'a> { #[derive(Subdiagnostic)] pub(crate) enum RequireStaticErr { - #[note(borrowck_used_impl_require_static)] + #[note("the used `impl` has a `'static` requirement")] UsedImpl { #[primary_span] multi_span: MultiSpan, @@ -140,42 +153,42 @@ pub(crate) enum RequireStaticErr { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarPathUseCause { - #[label(borrowck_borrow_due_to_use_coroutine)] + #[label("borrow occurs due to use in coroutine")] BorrowInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_use_due_to_use_coroutine)] + #[label("use occurs due to use in coroutine")] UseInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_due_to_use_coroutine)] + #[label("assign occurs due to use in coroutine")] AssignInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_part_due_to_use_coroutine)] + #[label("assign to part occurs due to use in coroutine")] AssignPartInCoroutine { #[primary_span] path_span: Span, }, - #[label(borrowck_borrow_due_to_use_closure)] + #[label("borrow occurs due to use in closure")] BorrowInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_use_due_to_use_closure)] + #[label("use occurs due to use in closure")] UseInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_due_to_use_closure)] + #[label("assignment occurs due to use in closure")] AssignInClosure { #[primary_span] path_span: Span, }, - #[label(borrowck_assign_part_due_to_use_closure)] + #[label("assignment to part occurs due to use in closure")] AssignPartInClosure { #[primary_span] path_span: Span, @@ -184,17 +197,17 @@ pub(crate) enum CaptureVarPathUseCause { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarKind { - #[label(borrowck_capture_immute)] + #[label("capture is immutable because of use here")] Immut { #[primary_span] kind_span: Span, }, - #[label(borrowck_capture_mut)] + #[label("capture is mutable because of use here")] Mut { #[primary_span] kind_span: Span, }, - #[label(borrowck_capture_move)] + #[label("capture is moved because of use here")] Move { #[primary_span] kind_span: Span, @@ -203,77 +216,97 @@ pub(crate) enum CaptureVarKind { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarCause { - #[label(borrowck_var_borrow_by_use_place_in_coroutine)] + #[label( + "{$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in coroutine" + )] BorrowUsePlaceCoroutine { is_single_var: bool, place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_place_in_closure)] + #[label( + "{$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in closure" + )] BorrowUsePlaceClosure { is_single_var: bool, place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_in_coroutine)] + #[label("borrow occurs due to use in coroutine")] BorrowUseInCoroutine { #[primary_span] var_span: Span, }, - #[label(borrowck_var_borrow_by_use_in_closure)] + #[label("borrow occurs due to use in closure")] BorrowUseInClosure { #[primary_span] var_span: Span, }, - #[label(borrowck_var_move_by_use_in_coroutine)] + #[label("move occurs due to use in coroutine")] MoveUseInCoroutine { #[primary_span] var_span: Span, }, - #[label(borrowck_var_move_by_use_in_closure)] + #[label("move occurs due to use in closure")] MoveUseInClosure { #[primary_span] var_span: Span, }, - #[label(borrowck_var_first_borrow_by_use_place_in_coroutine)] + #[label("first borrow occurs due to use of {$place} in coroutine")] FirstBorrowUsePlaceCoroutine { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_first_borrow_by_use_place_in_closure)] + #[label("first borrow occurs due to use of {$place} in closure")] FirstBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_second_borrow_by_use_place_in_coroutine)] + #[label("second borrow occurs due to use of {$place} in coroutine")] SecondBorrowUsePlaceCoroutine { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_second_borrow_by_use_place_in_closure)] + #[label("second borrow occurs due to use of {$place} in closure")] SecondBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_var_mutable_borrow_by_use_place_in_closure)] + #[label("mutable borrow occurs due to use of {$place} in closure")] MutableBorrowUsePlaceClosure { place: String, #[primary_span] var_span: Span, }, - #[label(borrowck_partial_var_move_by_use_in_coroutine)] + #[label( + "variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in coroutine" + )] PartialMoveUseInCoroutine { #[primary_span] var_span: Span, is_partial: bool, }, - #[label(borrowck_partial_var_move_by_use_in_closure)] + #[label( + "variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in closure" + )] PartialMoveUseInClosure { #[primary_span] var_span: Span, @@ -282,34 +315,57 @@ pub(crate) enum CaptureVarCause { } #[derive(Diagnostic)] -#[diag(borrowck_cannot_move_when_borrowed, code = E0505)] +#[diag("cannot move out of {$place -> + [value] value + *[other] {$place} +} because it is borrowed", code = E0505)] pub(crate) struct MoveBorrow<'a> { pub place: &'a str, pub borrow_place: &'a str, pub value_place: &'a str, #[primary_span] - #[label(borrowck_move_label)] + #[label( + "move out of {$value_place -> + [value] value + *[other] {$value_place} + } occurs here" + )] pub span: Span, - #[label] + #[label( + "borrow of {$borrow_place -> + [value] value + *[other] {$borrow_place} + } occurs here" + )] pub borrow_span: Span, } #[derive(Diagnostic)] -#[diag(borrowck_opaque_type_lifetime_mismatch)] +#[diag("opaque type used twice with different lifetimes")] pub(crate) struct LifetimeMismatchOpaqueParam<'tcx> { pub arg: GenericArg<'tcx>, pub prev: GenericArg<'tcx>, #[primary_span] - #[label] - #[note] + #[label("lifetime `{$arg}` used here")] + #[note( + "if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types" + )] pub span: Span, - #[label(borrowck_prev_lifetime_label)] + #[label("lifetime `{$prev}` previously used here")] pub prev_span: Span, } #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonLabel<'a> { - #[label(borrowck_moved_due_to_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this {$is_loop_message -> + [true] call, in previous iteration of loop + *[false] call + }" + )] Call { #[primary_span] fn_call_span: Span, @@ -317,7 +373,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_usage_in_operator)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to usage in {$is_loop_message -> + [true] operator, in previous iteration of loop + *[false] operator + }" + )] OperatorUse { #[primary_span] fn_call_span: Span, @@ -325,7 +389,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_implicit_into_iter_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this implicit call to {$is_loop_message -> + [true] `.into_iter()`, in previous iteration of loop + *[false] `.into_iter()` + }" + )] ImplicitCall { #[primary_span] fn_call_span: Span, @@ -333,7 +405,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_method_call)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this method {$is_loop_message -> + [true] call, in previous iteration of loop + *[false] call + }" + )] MethodCall { #[primary_span] fn_call_span: Span, @@ -341,7 +421,15 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_moved_due_to_await)] + #[label( + "{$place_name} {$is_partial -> + [true] partially moved + *[false] moved + } due to this {$is_loop_message -> + [true] await, in previous iteration of loop + *[false] await + }" + )] Await { #[primary_span] fn_call_span: Span, @@ -349,7 +437,18 @@ pub(crate) enum CaptureReasonLabel<'a> { is_partial: bool, is_loop_message: bool, }, - #[label(borrowck_value_moved_here)] + #[label( + "value {$is_partial -> + [true] partially moved + *[false] moved + } {$is_move_msg -> + [true] into closure here + *[false] here + }{$is_loop_message -> + [true] , in previous iteration of loop + *[false] {\"\"} + }" + )] MovedHere { #[primary_span] move_span: Span, @@ -357,7 +456,7 @@ pub(crate) enum CaptureReasonLabel<'a> { is_move_msg: bool, is_loop_message: bool, }, - #[label(borrowck_consider_borrow_type_contents)] + #[label("help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents")] BorrowContent { #[primary_span] var_span: Span, @@ -366,22 +465,22 @@ pub(crate) enum CaptureReasonLabel<'a> { #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonNote { - #[note(borrowck_moved_a_fn_once_in_call)] + #[note("this value implements `FnOnce`, which causes it to be moved when called")] FnOnceMoveInCall { #[primary_span] var_span: Span, }, - #[note(borrowck_calling_operator_moves)] + #[note("calling this operator moves the value")] UnOpMoveByOperator { #[primary_span] span: Span, }, - #[note(borrowck_calling_operator_moves_lhs)] + #[note("calling this operator moves the left-hand side")] LhsMoveByOperator { #[primary_span] span: Span, }, - #[note(borrowck_func_take_self_moved_place)] + #[note("`{$func}` takes ownership of the receiver `self`, which moves {$place_name}")] FuncTakeSelf { func: String, place_name: String, @@ -393,7 +492,7 @@ pub(crate) enum CaptureReasonNote { #[derive(Subdiagnostic)] pub(crate) enum CaptureReasonSuggest<'tcx> { #[suggestion( - borrowck_suggest_iterate_over_slice, + "consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop", applicability = "maybe-incorrect", code = "&", style = "verbose" @@ -404,7 +503,7 @@ pub(crate) enum CaptureReasonSuggest<'tcx> { span: Span, }, #[suggestion( - borrowck_suggest_create_fresh_reborrow, + "consider reborrowing the `Pin` instead of moving it", applicability = "maybe-incorrect", code = ".as_mut()", style = "verbose" @@ -417,13 +516,18 @@ pub(crate) enum CaptureReasonSuggest<'tcx> { #[derive(Subdiagnostic)] pub(crate) enum CaptureArgLabel { - #[label(borrowck_value_capture_here)] + #[label( + "value captured {$is_within -> + [true] here by coroutine + *[false] here + }" + )] Capture { is_within: bool, #[primary_span] args_span: Span, }, - #[label(borrowck_move_out_place_here)] + #[label("{$place} is moved here")] MoveOutPlace { place: String, #[primary_span] @@ -433,13 +537,17 @@ pub(crate) enum CaptureArgLabel { #[derive(Subdiagnostic)] pub(crate) enum OnClosureNote<'a> { - #[note(borrowck_closure_invoked_twice)] + #[note( + "closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment" + )] InvokedTwice { place_name: &'a str, #[primary_span] span: Span, }, - #[note(borrowck_closure_moved_twice)] + #[note( + "closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment" + )] MovedTwice { place_name: &'a str, #[primary_span] @@ -449,7 +557,12 @@ pub(crate) enum OnClosureNote<'a> { #[derive(Subdiagnostic)] pub(crate) enum TypeNoCopy<'a, 'tcx> { - #[label(borrowck_ty_no_impl_copy)] + #[label( + "{$is_partial_move -> + [true] partial move + *[false] move + } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait" + )] Label { is_partial_move: bool, ty: Ty<'tcx>, @@ -457,12 +570,24 @@ pub(crate) enum TypeNoCopy<'a, 'tcx> { #[primary_span] span: Span, }, - #[note(borrowck_ty_no_impl_copy)] + #[note( + "{$is_partial_move -> + [true] partial move + *[false] move + } occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait" + )] Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, } #[derive(Diagnostic)] -#[diag(borrowck_simd_intrinsic_arg_const)] +#[diag( + "{$arg -> + [1] 1st + [2] 2nd + [3] 3rd + *[other] {$arg}th + } argument of `{$intrinsic}` is required to be a `const` item" +)] pub(crate) struct SimdIntrinsicArgConst { #[primary_span] pub span: Span, @@ -471,8 +596,8 @@ pub(crate) struct SimdIntrinsicArgConst { } #[derive(LintDiagnostic)] -#[diag(borrowck_tail_expr_drop_order)] +#[diag("relative drop order changing in Rust 2024")] pub(crate) struct TailExprDropOrder { - #[label] + #[label("this temporary value will be dropped at the end of the block")] pub borrowed: Span, } diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index c2260a4590975..bc86cdbc9f7ef 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -638,27 +638,27 @@ impl<'a> TraitDef<'a> { GenericParamKind::Type { .. } => { // Extra restrictions on the generics parameters to the // type being derived upon. + let span = param.ident.span.with_ctxt(ctxt); let bounds: Vec<_> = self .additional_bounds .iter() .map(|p| { - cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), - self.is_const, - ) + cx.trait_bound(p.to_path(cx, span, type_ident, generics), self.is_const) }) .chain( // Add a bound for the current trait. - self.skip_path_as_bound - .not() - .then(|| cx.trait_bound(trait_path.clone(), self.is_const)), + self.skip_path_as_bound.not().then(|| { + let mut trait_path = trait_path.clone(); + trait_path.span = span; + cx.trait_bound(trait_path, self.is_const) + }), ) .chain({ // Add a `Copy` bound if required. if is_packed && self.needs_copy_as_bound_if_packed { let p = deriving::path_std!(marker::Copy); Some(cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), + p.to_path(cx, span, type_ident, generics), self.is_const, )) } else { @@ -671,7 +671,7 @@ impl<'a> TraitDef<'a> { ) .collect(); - cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None) + cx.typaram(span, param.ident, bounds, None) } GenericParamKind::Const { ty, span, .. } => { let const_nodefault_kind = GenericParamKind::Const { @@ -791,7 +791,8 @@ impl<'a> TraitDef<'a> { .collect(); // Create the type of `self`. - let path = cx.path_all(self.span, false, vec![type_ident], self_params); + let path = + cx.path_all(type_ident.span.with_ctxt(ctxt), false, vec![type_ident], self_params); let self_type = cx.ty_path(path); let rustc_const_unstable = cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span)); diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 7f02518d6c0de..fd25fba2daac7 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -399,7 +399,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { for piece in template { match *piece { InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s), - InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => { + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { match operands[operand_idx] { GlobalAsmOperandRef::Const { ref string } => { // Const operands get injected directly into the @@ -414,7 +414,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::LLVMRustGetMangledName(llval, s); }) .expect("symbol is not valid UTF-8"); - template_str.push_str(&symbol); + template_str.push_str(&escape_symbol_name(self, symbol, span)); } GlobalAsmOperandRef::SymStatic { def_id } => { let llval = self @@ -428,7 +428,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::LLVMRustGetMangledName(llval, s); }) .expect("symbol is not valid UTF-8"); - template_str.push_str(&symbol); + template_str.push_str(&escape_symbol_name(self, symbol, span)); } } } @@ -1390,3 +1390,42 @@ fn llvm_fixup_output_type<'ll, 'tcx>( _ => layout.llvm_type(cx), } } + +fn escape_symbol_name<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, symbol: String, span: Span) -> String { + use rustc_target::spec::{Arch, BinaryFormat}; + if !symbol.is_empty() + && symbol.chars().all(|c| matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.')) + { + return symbol; + } + if cx.tcx.sess.target.binary_format == BinaryFormat::Xcoff { + cx.tcx.sess.dcx().span_fatal( + span, + format!( + "symbol escaping is not supported for the binary format {}", + cx.tcx.sess.target.binary_format + ), + ); + } + if cx.tcx.sess.target.arch == Arch::Nvptx64 { + cx.tcx.sess.dcx().span_fatal( + span, + format!( + "symbol escaping is not supported for the architecture {}", + cx.tcx.sess.target.arch + ), + ); + } + let mut escaped_symbol = String::new(); + escaped_symbol.push('\"'); + for c in symbol.chars() { + match c { + '\n' => escaped_symbol.push_str("\\\n"), + '"' => escaped_symbol.push_str("\\\""), + '\\' => escaped_symbol.push_str("\\\\"), + c => escaped_symbol.push(c), + } + } + escaped_symbol.push('\"'); + escaped_symbol +} diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml index 39e512be6820f..d28a190ea9c18 100644 --- a/compiler/rustc_driver_impl/Cargo.toml +++ b/compiler/rustc_driver_impl/Cargo.toml @@ -10,7 +10,6 @@ jiff = { version = "0.2.5", default-features = false, features = ["std"] } rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } -rustc_borrowck = { path = "../rustc_borrowck" } rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_data_structures = { path = "../rustc_data_structures" } @@ -36,7 +35,6 @@ rustc_resolve = { path = "../rustc_resolve" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } -rustc_trait_selection = { path = "../rustc_trait_selection" } serde_json = "1.0.59" shlex = "1.0" tracing = { version = "0.1.35" } diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 2e97b4fed245d..8fc793acc5564 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -114,14 +114,12 @@ pub fn default_translator() -> Translator { pub static DEFAULT_LOCALE_RESOURCES: &[&str] = &[ // tidy-alphabetical-start - rustc_borrowck::DEFAULT_LOCALE_RESOURCE, rustc_const_eval::DEFAULT_LOCALE_RESOURCE, rustc_hir_analysis::DEFAULT_LOCALE_RESOURCE, rustc_lint::DEFAULT_LOCALE_RESOURCE, rustc_mir_build::DEFAULT_LOCALE_RESOURCE, rustc_parse::DEFAULT_LOCALE_RESOURCE, rustc_passes::DEFAULT_LOCALE_RESOURCE, - rustc_trait_selection::DEFAULT_LOCALE_RESOURCE, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index c9e887061305f..641defd1eabfe 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -192,7 +192,7 @@ pub fn fluent_bundle( Ok(Some(bundle)) } -fn register_functions(bundle: &mut FluentBundle) { +pub fn register_functions(bundle: &mut fluent_bundle::bundle::FluentBundle) { bundle .add_function("STREQ", |positional, _named| match positional { [FluentValue::String(a), FluentValue::String(b)] => format!("{}", (a == b)).into(), diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index aba79c30f3a30..ed3f9a405342e 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -3,8 +3,8 @@ use std::env; use std::error::Report; use std::sync::Arc; -use rustc_error_messages::langid; pub use rustc_error_messages::{FluentArgs, LazyFallbackBundle}; +use rustc_error_messages::{langid, register_functions}; use tracing::{debug, trace}; use crate::error::{TranslateError, TranslateErrorKind}; @@ -91,6 +91,7 @@ impl Translator { let mut bundle = fluent_bundle::FluentBundle::new(vec![langid!("en-US")]); bundle.set_use_isolating(false); bundle.add_resource(resource).unwrap(); + register_functions(&mut bundle); let message = bundle.get_message(GENERATED_MSG_ID).unwrap(); let value = message.value().unwrap(); diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index a444b5e4badf5..e4d93b2e0c29f 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -1094,6 +1094,9 @@ pub enum AttributeKind { /// Represents `#[rustc_dyn_incompatible_trait]`. RustcDynIncompatibleTrait(Span), + /// Represents `#[rustc_effective_visibility]`. + RustcEffectiveVisibility, + /// Represents `#[rustc_has_incoherent_inherent_impls]` RustcHasIncoherentInherentImpls, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index b6249e1e2ec2c..2a214fe58220b 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -112,6 +112,7 @@ impl AttributeKind { RustcDumpUserArgs => No, RustcDumpVtable(..) => No, RustcDynIncompatibleTrait(..) => No, + RustcEffectiveVisibility => Yes, RustcHasIncoherentInherentImpls => Yes, RustcHiddenTypeOfOpaques => No, RustcIfThisChanged(..) => No, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4c1bcffa1cf4c..b117fa8327296 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,6 +1,7 @@ // ignore-tidy-filelength use std::borrow::Cow; use std::fmt; +use std::ops::Not; use rustc_abi::ExternAbi; use rustc_ast::attr::AttributeExt; @@ -1012,10 +1013,14 @@ impl<'hir> Generics<'hir> { span_for_parentheses.map_or_else( || { - // We include bounds that come from a `#[derive(_)]` but point at the user's code, - // as we use this method to get a span appropriate for suggestions. + // We include bounds that come from a `#[derive(_)]` but point at the user's + // code, as we use this method to get a span appropriate for suggestions. let bs = bound.span(); - bs.can_be_used_for_suggestions().then(|| (bs.shrink_to_hi(), None)) + // We use `from_expansion` instead of `can_be_used_for_suggestions` because + // the trait bound from imperfect derives do point at the type parameter, + // but expanded to a where clause, so we want to ignore those. This is only + // true for derive intrinsics. + bs.from_expansion().not().then(|| (bs.shrink_to_hi(), None)) }, |span| Some((span.shrink_to_hi(), Some(span.shrink_to_lo()))), ) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 33b8d3c829655..4dd9f50d4a5d0 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -142,6 +142,7 @@ hir_analysis_copy_impl_on_non_adt = hir_analysis_copy_impl_on_type_with_dtor = the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors + .note = destructor declared here hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}` .label = can't implement cross-crate trait with a default impl for non-struct/enum type diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index c00122bce559a..e0bfae9617ff1 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -923,7 +923,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ); check_where_clauses(wfcx, def_id); - if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if tcx.is_type_const(def_id.into()) { wfcheck::check_type_const(wfcx, def_id, ty, true)?; } Ok(()) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 9e07d5260d20e..f418dec940bbc 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -6,10 +6,9 @@ use hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, MultiSpan, pluralize, struct_span_code_err}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::VisitorExt; -use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, find_attr, intravisit}; +use rustc_hir::{self as hir, AmbigArg, GenericParamKind, ImplItemKind, intravisit}; use rustc_infer::infer::{self, BoundRegionConversionTime, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::util; use rustc_middle::ty::error::{ExpectedFound, TypeError}; @@ -2051,12 +2050,8 @@ fn compare_type_const<'tcx>( impl_const_item: ty::AssocItem, trait_const_item: ty::AssocItem, ) -> Result<(), ErrorGuaranteed> { - let impl_is_type_const = - find_attr!(tcx.get_all_attrs(impl_const_item.def_id), AttributeKind::TypeConst(_)); - let trait_type_const_span = find_attr!( - tcx.get_all_attrs(trait_const_item.def_id), - AttributeKind::TypeConst(sp) => *sp - ); + let impl_is_type_const = tcx.is_type_const(impl_const_item.def_id); + let trait_type_const_span = tcx.type_const_span(trait_const_item.def_id); if let Some(trait_type_const_span) = trait_type_const_span && !impl_is_type_const diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index c20e5146546a2..31104411ab55b 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -6,6 +6,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint_defs::builtin::{REFINING_IMPL_TRAIT_INTERNAL, REFINING_IMPL_TRAIT_REACHABLE}; use rustc_middle::span_bug; use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::print::{with_no_trimmed_paths, with_types_for_signature}; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, @@ -332,6 +333,17 @@ fn report_mismatched_rpitit_signature<'tcx>( hir::FnRetTy::Return(ty) => ty.span, }); + // Use ForSignature mode to ensure RPITITs are printed as `impl Trait` rather than + // `impl Trait { T::method(..) }` when RTN is enabled. + // + // We use `with_no_trimmed_paths!` to avoid triggering the `trimmed_def_paths` query, + // which requires diagnostic context (via `must_produce_diag`). Since we're formatting + // the type before creating the diagnostic, we need to avoid this query. This is the + // standard approach used elsewhere in the compiler for formatting types in suggestions + // (e.g., see `rustc_hir_typeck/src/demand.rs`). + let return_ty_suggestion = + with_no_trimmed_paths!(with_types_for_signature!(format!("{return_ty}"))); + let span = unmatched_bound.unwrap_or(span); tcx.emit_node_span_lint( if is_internal { REFINING_IMPL_TRAIT_INTERNAL } else { REFINING_IMPL_TRAIT_REACHABLE }, @@ -342,7 +354,7 @@ fn report_mismatched_rpitit_signature<'tcx>( trait_return_span, pre, post, - return_ty, + return_ty: return_ty_suggestion, unmatched_bound, }, ); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8b50eceb26e49..acead42c9a0e8 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -953,7 +953,7 @@ pub(crate) fn check_associated_item( wfcx.register_wf_obligation(span, loc, ty.into()); let has_value = item.defaultness(tcx).has_value(); - if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if tcx.is_type_const(def_id.into()) { check_type_const(wfcx, def_id, ty, has_value)?; } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index f81913a9c86f3..466dc262764c9 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -122,9 +122,10 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; Err(tcx.dcx().emit_err(errors::CopyImplOnNonAdt { span })) } - Err(CopyImplementationError::HasDestructor) => { + Err(CopyImplementationError::HasDestructor(did)) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; - Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span })) + let impl_ = tcx.def_span(did); + Err(tcx.dcx().emit_err(errors::CopyImplOnTypeWithDtor { span, impl_ })) } Err(CopyImplementationError::HasUnsafeFields) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f0c9023c522cf..0fdc97756888b 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -278,6 +278,8 @@ pub(crate) struct CopyImplOnTypeWithDtor { #[primary_span] #[label] pub span: Span, + #[note] + pub impl_: Span, } #[derive(Diagnostic)] @@ -1023,7 +1025,7 @@ pub(crate) struct UnusedAssociatedTypeBounds { #[diag(hir_analysis_rpitit_refined)] #[note] #[note(hir_analysis_feedback_note)] -pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { +pub(crate) struct ReturnPositionImplTraitInTraitRefined { #[suggestion(applicability = "maybe-incorrect", code = "{pre}{return_ty}{post}")] pub impl_return_span: Span, #[label] @@ -1033,7 +1035,7 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { pub pre: &'static str, pub post: &'static str, - pub return_ty: Ty<'tcx>, + pub return_ty: String, } #[derive(LintDiagnostic)] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 3515ce4ea9399..a1c3af5f999d4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -4,10 +4,9 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::attrs::AttributeKind; +use rustc_hir::PolyTraitRef; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; -use rustc_hir::{PolyTraitRef, find_attr}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -603,10 +602,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }); if let ty::AssocTag::Const = assoc_tag - && !find_attr!( - self.tcx().get_all_attrs(assoc_item.def_id), - AttributeKind::TypeConst(_) - ) + && !self.tcx().is_type_const(assoc_item.def_id) { if tcx.features().min_generic_const_args() { let mut err = self.dcx().struct_span_err( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 29f29761b6055..57defac577d8a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -592,7 +592,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if span.can_be_used_for_suggestions() && poly_trait_ref.trait_ref.trait_def_id().is_some() && !self.maybe_suggest_impl_trait(span, hir_id, hir_bounds, &mut diag) - && !self.maybe_suggest_dyn_trait(hir_id, sugg, &mut diag) + && !self.maybe_suggest_dyn_trait(hir_id, span, sugg, &mut diag) { self.maybe_suggest_add_generic_impl_trait(span, hir_id, &mut diag); } @@ -750,10 +750,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn maybe_suggest_dyn_trait( &self, hir_id: hir::HirId, + span: Span, sugg: Vec<(Span, String)>, diag: &mut Diag<'_>, ) -> bool { let tcx = self.tcx(); + if span.in_derive_expansion() { + return false; + } // Look at the direct HIR parent, since we care about the relationship between // the type and the thing that directly encloses it. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 9f84f652698b4..d4b9d2e359d59 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -28,10 +28,9 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, struct_span_code_err, }; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId, find_attr}; +use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::DynCompatibilityViolation; use rustc_macros::{TypeFoldable, TypeVisitable}; @@ -1423,7 +1422,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { LowerTypeRelativePathMode::Const, )? { TypeRelativePath::AssocItem(def_id, args) => { - if !find_attr!(self.tcx().get_all_attrs(def_id), AttributeKind::TypeConst(_)) { + if !self.tcx().is_type_const(def_id) { let mut err = self.dcx().struct_span_err( span, "use of trait associated const without `#[type_const]`", @@ -1896,7 +1895,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::AssocTag::Const, ) { Ok((item_def_id, item_args)) => { - if !find_attr!(self.tcx().get_all_attrs(item_def_id), AttributeKind::TypeConst(_)) { + if !self.tcx().is_type_const(item_def_id) { let mut err = self.dcx().struct_span_err( span, "use of `const` in the type system without `#[type_const]`", diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index f7a1434359593..01f57f3a56df6 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -85,12 +85,9 @@ mod variance; pub use errors::NoVariantNamed; use rustc_abi::{CVariadicStatus, ExternAbi}; -use rustc_hir::attrs::AttributeKind; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::lints::DelayedLint; -use rustc_hir::{ - find_attr, {self as hir}, -}; use rustc_middle::mir::interpret::GlobalId; use rustc_middle::query::Providers; use rustc_middle::ty::{Const, Ty, TyCtxt}; @@ -238,7 +235,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { } DefKind::Const if !tcx.generics_of(item_def_id).own_requires_monomorphization() - && !find_attr!(tcx.get_all_attrs(item_def_id), AttributeKind::TypeConst(_)) => + && !tcx.is_type_const(item_def_id.into()) => { // FIXME(generic_const_items): Passing empty instead of identity args is fishy but // seems to be fine for now. Revisit this! diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 934aa0a996143..c703057a30fbf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1932,25 +1932,94 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, ); } else { + let mut suggest_derive = true; if let Some(errors) = self.type_implements_trait_shallow(clone_trait_did, expected_ty, self.param_env) { + let manually_impl = "consider manually implementing `Clone` to avoid the \ + implicit type parameter bounds"; match &errors[..] { [] => {} [error] => { - diag.help(format!( - "`Clone` is not implemented because the trait bound `{}` is \ - not satisfied", - error.obligation.predicate, - )); + let msg = "`Clone` is not implemented because a trait bound is not \ + satisfied"; + if let traits::ObligationCauseCode::ImplDerived(data) = + error.obligation.cause.code() + { + let mut span: MultiSpan = data.span.into(); + if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) { + span.push_span_label( + data.span, + format!( + "derive introduces an implicit `{}` bound", + error.obligation.predicate + ), + ); + } + diag.span_help(span, msg); + if self.tcx.is_automatically_derived(data.impl_or_alias_def_id) + && data.impl_or_alias_def_id.is_local() + { + diag.help(manually_impl); + suggest_derive = false; + } + } else { + diag.help(msg); + } } _ => { - diag.help(format!( - "`Clone` is not implemented because the following trait bounds \ - could not be satisfied: {}", - listify(&errors, |e| format!("`{}`", e.obligation.predicate)) - .unwrap(), - )); + let unsatisfied_bounds: Vec<_> = errors + .iter() + .filter_map(|error| match error.obligation.cause.code() { + traits::ObligationCauseCode::ImplDerived(data) => { + let pre = if self + .tcx + .is_automatically_derived(data.impl_or_alias_def_id) + { + "derive introduces an implicit " + } else { + "" + }; + Some(( + data.span, + format!( + "{pre}unsatisfied trait bound `{}`", + error.obligation.predicate + ), + )) + } + _ => None, + }) + .collect(); + let msg = "`Clone` is not implemented because the some trait bounds \ + could not be satisfied"; + if errors.len() == unsatisfied_bounds.len() { + let mut unsatisfied_bounds_spans: MultiSpan = unsatisfied_bounds + .iter() + .map(|(span, _)| *span) + .collect::>() + .into(); + for (span, label) in unsatisfied_bounds { + unsatisfied_bounds_spans.push_span_label(span, label); + } + diag.span_help(unsatisfied_bounds_spans, msg); + if errors.iter().all(|error| match error.obligation.cause.code() { + traits::ObligationCauseCode::ImplDerived(data) => { + self.tcx.is_automatically_derived(data.impl_or_alias_def_id) + && data.impl_or_alias_def_id.is_local() + } + _ => false, + }) { + diag.help(manually_impl); + suggest_derive = false; + } + } else { + diag.help(format!( + "{msg}: {}", + listify(&errors, |e| format!("`{}`", e.obligation.predicate)) + .unwrap(), + )); + } } } for error in errors { @@ -1968,7 +2037,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]); + if suggest_derive { + self.suggest_derive(diag, &vec![(trait_ref.upcast(self.tcx), None, None)]); + } } } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index cd25b866b0983..517d73f517833 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1748,19 +1748,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find all the requirements that come from a local `impl` block. let mut skip_list: UnordSet<_> = Default::default(); let mut spanned_predicates = FxIndexMap::default(); + let mut manually_impl = false; for (p, parent_p, cause) in unsatisfied_predicates { // Extract the predicate span and parent def id of the cause, // if we have one. - let (item_def_id, cause_span) = match cause.as_ref().map(|cause| cause.code()) { - Some(ObligationCauseCode::ImplDerived(data)) => { - (data.impl_or_alias_def_id, data.span) - } - Some( - ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _) - | ObligationCauseCode::WhereClause(def_id, span), - ) if !span.is_dummy() => (*def_id, *span), - _ => continue, - }; + let (item_def_id, cause_span, cause_msg) = + match cause.as_ref().map(|cause| cause.code()) { + Some(ObligationCauseCode::ImplDerived(data)) => { + let msg = if let DefKind::Impl { of_trait: true } = + self.tcx.def_kind(data.impl_or_alias_def_id) + { + format!( + "type parameter would need to implement `{}`", + self.tcx + .item_name(self.tcx.impl_trait_id(data.impl_or_alias_def_id)) + ) + } else { + format!("unsatisfied bound `{p}` introduced here") + }; + (data.impl_or_alias_def_id, data.span, msg) + } + Some( + ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _) + | ObligationCauseCode::WhereClause(def_id, span), + ) if !span.is_dummy() => { + (*def_id, *span, format!("unsatisfied bound `{p}` introduced here")) + } + _ => continue, + }; // Don't point out the span of `WellFormed` predicates. if !matches!( @@ -1791,13 +1806,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let entry = entry.or_insert_with(|| { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); - entry.0.insert(span); + entry.0.insert(cause_span); entry.1.insert(( - span, - "unsatisfied trait bound introduced in this `derive` macro", + cause_span, + cause_msg, )); entry.2.push(p); skip_list.insert(p); + manually_impl = true; } // Unmet obligation coming from an `impl`. @@ -1842,7 +1858,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.2.push(p); if cause_span != *item_span { entry.0.insert(cause_span); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); + entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); } else { if let Some(of_trait) = of_trait { entry.0.insert(of_trait.trait_ref.path.span); @@ -1850,9 +1866,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { entry.0.insert(self_ty.span); }; if let Some(of_trait) = of_trait { - entry.1.insert((of_trait.trait_ref.path.span, "")); + entry.1.insert((of_trait.trait_ref.path.span, String::new())); } - entry.1.insert((self_ty.span, "")); + entry.1.insert((self_ty.span, String::new())); } Some(Node::Item(hir::Item { kind: hir::ItemKind::Trait(_, rustc_ast::ast::IsAuto::Yes, ..), @@ -1881,8 +1897,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (FxIndexSet::default(), FxIndexSet::default(), Vec::new()) }); entry.0.insert(cause_span); - entry.1.insert((ident.span, "")); - entry.1.insert((cause_span, "unsatisfied trait bound introduced here")); + entry.1.insert((ident.span, String::new())); + entry.1.insert((cause_span, "unsatisfied trait bound introduced here".to_string())); entry.2.push(p); } _ => { @@ -2083,6 +2099,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { *suggested_derive = self.suggest_derive(err, unsatisfied_predicates); *unsatisfied_bounds = true; } + if manually_impl { + err.help("consider manually implementing the trait to avoid undesired bounds"); + } } /// If an appropriate error source is not found, check method chain for possible candidates diff --git a/compiler/rustc_lexer/src/cursor.rs b/compiler/rustc_lexer/src/cursor.rs deleted file mode 100644 index 165262b82c75d..0000000000000 --- a/compiler/rustc_lexer/src/cursor.rs +++ /dev/null @@ -1,125 +0,0 @@ -use std::str::Chars; - -pub enum FrontmatterAllowed { - Yes, - No, -} - -/// Peekable iterator over a char sequence. -/// -/// Next characters can be peeked via `first` method, -/// and position can be shifted forward via `bump` method. -pub struct Cursor<'a> { - len_remaining: usize, - /// Iterator over chars. Slightly faster than a &str. - chars: Chars<'a>, - pub(crate) frontmatter_allowed: FrontmatterAllowed, - #[cfg(debug_assertions)] - prev: char, -} - -pub(crate) const EOF_CHAR: char = '\0'; - -impl<'a> Cursor<'a> { - pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> { - Cursor { - len_remaining: input.len(), - chars: input.chars(), - frontmatter_allowed, - #[cfg(debug_assertions)] - prev: EOF_CHAR, - } - } - - pub fn as_str(&self) -> &'a str { - self.chars.as_str() - } - - /// Returns the last eaten symbol (or `'\0'` in release builds). - /// (For debug assertions only.) - pub(crate) fn prev(&self) -> char { - #[cfg(debug_assertions)] - { - self.prev - } - - #[cfg(not(debug_assertions))] - { - EOF_CHAR - } - } - - /// Peeks the next symbol from the input stream without consuming it. - /// If requested position doesn't exist, `EOF_CHAR` is returned. - /// However, getting `EOF_CHAR` doesn't always mean actual end of file, - /// it should be checked with `is_eof` method. - pub fn first(&self) -> char { - // `.next()` optimizes better than `.nth(0)` - self.chars.clone().next().unwrap_or(EOF_CHAR) - } - - /// Peeks the second symbol from the input stream without consuming it. - pub(crate) fn second(&self) -> char { - // `.next()` optimizes better than `.nth(1)` - let mut iter = self.chars.clone(); - iter.next(); - iter.next().unwrap_or(EOF_CHAR) - } - - /// Peeks the third symbol from the input stream without consuming it. - pub fn third(&self) -> char { - // `.next()` optimizes better than `.nth(2)` - let mut iter = self.chars.clone(); - iter.next(); - iter.next(); - iter.next().unwrap_or(EOF_CHAR) - } - - /// Checks if there is nothing more to consume. - pub(crate) fn is_eof(&self) -> bool { - self.chars.as_str().is_empty() - } - - /// Returns amount of already consumed symbols. - pub(crate) fn pos_within_token(&self) -> u32 { - (self.len_remaining - self.chars.as_str().len()) as u32 - } - - /// Resets the number of bytes consumed to 0. - pub(crate) fn reset_pos_within_token(&mut self) { - self.len_remaining = self.chars.as_str().len(); - } - - /// Moves to the next character. - pub(crate) fn bump(&mut self) -> Option { - let c = self.chars.next()?; - - #[cfg(debug_assertions)] - { - self.prev = c; - } - - Some(c) - } - - /// Moves to a substring by a number of bytes. - pub(crate) fn bump_bytes(&mut self, n: usize) { - self.chars = self.as_str()[n..].chars(); - } - - /// Eats symbols while predicate returns true or until the end of file is reached. - pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { - // It was tried making optimized version of this for eg. line comments, but - // LLVM can inline all of this and compile it down to fast iteration over bytes. - while predicate(self.first()) && !self.is_eof() { - self.bump(); - } - } - - pub(crate) fn eat_until(&mut self, byte: u8) { - self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) { - Some(index) => self.as_str()[index..].chars(), - None => "".chars(), - } - } -} diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index 27ffcbc943bde..9d3da6ef49302 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -25,15 +25,13 @@ #![deny(unstable_features)] // tidy-alphabetical-end -mod cursor; - #[cfg(test)] mod tests; +use std::str::Chars; + use LiteralKind::*; use TokenKind::*; -use cursor::EOF_CHAR; -pub use cursor::{Cursor, FrontmatterAllowed}; pub use unicode_ident::UNICODE_VERSION; use unicode_properties::UnicodeEmoji; @@ -407,7 +405,129 @@ pub fn is_ident(string: &str) -> bool { } } -impl Cursor<'_> { +pub enum FrontmatterAllowed { + Yes, + No, +} + +/// Peekable iterator over a char sequence. +/// +/// Next characters can be peeked via `first` method, +/// and position can be shifted forward via `bump` method. +pub struct Cursor<'a> { + len_remaining: usize, + /// Iterator over chars. Slightly faster than a &str. + chars: Chars<'a>, + pub(crate) frontmatter_allowed: FrontmatterAllowed, + #[cfg(debug_assertions)] + prev: char, +} + +const EOF_CHAR: char = '\0'; + +impl<'a> Cursor<'a> { + pub fn new(input: &'a str, frontmatter_allowed: FrontmatterAllowed) -> Cursor<'a> { + Cursor { + len_remaining: input.len(), + chars: input.chars(), + frontmatter_allowed, + #[cfg(debug_assertions)] + prev: EOF_CHAR, + } + } + + pub fn as_str(&self) -> &'a str { + self.chars.as_str() + } + + /// Returns the last eaten symbol (or `'\0'` in release builds). + /// (For debug assertions only.) + pub(crate) fn prev(&self) -> char { + #[cfg(debug_assertions)] + { + self.prev + } + + #[cfg(not(debug_assertions))] + { + EOF_CHAR + } + } + + /// Peeks the next symbol from the input stream without consuming it. + /// If requested position doesn't exist, `EOF_CHAR` is returned. + /// However, getting `EOF_CHAR` doesn't always mean actual end of file, + /// it should be checked with `is_eof` method. + pub fn first(&self) -> char { + // `.next()` optimizes better than `.nth(0)` + self.chars.clone().next().unwrap_or(EOF_CHAR) + } + + /// Peeks the second symbol from the input stream without consuming it. + pub(crate) fn second(&self) -> char { + // `.next()` optimizes better than `.nth(1)` + let mut iter = self.chars.clone(); + iter.next(); + iter.next().unwrap_or(EOF_CHAR) + } + + /// Peeks the third symbol from the input stream without consuming it. + pub fn third(&self) -> char { + // `.next()` optimizes better than `.nth(2)` + let mut iter = self.chars.clone(); + iter.next(); + iter.next(); + iter.next().unwrap_or(EOF_CHAR) + } + + /// Checks if there is nothing more to consume. + pub(crate) fn is_eof(&self) -> bool { + self.chars.as_str().is_empty() + } + + /// Returns amount of already consumed symbols. + pub(crate) fn pos_within_token(&self) -> u32 { + (self.len_remaining - self.chars.as_str().len()) as u32 + } + + /// Resets the number of bytes consumed to 0. + pub(crate) fn reset_pos_within_token(&mut self) { + self.len_remaining = self.chars.as_str().len(); + } + + /// Moves to the next character. + pub(crate) fn bump(&mut self) -> Option { + let c = self.chars.next()?; + + #[cfg(debug_assertions)] + { + self.prev = c; + } + + Some(c) + } + + /// Moves to a substring by a number of bytes. + pub(crate) fn bump_bytes(&mut self, n: usize) { + self.chars = self.as_str()[n..].chars(); + } + + /// Eats symbols while predicate returns true or until the end of file is reached. + pub(crate) fn eat_while(&mut self, mut predicate: impl FnMut(char) -> bool) { + // It was tried making optimized version of this for eg. line comments, but + // LLVM can inline all of this and compile it down to fast iteration over bytes. + while predicate(self.first()) && !self.is_eof() { + self.bump(); + } + } + + pub(crate) fn eat_until(&mut self, byte: u8) { + self.chars = match memchr::memchr(byte, self.as_str().as_bytes()) { + Some(index) => self.as_str()[index..].chars(), + None => "".chars(), + } + } + /// Parses a token from the input string. pub fn advance_token(&mut self) -> Token { let Some(first_char) = self.bump() else { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 41e1388e31464..348e5ccf6217f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1886,10 +1886,15 @@ impl<'tcx> TyCtxt<'tcx> { self.is_lang_item(self.parent(def_id), LangItem::AsyncDropInPlace) } + pub fn type_const_span(self, def_id: DefId) -> Option { + matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst) + .then(|| find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(sp) => *sp)) + .flatten() + } + /// Check if the given `def_id` is a const with the `#[type_const]` attribute. pub fn is_type_const(self, def_id: DefId) -> bool { - matches!(self.def_kind(def_id), DefKind::Const | DefKind::AssocConst) - && find_attr!(self.get_all_attrs(def_id), AttributeKind::TypeConst(_)) + self.type_const_span(def_id).is_some() } /// Returns the movability of the coroutine of `def_id`, or panics diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 279c34cb275d9..b3b06314e1a0f 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -526,12 +526,15 @@ pub fn suggest_constraining_type_params<'a>( // // fn foo(t: T) { ... } // - help: consider restricting this type parameter with `T: Foo` - suggestions.push(( - param.span.shrink_to_hi(), - post, - format!(": {constraint}"), - SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, - )); + let span = param.span.shrink_to_hi(); + if span.can_be_used_for_suggestions() { + suggestions.push(( + span, + post, + format!(": {constraint}"), + SuggestChangingConstraintsMessage::RestrictType { ty: param_name }, + )); + } } // FIXME: remove the suggestions that are from derive, as the span is not correct diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 4e789a321649e..8991e3b9d502e 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use std::path::PathBuf; -use rustc_ast::token::Token; +use rustc_ast::token::{self, InvisibleOrigin, MetaVarKind, Token}; use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::{Path, Visibility}; use rustc_errors::codes::*; @@ -17,7 +17,6 @@ use rustc_span::edition::{Edition, LATEST_STABLE_EDITION}; use rustc_span::{Ident, Span, Symbol}; use crate::fluent_generated as fluent; -use crate::parser::{ForbiddenLetReason, TokenDescription}; #[derive(Diagnostic)] #[diag(parse_maybe_report_ambiguous_plus)] @@ -3710,3 +3709,64 @@ pub(crate) struct StructLiteralWithoutPathLate { #[suggestion(applicability = "has-placeholders", code = "/* Type */ ", style = "verbose")] pub suggestion_span: Span, } + +/// Used to forbid `let` expressions in certain syntactic locations. +#[derive(Clone, Copy, Subdiagnostic)] +pub(crate) enum ForbiddenLetReason { + /// `let` is not valid and the source environment is not important + OtherForbidden, + /// A let chain with the `||` operator + #[note(parse_not_supported_or)] + NotSupportedOr(#[primary_span] Span), + /// A let chain with invalid parentheses + /// + /// For example, `let 1 = 1 && (expr && expr)` is allowed + /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not + #[note(parse_not_supported_parentheses)] + NotSupportedParentheses(#[primary_span] Span), +} + +#[derive(Debug, rustc_macros::Subdiagnostic)] +#[suggestion( + parse_misspelled_kw, + applicability = "machine-applicable", + code = "{similar_kw}", + style = "verbose" +)] +pub(crate) struct MisspelledKw { + // We use a String here because `Symbol::into_diag_arg` calls `Symbol::to_ident_string`, which + // prefix the keyword with a `r#` because it aims to print the symbol as an identifier. + pub similar_kw: String, + #[primary_span] + pub span: Span, + pub is_incorrect_case: bool, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub(super) enum TokenDescription { + ReservedIdentifier, + Keyword, + ReservedKeyword, + DocComment, + + // Expanded metavariables are wrapped in invisible delimiters which aren't + // pretty-printed. In error messages we must handle these specially + // otherwise we get confusing things in messages like "expected `(`, found + // ``". It's better to say e.g. "expected `(`, found type metavariable". + MetaVar(MetaVarKind), +} + +impl TokenDescription { + pub(super) fn from_token(token: &Token) -> Option { + match token.kind { + _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier), + _ if token.is_used_keyword() => Some(TokenDescription::Keyword), + _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword), + token::DocComment(..) => Some(TokenDescription::DocComment), + token::OpenInvisible(InvisibleOrigin::MetaVar(kind)) => { + Some(TokenDescription::MetaVar(kind)) + } + _ => None, + } + } +} diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 60e12fa05adfd..cb8a291c7fa05 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -35,10 +35,10 @@ use crate::errors::{ ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, - PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, - StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, - SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, TernaryOperatorSuggestion, - UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, + MisspelledKw, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, + SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, + SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, + TernaryOperatorSuggestion, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; use crate::parser::FnContext; @@ -212,22 +212,6 @@ impl std::fmt::Display for UnaryFixity { } } -#[derive(Debug, rustc_macros::Subdiagnostic)] -#[suggestion( - parse_misspelled_kw, - applicability = "machine-applicable", - code = "{similar_kw}", - style = "verbose" -)] -struct MisspelledKw { - // We use a String here because `Symbol::into_diag_arg` calls `Symbol::to_ident_string`, which - // prefix the keyword with a `r#` because it aims to print the symbol as an identifier. - similar_kw: String, - #[primary_span] - span: Span, - is_incorrect_case: bool, -} - /// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`. /// /// This is a specialized version of [`Symbol::find_similar`] that constructs an error when a diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 44c6acec88660..84fe6770be583 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -21,7 +21,6 @@ use rustc_ast::{ use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic}; use rustc_literal_escaper::unescape_char; -use rustc_macros::Subdiagnostic; use rustc_session::errors::{ExprParenthesesNeeded, report_lit_error}; use rustc_session::lint::BuiltinLintDiag; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; @@ -2774,7 +2773,7 @@ impl<'a> Parser<'a> { let recovered = if !restrictions.contains(Restrictions::ALLOW_LET) { let err = errors::ExpectedExpressionFoundLet { span: self.token.span, - reason: ForbiddenLetReason::OtherForbidden, + reason: errors::ForbiddenLetReason::OtherForbidden, missing_let: None, comparison: None, }; @@ -4189,22 +4188,6 @@ pub(crate) fn could_be_unclosed_char_literal(ident: Ident) -> bool { && unescape_char(ident.without_first_quote().name.as_str()).is_ok() } -/// Used to forbid `let` expressions in certain syntactic locations. -#[derive(Clone, Copy, Subdiagnostic)] -pub(crate) enum ForbiddenLetReason { - /// `let` is not valid and the source environment is not important - OtherForbidden, - /// A let chain with the `||` operator - #[note(parse_not_supported_or)] - NotSupportedOr(#[primary_span] Span), - /// A let chain with invalid parentheses - /// - /// For example, `let 1 = 1 && (expr && expr)` is allowed - /// but `(let 1 = 1 && (let 1 = 1 && (let 1 = 1))) && let a = 1` is not - #[note(parse_not_supported_parentheses)] - NotSupportedParentheses(#[primary_span] Span), -} - /// Whether let chains are allowed on all editions, or it's edition dependent (allowed only on /// 2024 and later). In case of edition dependence, specify the currently present edition. pub enum LetChainsPolicy { @@ -4225,7 +4208,7 @@ struct CondChecker<'a> { parser: &'a Parser<'a>, let_chains_policy: LetChainsPolicy, depth: u32, - forbid_let_reason: Option, + forbid_let_reason: Option, missing_let: Option, comparison: Option, found_incorrect_let_chain: Option, @@ -4248,14 +4231,13 @@ impl<'a> CondChecker<'a> { impl MutVisitor for CondChecker<'_> { fn visit_expr(&mut self, e: &mut Expr) { self.depth += 1; - use ForbiddenLetReason::*; let span = e.span; match e.kind { ExprKind::Let(_, _, _, ref mut recovered @ Recovered::No) => { if let Some(reason) = self.forbid_let_reason { let error = match reason { - NotSupportedOr(or_span) => { + errors::ForbiddenLetReason::NotSupportedOr(or_span) => { self.parser.dcx().emit_err(errors::OrInLetChain { span: or_span }) } _ => { @@ -4289,24 +4271,27 @@ impl MutVisitor for CondChecker<'_> { mut_visit::walk_expr(self, e); } ExprKind::Binary(Spanned { node: BinOpKind::Or, span: or_span }, _, _) - if let None | Some(NotSupportedOr(_)) = self.forbid_let_reason => + if let None | Some(errors::ForbiddenLetReason::NotSupportedOr(_)) = + self.forbid_let_reason => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(NotSupportedOr(or_span)); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::NotSupportedOr(or_span)); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } ExprKind::Paren(ref inner) - if let None | Some(NotSupportedParentheses(_)) = self.forbid_let_reason => + if let None | Some(errors::ForbiddenLetReason::NotSupportedParentheses(_)) = + self.forbid_let_reason => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(NotSupportedParentheses(inner.span)); + self.forbid_let_reason = + Some(errors::ForbiddenLetReason::NotSupportedParentheses(inner.span)); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } ExprKind::Assign(ref lhs, _, span) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); let missing_let = self.missing_let; if let ExprKind::Binary(_, _, rhs) = &lhs.kind && let ExprKind::Path(_, _) @@ -4339,7 +4324,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Tup(_) | ExprKind::Paren(_) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } @@ -4347,7 +4332,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Type(ref mut op, _) | ExprKind::UnsafeBinderCast(_, ref mut op, _) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(OtherForbidden); + self.forbid_let_reason = Some(errors::ForbiddenLetReason::OtherForbidden); self.visit_expr(op); self.forbid_let_reason = forbid_let_reason; } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 3ef73a55d47d7..0ff0b66229366 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -20,7 +20,6 @@ use std::{fmt, mem, slice}; use attr_wrapper::{AttrWrapper, UsePreAttrPos}; pub use diagnostics::AttemptLocalParseRecovery; -pub(crate) use expr::ForbiddenLetReason; // Public to use it for custom `if` expressions in rustfmt forks like https://github.com/tucant/rustfmt pub use expr::LetChainsPolicy; pub(crate) use item::{FnContext, FnParseMode}; @@ -50,7 +49,7 @@ use token_type::TokenTypeSet; pub use token_type::{ExpKeywordPair, ExpTokenPair, TokenType}; use tracing::debug; -use crate::errors::{self, IncorrectVisibilityRestriction, NonStringAbiLiteral}; +use crate::errors::{self, IncorrectVisibilityRestriction, NonStringAbiLiteral, TokenDescription}; use crate::exp; #[cfg(test)] @@ -308,35 +307,6 @@ impl From for Trailing { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub(super) enum TokenDescription { - ReservedIdentifier, - Keyword, - ReservedKeyword, - DocComment, - - // Expanded metavariables are wrapped in invisible delimiters which aren't - // pretty-printed. In error messages we must handle these specially - // otherwise we get confusing things in messages like "expected `(`, found - // ``". It's better to say e.g. "expected `(`, found type metavariable". - MetaVar(MetaVarKind), -} - -impl TokenDescription { - pub(super) fn from_token(token: &Token) -> Option { - match token.kind { - _ if token.is_special_ident() => Some(TokenDescription::ReservedIdentifier), - _ if token.is_used_keyword() => Some(TokenDescription::Keyword), - _ if token.is_unused_keyword() => Some(TokenDescription::ReservedKeyword), - token::DocComment(..) => Some(TokenDescription::DocComment), - token::OpenInvisible(InvisibleOrigin::MetaVar(kind)) => { - Some(TokenDescription::MetaVar(kind)) - } - _ => None, - } - } -} - pub fn token_descr(token: &Token) -> String { let s = pprust::token_to_string(token).to_string(); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0d64e30d9c79e..acc7abe191675 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -307,6 +307,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::RustcDumpUserArgs | AttributeKind::RustcDumpVtable(..) | AttributeKind::RustcDynIncompatibleTrait(..) + | AttributeKind::RustcEffectiveVisibility | AttributeKind::RustcHasIncoherentInherentImpls | AttributeKind::RustcHiddenTypeOfOpaques | AttributeKind::RustcIfThisChanged(..) @@ -401,7 +402,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::rustc_regions | sym::rustc_strict_coherence | sym::rustc_mir - | sym::rustc_effective_visibility | sym::rustc_outlives | sym::rustc_symbol_name | sym::rustc_evaluate_where_clauses diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4a88ea0cc4450..f69f8777ef425 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -876,7 +876,7 @@ pub struct TestReachabilityVisitor<'a, 'tcx> { impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> { fn effective_visibility_diagnostic(&self, def_id: LocalDefId) { - if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) { + if find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::RustcEffectiveVisibility) { let mut error_msg = String::new(); let span = self.tcx.def_span(def_id.to_def_id()); if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) { diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 1071105522d11..cd61a8f654733 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -10,7 +10,6 @@ rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } -rustc_fluent_macro = { path = "../rustc_fluent_macro" } rustc_hir = { path = "../rustc_hir" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl deleted file mode 100644 index fcb250250871e..0000000000000 --- a/compiler/rustc_trait_selection/messages.ftl +++ /dev/null @@ -1,470 +0,0 @@ -trait_selection_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} -trait_selection_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} -trait_selection_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> - [true] , for some specific lifetime `'{$lifetime}` - *[false] {""} -} - -trait_selection_actual_impl_expl_expected_other_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_other_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}` - -trait_selection_actual_impl_expl_expected_other_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_other_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_actual_impl_expl_expected_passive_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}` -trait_selection_actual_impl_expl_expected_passive_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_passive_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_actual_impl_expl_expected_signature_any = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}` -trait_selection_actual_impl_expl_expected_signature_some = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`... -trait_selection_actual_impl_expl_expected_signature_two = {$leading_ellipsis -> - [true] ... - *[false] {""} -}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... -trait_selection_adjust_signature_borrow = consider adjusting the signature so it borrows its {$len -> - [one] argument - *[other] arguments - } - -trait_selection_adjust_signature_remove_borrow = consider adjusting the signature so it does not borrow its {$len -> - [one] argument - *[other] arguments - } - -trait_selection_ascribe_user_type_prove_predicate = ...so that the where clause holds - -trait_selection_await_both_futures = consider `await`ing on both `Future`s -trait_selection_await_future = consider `await`ing on the `Future` -trait_selection_await_note = calling an async function returns a future - -trait_selection_but_calling_introduces = {$has_param_name -> - [true] `{$param_name}` - *[false] `fn` parameter -} has {$lifetime_kind -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` -} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement - .label1 = {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` - } - .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> - [true] `impl` of `{$impl_path}` - *[false] inherent `impl` - } - -trait_selection_but_needs_to_satisfy = {$has_param_name -> - [true] `{$param_name}` - *[false] `fn` parameter -} has {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` -} but it needs to satisfy a `'static` lifetime requirement - .influencer = this data with {$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` - }... - .require = {$spans_empty -> - *[true] ...is used and required to live as long as `'static` here - [false] ...and is required to live as long as `'static` here - } - .used_here = ...is used here... - .introduced_by_bound = `'static` lifetime requirement introduced by this bound - -trait_selection_closure_fn_mut_label = closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here - -trait_selection_closure_fn_once_label = closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment - -trait_selection_closure_kind_mismatch = expected a closure that implements the `{$trait_prefix}{$expected}` trait, but this closure only implements `{$trait_prefix}{$found}` - .label = this closure implements `{$trait_prefix}{$found}`, not `{$trait_prefix}{$expected}` - -trait_selection_closure_kind_requirement = the requirement to implement `{$trait_prefix}{$expected}` derives from here - -trait_selection_compare_impl_item_obligation = ...so that the definition in impl matches the definition from the trait -trait_selection_consider_specifying_length = consider specifying the actual array length -trait_selection_coro_closure_not_fn = {$coro_kind}closure does not implement `{$kind}` because it captures state from its environment - -trait_selection_data_flows = ...but data{$label_var1_exists -> - [true] {" "}from `{$label_var1}` - *[false] {""} -} flows{$label_var2_exists -> - [true] {" "}into `{$label_var2}` - *[false] {""} -} here - -trait_selection_data_lifetime_flow = ...but data with one lifetime flows into the other here -trait_selection_data_returned = ...but data{$label_var1_exists -> - [true] {" "}from `{$label_var1}` - *[false] {""} -} is returned here - -trait_selection_declared_different = this parameter and the return type are declared with different lifetimes... -trait_selection_declared_multiple = this type is declared with multiple lifetimes... -trait_selection_disallowed_positional_argument = positional format arguments are not allowed here - .help = only named format arguments with the name of one of the generic types are allowed in this context - -trait_selection_does_not_outlive_static_from_impl = ...does not necessarily outlive the static lifetime introduced by the compatible `impl` -trait_selection_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement -trait_selection_dtcs_has_req_note = the used `impl` has a `'static` requirement -trait_selection_dtcs_introduces_requirement = calling this method introduces the `impl`'s `'static` requirement -trait_selection_dtcs_suggestion = consider relaxing the implicit `'static` requirement - -trait_selection_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}` - -trait_selection_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type - -trait_selection_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}` - .label = lifetime `{$named}` required - -trait_selection_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type - .label = lifetime `{$named}` required - -trait_selection_fn_consider_casting = consider casting the fn item to a fn pointer: `{$casting}` - -trait_selection_fn_consider_casting_both = consider casting both fn items to fn pointers using `as {$sig}` - -trait_selection_fn_uniq_types = different fn items have unique types, even if their signatures are the same -trait_selection_fps_cast = consider casting to a fn pointer -trait_selection_fps_cast_both = consider casting both fn items to fn pointers using `as {$expected_sig}` - -trait_selection_fps_items_are_distinct = fn items are distinct from fn pointers -trait_selection_fps_remove_ref = consider removing the reference -trait_selection_fps_use_ref = consider using a reference -trait_selection_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime - -trait_selection_ignored_diagnostic_option = `{$option_name}` is ignored due to previous definition of `{$option_name}` - .other_label = `{$option_name}` is first declared here - .label = `{$option_name}` is already declared here - -trait_selection_implicit_static_lifetime_note = this has an implicit `'static` lifetime requirement -trait_selection_implicit_static_lifetime_suggestion = consider relaxing the implicit `'static` requirement -trait_selection_inherent_projection_normalization_overflow = overflow evaluating associated type `{$ty}` - -trait_selection_invalid_format_specifier = invalid format specifier - .help = no format specifier are supported in this position - -trait_selection_label_bad = {$bad_kind -> - *[other] cannot infer type - [more_info] cannot infer {$prefix_kind -> - *[type] type for {$prefix} - [const_with_param] the value of const parameter - [const] the value of the constant - } `{$name}`{$has_parent -> - [true] {" "}declared on the {$parent_prefix} `{$parent_name}` - *[false] {""} - } -} - -trait_selection_lf_bound_not_satisfied = lifetime bound not satisfied -trait_selection_lifetime_mismatch = lifetime mismatch - -trait_selection_lifetime_param_suggestion = consider {$is_reuse -> - [true] reusing - *[false] introducing -} a named lifetime parameter{$is_impl -> - [true] {" "}and update trait if needed - *[false] {""} -} -trait_selection_lifetime_param_suggestion_elided = each elided lifetime in input position becomes a distinct lifetime - -trait_selection_malformed_on_unimplemented_attr = malformed `on_unimplemented` attribute - .help = only `message`, `note` and `label` are allowed as options - .label = invalid option found here - -trait_selection_meant_byte_literal = if you meant to write a byte literal, prefix with `b` -trait_selection_meant_char_literal = if you meant to write a `char` literal, use single quotes -trait_selection_meant_str_literal = if you meant to write a string literal, use double quotes -trait_selection_mismatched_static_lifetime = incompatible lifetime on type -trait_selection_missing_options_for_on_unimplemented_attr = missing options for `on_unimplemented` attribute - .help = at least one of the `message`, `note` and `label` options are expected - -trait_selection_msl_introduces_static = introduces a `'static` lifetime requirement -trait_selection_msl_unmet_req = because this has an unmet lifetime requirement - -trait_selection_negative_positive_conflict = found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> - [none] {""} - *[default] {" "}for type `{$self_desc}` - }: - .negative_implementation_here = negative implementation here - .negative_implementation_in_crate = negative implementation in crate `{$negative_impl_cname}` - .positive_implementation_here = positive implementation here - .positive_implementation_in_crate = positive implementation in crate `{$positive_impl_cname}` - -trait_selection_nothing = {""} - -trait_selection_oc_cant_coerce_force_inline = - cannot coerce functions which must be inlined to function pointers -trait_selection_oc_cant_coerce_intrinsic = cannot coerce intrinsics to function pointers -trait_selection_oc_closure_selfref = closure/coroutine type that references itself -trait_selection_oc_const_compat = const not compatible with trait -trait_selection_oc_fn_lang_correct_type = {$lang_item_name -> - [panic_impl] `#[panic_handler]` - *[lang_item_name] lang item `{$lang_item_name}` - } function has wrong type -trait_selection_oc_fn_main_correct_type = `main` function has wrong type -trait_selection_oc_generic = mismatched types - -trait_selection_oc_if_else_different = `if` and `else` have incompatible types -trait_selection_oc_intrinsic_correct_type = intrinsic has wrong type -trait_selection_oc_match_compat = `match` arms have incompatible types -trait_selection_oc_method_compat = method not compatible with trait -trait_selection_oc_method_correct_type = mismatched `self` parameter type -trait_selection_oc_no_diverge = `else` clause of `let...else` does not diverge -trait_selection_oc_no_else = `if` may be missing an `else` clause -trait_selection_oc_try_compat = `?` operator has incompatible types -trait_selection_oc_type_compat = type not compatible with trait - -trait_selection_opaque_captures_lifetime = hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds - .label = opaque type defined here -trait_selection_opaque_type_non_generic_param = - expected generic {$kind} parameter, found `{$arg}` - .label = {STREQ($arg, "'static") -> - [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type - *[other] this generic parameter must be used with a generic {$kind} parameter - } - -trait_selection_outlives_bound = lifetime of the source pointer does not outlive lifetime bound of the object type -trait_selection_outlives_content = lifetime of reference outlives lifetime of borrowed content... - -trait_selection_precise_capturing_existing = add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it -trait_selection_precise_capturing_new = add a `use<...>` bound to explicitly capture `{$new_lifetime}` - -trait_selection_precise_capturing_new_but_apit = add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate - -trait_selection_precise_capturing_overcaptures = use the precise capturing `use<...>` syntax to make the captures explicit - -trait_selection_prlf_defined_with_sub = the lifetime `{$sub_symbol}` defined here... -trait_selection_prlf_defined_without_sub = the lifetime defined here... -trait_selection_prlf_known_limitation = this is a known limitation that will be removed in the future (see issue #100013 for more information) - -trait_selection_prlf_must_outlive_with_sup = ...must outlive the lifetime `{$sup_symbol}` defined here -trait_selection_prlf_must_outlive_without_sup = ...must outlive the lifetime defined here -trait_selection_reborrow = ...so that reference does not outlive borrowed content -trait_selection_ref_longer_than_data = in type `{$ty}`, reference has a longer lifetime than the data it references - -trait_selection_reference_outlives_referent = ...so that the reference type `{$name}` does not outlive the data it points at -trait_selection_region_explanation = {$pref_kind -> - *[should_not_happen] [{$pref_kind}] - [ref_valid_for] ...the reference is valid for - [content_valid_for] ...but the borrowed content is only valid for - [type_obj_valid_for] object type is valid for - [source_pointer_valid_for] source pointer is only valid for - [type_satisfy] type must satisfy - [type_outlive] type must outlive - [lf_param_instantiated_with] lifetime parameter instantiated with - [lf_param_must_outlive] but lifetime parameter must outlive - [lf_instantiated_with] lifetime instantiated with - [lf_must_outlive] but lifetime must outlive - [pointer_valid_for] the pointer is valid for - [data_valid_for] but the referenced data is only valid for - [empty] {""} -}{$pref_kind -> - [empty] {""} - *[other] {" "} -}{$desc_kind -> - *[should_not_happen] [{$desc_kind}] - [restatic] the static lifetime - [revar] lifetime {$desc_arg} - [as_defined] the lifetime `{$desc_arg}` as defined here - [as_defined_anon] the anonymous lifetime as defined here - [defined_here] the anonymous lifetime defined here - [defined_here_reg] the lifetime `{$desc_arg}` as defined here -}{$suff_kind -> - *[should_not_happen] [{$suff_kind}] - [empty]{""} - [continues] ... - [req_by_binding] {" "}as required by this binding -} - -trait_selection_relate_object_bound = ...so that it can be closed over into an object -trait_selection_relate_param_bound = ...so that the type `{$name}` will meet its required lifetime bounds{$continues -> - [true] ... - *[false] {""} -} -trait_selection_relate_param_bound_2 = ...that is required by this bound -trait_selection_relate_region_param_bound = ...so that the declared lifetime parameter bounds are satisfied -trait_selection_ril_because_of = because of this returned expression -trait_selection_ril_introduced_by = requirement introduced by this return type -trait_selection_ril_introduced_here = `'static` requirement introduced here -trait_selection_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type - -trait_selection_rustc_on_unimplemented_empty_on_clause = empty `on`-clause in `#[rustc_on_unimplemented]` - .label = empty `on`-clause here -trait_selection_rustc_on_unimplemented_expected_identifier = expected an identifier inside this `on`-clause - .label = expected an identifier here, not `{$path}` -trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not = expected a single predicate in `not(..)` - .label = unexpected quantity of predicates here -trait_selection_rustc_on_unimplemented_invalid_flag = invalid flag in `on`-clause - .label = expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}` -trait_selection_rustc_on_unimplemented_invalid_name = invalid name in `on`-clause - .label = expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `{$invalid_name}` -trait_selection_rustc_on_unimplemented_invalid_predicate = this predicate is invalid - .label = expected one of `any`, `all` or `not` here, not `{$invalid_pred}` -trait_selection_rustc_on_unimplemented_missing_value = this attribute must have a value - .label = expected value here - .note = e.g. `#[rustc_on_unimplemented(message="foo")]` -trait_selection_rustc_on_unimplemented_unsupported_literal_in_on = literals inside `on`-clauses are not supported - .label = unexpected literal here - -trait_selection_source_kind_closure_return = - try giving this closure an explicit return type - -# coroutine_kind may need to be translated -trait_selection_source_kind_fully_qualified = - try using a fully qualified path to specify the expected types - -trait_selection_source_kind_subdiag_generic_label = - cannot infer {$is_type -> - [true] type - *[false] the value - } of the {$is_type -> - [true] type - *[false] const - } {$parent_exists -> - [true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` - *[false] parameter {$param_name} - } - -trait_selection_source_kind_subdiag_generic_suggestion = - consider specifying the generic {$arg_count -> - [one] argument - *[other] arguments - } - -trait_selection_source_kind_subdiag_let = {$kind -> - [with_pattern] consider giving `{$name}` an explicit type - [closure] consider giving this closure parameter an explicit type - *[other] consider giving this pattern a type -}{$x_kind -> - [has_name] , where the {$prefix_kind -> - *[type] type for {$prefix} - [const_with_param] value of const parameter - [const] value of the constant - } `{$arg_name}` is specified - [underscore] , where the placeholders `_` are specified - *[empty] {""} -} - -trait_selection_srs_add = consider returning the local binding `{$ident}` -trait_selection_srs_add_one = consider returning one of these bindings - -trait_selection_srs_remove = consider removing this semicolon -trait_selection_srs_remove_and_box = consider removing this semicolon and boxing the expressions -trait_selection_stp_wrap_many = try wrapping the pattern in a variant of `{$path}` - -trait_selection_stp_wrap_one = try wrapping the pattern in `{$variant}` -trait_selection_subtype = ...so that the {$requirement -> - [method_compat] method type is compatible with trait - [type_compat] associated type is compatible with trait - [const_compat] const is compatible with trait - [expr_assignable] expression is assignable - [if_else_different] `if` and `else` have incompatible types - [no_else] `if` missing an `else` returns `()` - [fn_main_correct_type] `main` function has the correct type - [fn_lang_correct_type] lang item function has the correct type - [intrinsic_correct_type] intrinsic has the correct type - [method_correct_type] method receiver has the correct type - *[other] types are compatible -} -trait_selection_subtype_2 = ...so that {$requirement -> - [method_compat] method type is compatible with trait - [type_compat] associated type is compatible with trait - [const_compat] const is compatible with trait - [expr_assignable] expression is assignable - [if_else_different] `if` and `else` have incompatible types - [no_else] `if` missing an `else` returns `()` - [fn_main_correct_type] `main` function has the correct type - [fn_lang_correct_type] lang item function has the correct type - [intrinsic_correct_type] intrinsic has the correct type - [method_correct_type] method receiver has the correct type - *[other] types are compatible -} - -trait_selection_suggest_accessing_field = you might have meant to use field `{$name}` whose type is `{$ty}` - -trait_selection_suggest_add_let_for_letchains = consider adding `let` - -trait_selection_tid_consider_borrowing = consider borrowing this type parameter in the trait -trait_selection_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` - -trait_selection_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output -trait_selection_trait_has_no_impls = this trait has no implementations, consider adding one - -trait_selection_trait_impl_diff = `impl` item signature doesn't match `trait` item signature - .found = found `{$found}` - .expected = expected `{$expected}` - .expected_found = expected signature `{$expected}` - {" "}found signature `{$found}` - -trait_selection_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough - .label_satisfy = doesn't satisfy where-clause - .label_where = due to a where-clause on `{$def_id}`... - .label_dup = implementation of `{$trait_def_id}` is not general enough - -trait_selection_try_cannot_convert = `?` operator cannot convert from `{$found}` to `{$expected}` - -trait_selection_tuple_trailing_comma = use a trailing comma to create a tuple with one element - -trait_selection_ty_alias_overflow = in case this is a recursive type alias, consider using a struct, enum, or union instead -trait_selection_type_annotations_needed = {$source_kind -> - [closure] type annotations needed for the closure `{$source_name}` - [normal] type annotations needed for `{$source_name}` - *[other] type annotations needed -} - .label = type must be known at this point - -trait_selection_types_declared_different = these two types are declared with different lifetimes... - -trait_selection_unable_to_construct_constant_value = unable to construct a constant value for the unevaluated constant {$unevaluated} - -trait_selection_unknown_format_parameter_for_on_unimplemented_attr = there is no parameter `{$argument_name}` on trait `{$trait_name}` - .help = expect either a generic argument name or {"`{Self}`"} as format argument - -trait_selection_warn_removing_apit_params_for_overcapture = you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable - -trait_selection_warn_removing_apit_params_for_undercapture = you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable - -trait_selection_where_copy_predicates = copy the `where` clause predicates from the trait - -trait_selection_where_remove = remove the `where` clause -trait_selection_wrapped_parser_error = {$description} - .label = {$label} diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index b11461cd0e32d..d15fb40dd1cb0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -2,7 +2,8 @@ use std::iter; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{ - Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, struct_span_code_err, + Applicability, Diag, E0309, E0310, E0311, E0803, Subdiagnostic, inline_fluent, + struct_span_code_err, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -25,7 +26,6 @@ use crate::errors::{ self, FulfillReqLifetime, LfBoundNotSatisfied, OutlivesBound, OutlivesContent, RefLongerThanData, RegionOriginNote, WhereClauseSuggestions, note_and_explain, }; -use crate::fluent_generated as fluent; use crate::infer::region_constraints::GenericKind; use crate::infer::{ BoundRegionConversionTime, InferCtxt, RegionResolutionError, RegionVariableOrigin, @@ -228,18 +228,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expected_found: self.values_str(trace.values, &trace.cause, err.long_ty_path()), } .add_to_diag(err), - SubregionOrigin::Reborrow(span) => { - RegionOriginNote::Plain { span, msg: fluent::trait_selection_reborrow } - .add_to_diag(err) + SubregionOrigin::Reborrow(span) => RegionOriginNote::Plain { + span, + msg: inline_fluent!("...so that reference does not outlive borrowed content"), } + .add_to_diag(err), SubregionOrigin::RelateObjectBound(span) => { - RegionOriginNote::Plain { span, msg: fluent::trait_selection_relate_object_bound } - .add_to_diag(err); + RegionOriginNote::Plain { + span, + msg: inline_fluent!("...so that it can be closed over into an object"), + } + .add_to_diag(err); } SubregionOrigin::ReferenceOutlivesReferent(ty, span) => { RegionOriginNote::WithName { span, - msg: fluent::trait_selection_reference_outlives_referent, + msg: inline_fluent!("...so that the reference type `{$name}` does not outlive the data it points at"), name: &self.ty_to_string(ty), continues: false, } @@ -248,7 +252,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateParamBound(span, ty, opt_span) => { RegionOriginNote::WithName { span, - msg: fluent::trait_selection_relate_param_bound, + msg: inline_fluent!("...so that the type `{$name}` will meet its required lifetime bounds{$continues -> +[true] ... +*[false] {\"\"} +}"), name: &self.ty_to_string(ty), continues: opt_span.is_some(), } @@ -256,7 +263,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(span) = opt_span { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_relate_param_bound_2, + msg: inline_fluent!("...that is required by this bound"), } .add_to_diag(err); } @@ -264,14 +271,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::RelateRegionParamBound(span, _) => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_relate_region_param_bound, + msg: inline_fluent!( + "...so that the declared lifetime parameter bounds are satisfied" + ), } .add_to_diag(err); } SubregionOrigin::CompareImplItemObligation { span, .. } => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_compare_impl_item_obligation, + msg: inline_fluent!( + "...so that the definition in impl matches the definition from the trait" + ), } .add_to_diag(err); } @@ -281,7 +292,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::AscribeUserTypeProvePredicate(span) => { RegionOriginNote::Plain { span, - msg: fluent::trait_selection_ascribe_user_type_prove_predicate, + msg: inline_fluent!("...so that the where clause holds"), } .add_to_diag(err); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 45e4f5fe23a6f..3cb3224302b6c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -12,7 +12,7 @@ use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, - pluralize, struct_span_code_err, + inline_fluent, pluralize, struct_span_code_err, }; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; @@ -3003,7 +3003,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { err.span_help( self.tcx.def_span(trait_def_id), - crate::fluent_generated::trait_selection_trait_has_no_impls, + inline_fluent!("this trait has no implementations, consider adding one"), ); } else if !suggested && trait_predicate.polarity() == ty::PredicatePolarity::Positive { // Can't show anything else useful, try to find similar impls. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 0a6af42e122b6..5eff7bba7c633 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -360,10 +360,10 @@ pub enum AppendConstMessage { } #[derive(LintDiagnostic)] -#[diag(trait_selection_malformed_on_unimplemented_attr)] -#[help] +#[diag("malformed `on_unimplemented` attribute")] +#[help("only `message`, `note` and `label` are allowed as options")] pub struct MalformedOnUnimplementedAttrLint { - #[label] + #[label("invalid option found here")] pub span: Span, } @@ -374,17 +374,17 @@ impl MalformedOnUnimplementedAttrLint { } #[derive(LintDiagnostic)] -#[diag(trait_selection_missing_options_for_on_unimplemented_attr)] -#[help] +#[diag("missing options for `on_unimplemented` attribute")] +#[help("at least one of the `message`, `note` and `label` options are expected")] pub struct MissingOptionsForOnUnimplementedAttr; #[derive(LintDiagnostic)] -#[diag(trait_selection_ignored_diagnostic_option)] +#[diag("`{$option_name}` is ignored due to previous definition of `{$option_name}`")] pub struct IgnoredDiagnosticOption { pub option_name: &'static str, - #[label] + #[label("`{$option_name}` is already declared here")] pub span: Span, - #[label(trait_selection_other_label)] + #[label("`{$option_name}` is first declared here")] pub prev_span: Span, } @@ -410,7 +410,7 @@ impl IgnoredDiagnosticOption { } #[derive(LintDiagnostic)] -#[diag(trait_selection_wrapped_parser_error)] +#[diag("{$description}")] pub struct WrappedParserError { pub description: String, pub label: String, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs index 1954f8a1f639f..8488d76e2c773 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented_format.rs @@ -310,25 +310,27 @@ pub mod errors { use super::*; #[derive(LintDiagnostic)] - #[diag(trait_selection_unknown_format_parameter_for_on_unimplemented_attr)] - #[help] + #[diag("there is no parameter `{$argument_name}` on trait `{$trait_name}`")] + #[help("expect either a generic argument name or {\"`{Self}`\"} as format argument")] pub struct UnknownFormatParameterForOnUnimplementedAttr { pub argument_name: Symbol, pub trait_name: Ident, } #[derive(LintDiagnostic)] - #[diag(trait_selection_disallowed_positional_argument)] - #[help] + #[diag("positional format arguments are not allowed here")] + #[help( + "only named format arguments with the name of one of the generic types are allowed in this context" + )] pub struct DisallowedPositionalArgument; #[derive(LintDiagnostic)] - #[diag(trait_selection_invalid_format_specifier)] - #[help] + #[diag("invalid format specifier")] + #[help("no format specifier are supported in this position")] pub struct InvalidFormatSpecifier; #[derive(LintDiagnostic)] - #[diag(trait_selection_missing_options_for_on_unimplemented_attr)] - #[help] + #[diag("missing options for `on_unimplemented` attribute")] + #[help("at least one of the `message`, `note` and `label` options are expected")] pub struct MissingOptionsForOnUnimplementedAttr; } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 22fa437ed5c7d..63fd61cb257b2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3583,11 +3583,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .. })) => { let mut spans = Vec::with_capacity(2); - if let Some(of_trait) = of_trait { + if let Some(of_trait) = of_trait + && !of_trait.trait_ref.path.span.in_derive_expansion() + { spans.push(of_trait.trait_ref.path.span); } spans.push(self_ty.span); let mut spans: MultiSpan = spans.into(); + let mut derived = false; if matches!( self_ty.span.ctxt().outer_expn_data().kind, ExpnKind::Macro(MacroKind::Derive, _) @@ -3595,9 +3598,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind), Some(ExpnKind::Macro(MacroKind::Derive, _)) ) { + derived = true; spans.push_span_label( data.span, - "unsatisfied trait bound introduced in this `derive` macro", + if data.span.in_derive_expansion() { + format!("type parameter would need to implement `{trait_name}`") + } else { + format!("unsatisfied trait bound") + }, ); } else if !data.span.is_dummy() && !data.span.overlaps(self_ty.span) { // `Sized` may be an explicit or implicit trait bound. If it is @@ -3623,6 +3631,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } err.span_note(spans, msg); + if derived && trait_name != "Copy" { + err.help(format!( + "consider manually implementing `{trait_name}` to avoid undesired \ + bounds", + )); + } point_at_assoc_type_restriction( tcx, err, diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index af241099c0149..e0690b8a6245d 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -3,7 +3,7 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, - EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, + EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, inline_fluent, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -17,12 +17,11 @@ use rustc_span::{BytePos, Ident, Span, Symbol, kw}; use crate::error_reporting::infer::ObligationCauseAsDiagArg; use crate::error_reporting::infer::need_type_info::UnderspecifiedArgKind; use crate::error_reporting::infer::nice_region_error::placeholder_error::Highlighted; -use crate::fluent_generated as fluent; pub mod note_and_explain; #[derive(Diagnostic)] -#[diag(trait_selection_unable_to_construct_constant_value)] +#[diag("unable to construct a constant value for the unevaluated constant {$unevaluated}")] pub struct UnableToConstructConstantValue<'a> { #[primary_span] pub span: Span, @@ -31,60 +30,64 @@ pub struct UnableToConstructConstantValue<'a> { #[derive(Diagnostic)] pub enum InvalidOnClause { - #[diag(trait_selection_rustc_on_unimplemented_empty_on_clause, code = E0232)] + #[diag("empty `on`-clause in `#[rustc_on_unimplemented]`", code = E0232)] Empty { #[primary_span] - #[label] + #[label("empty `on`-clause here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_expected_one_predicate_in_not, code = E0232)] + #[diag("expected a single predicate in `not(..)`", code = E0232)] ExpectedOnePredInNot { #[primary_span] - #[label] + #[label("unexpected quantity of predicates here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_unsupported_literal_in_on, code = E0232)] + #[diag("literals inside `on`-clauses are not supported", code = E0232)] UnsupportedLiteral { #[primary_span] - #[label] + #[label("unexpected literal here")] span: Span, }, - #[diag(trait_selection_rustc_on_unimplemented_expected_identifier, code = E0232)] + #[diag("expected an identifier inside this `on`-clause", code = E0232)] ExpectedIdentifier { #[primary_span] - #[label] + #[label("expected an identifier here, not `{$path}`")] span: Span, path: Path, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_predicate, code = E0232)] + #[diag("this predicate is invalid", code = E0232)] InvalidPredicate { #[primary_span] - #[label] + #[label("expected one of `any`, `all` or `not` here, not `{$invalid_pred}`")] span: Span, invalid_pred: Symbol, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_flag, code = E0232)] + #[diag("invalid flag in `on`-clause", code = E0232)] InvalidFlag { #[primary_span] - #[label] + #[label( + "expected one of the `crate_local`, `direct` or `from_desugaring` flags, not `{$invalid_flag}`" + )] span: Span, invalid_flag: Symbol, }, - #[diag(trait_selection_rustc_on_unimplemented_invalid_name, code = E0232)] + #[diag("invalid name in `on`-clause", code = E0232)] InvalidName { #[primary_span] - #[label] + #[label( + "expected one of `cause`, `from_desugaring`, `Self` or any generic parameter of the trait, not `{$invalid_name}`" + )] span: Span, invalid_name: Symbol, }, } #[derive(Diagnostic)] -#[diag(trait_selection_rustc_on_unimplemented_missing_value, code = E0232)] -#[note] +#[diag("this attribute must have a value", code = E0232)] +#[note("e.g. `#[rustc_on_unimplemented(message=\"foo\")]`")] pub struct NoValueInOnUnimplemented { #[primary_span] - #[label] + #[label("expected value here")] pub span: Span, } @@ -99,26 +102,33 @@ pub struct NegativePositiveConflict<'tcx> { impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { #[track_caller] fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { - let mut diag = Diag::new(dcx, level, fluent::trait_selection_negative_positive_conflict); + let mut diag = Diag::new(dcx, level, inline_fluent!("found both positive and negative implementation of trait `{$trait_desc}`{$self_desc -> +[none] {\"\"} +*[default] {\" \"}for type `{$self_desc}` +}:")); diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string()); diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string())); diag.span(self.impl_span); diag.code(E0751); match self.negative_impl_span { Ok(span) => { - diag.span_label(span, fluent::trait_selection_negative_implementation_here); + diag.span_label(span, inline_fluent!("negative implementation here")); } Err(cname) => { - diag.note(fluent::trait_selection_negative_implementation_in_crate); + diag.note(inline_fluent!( + "negative implementation in crate `{$negative_impl_cname}`" + )); diag.arg("negative_impl_cname", cname.to_string()); } } match self.positive_impl_span { Ok(span) => { - diag.span_label(span, fluent::trait_selection_positive_implementation_here); + diag.span_label(span, inline_fluent!("positive implementation here")); } Err(cname) => { - diag.note(fluent::trait_selection_positive_implementation_in_crate); + diag.note(inline_fluent!( + "positive implementation in crate `{$positive_impl_cname}`" + )); diag.arg("positive_impl_cname", cname.to_string()); } } @@ -127,7 +137,7 @@ impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { } #[derive(Diagnostic)] -#[diag(trait_selection_inherent_projection_normalization_overflow)] +#[diag("overflow evaluating associated type `{$ty}`")] pub struct InherentProjectionNormalizationOverflow { #[primary_span] pub span: Span, @@ -145,7 +155,12 @@ impl Subdiagnostic for AdjustSignatureBorrow { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("len", to_borrow.len()); diag.multipart_suggestion_verbose( - fluent::trait_selection_adjust_signature_borrow, + inline_fluent!( + "consider adjusting the signature so it borrows its {$len -> +[one] argument +*[other] arguments +}" + ), to_borrow, Applicability::MaybeIncorrect, ); @@ -153,7 +168,12 @@ impl Subdiagnostic for AdjustSignatureBorrow { AdjustSignatureBorrow::RemoveBorrow { remove_borrow } => { diag.arg("len", remove_borrow.len()); diag.multipart_suggestion_verbose( - fluent::trait_selection_adjust_signature_remove_borrow, + inline_fluent!( + "consider adjusting the signature so it does not borrow its {$len -> +[one] argument +*[other] arguments +}" + ), remove_borrow, Applicability::MaybeIncorrect, ); @@ -163,14 +183,14 @@ impl Subdiagnostic for AdjustSignatureBorrow { } #[derive(Diagnostic)] -#[diag(trait_selection_closure_kind_mismatch, code = E0525)] +#[diag("expected a closure that implements the `{$trait_prefix}{$expected}` trait, but this closure only implements `{$trait_prefix}{$found}`", code = E0525)] pub struct ClosureKindMismatch { #[primary_span] - #[label] + #[label("this closure implements `{$trait_prefix}{$found}`, not `{$trait_prefix}{$expected}`")] pub closure_span: Span, pub expected: ClosureKind, pub found: ClosureKind, - #[label(trait_selection_closure_kind_requirement)] + #[label("the requirement to implement `{$trait_prefix}{$expected}` derives from here")] pub cause_span: Span, pub trait_prefix: &'static str, @@ -183,7 +203,9 @@ pub struct ClosureKindMismatch { } #[derive(Subdiagnostic)] -#[label(trait_selection_closure_fn_once_label)] +#[label( + "closure is `{$trait_prefix}FnOnce` because it moves the variable `{$place}` out of its environment" +)] pub struct ClosureFnOnceLabel { #[primary_span] pub span: Span, @@ -191,7 +213,7 @@ pub struct ClosureFnOnceLabel { } #[derive(Subdiagnostic)] -#[label(trait_selection_closure_fn_mut_label)] +#[label("closure is `{$trait_prefix}FnMut` because it mutates the variable `{$place}` here")] pub struct ClosureFnMutLabel { #[primary_span] pub span: Span, @@ -199,7 +221,9 @@ pub struct ClosureFnMutLabel { } #[derive(Diagnostic)] -#[diag(trait_selection_coro_closure_not_fn)] +#[diag( + "{$coro_kind}closure does not implement `{$kind}` because it captures state from its environment" +)] pub(crate) struct CoroClosureNotFn { #[primary_span] pub span: Span, @@ -208,13 +232,17 @@ pub(crate) struct CoroClosureNotFn { } #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0282)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0282)] pub struct AnnotationRequired<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -226,13 +254,17 @@ pub struct AnnotationRequired<'a> { // Copy of `AnnotationRequired` for E0283 #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0283)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0283)] pub struct AmbiguousImpl<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -244,13 +276,17 @@ pub struct AmbiguousImpl<'a> { // Copy of `AnnotationRequired` for E0284 #[derive(Diagnostic)] -#[diag(trait_selection_type_annotations_needed, code = E0284)] +#[diag("{$source_kind -> +[closure] type annotations needed for the closure `{$source_name}` +[normal] type annotations needed for `{$source_name}` +*[other] type annotations needed +}", code = E0284)] pub struct AmbiguousReturn<'a> { #[primary_span] pub span: Span, pub source_kind: &'static str, pub source_name: &'a str, - #[label] + #[label("type must be known at this point")] pub failure_span: Option, #[subdiagnostic] pub bad_label: Option>, @@ -262,7 +298,19 @@ pub struct AmbiguousReturn<'a> { // Used when a better one isn't available #[derive(Subdiagnostic)] -#[label(trait_selection_label_bad)] +#[label( + "{$bad_kind -> +*[other] cannot infer type +[more_info] cannot infer {$prefix_kind -> +*[type] type for {$prefix} +[const_with_param] the value of const parameter +[const] the value of the constant +} `{$name}`{$has_parent -> +[true] {\" \"}declared on the {$parent_prefix} `{$parent_name}` +*[false] {\"\"} +} +}" +)] pub struct InferenceBadError<'a> { #[primary_span] pub span: Span, @@ -278,7 +326,19 @@ pub struct InferenceBadError<'a> { #[derive(Subdiagnostic)] pub enum SourceKindSubdiag<'a> { #[suggestion( - trait_selection_source_kind_subdiag_let, + "{$kind -> +[with_pattern] consider giving `{$name}` an explicit type +[closure] consider giving this closure parameter an explicit type +*[other] consider giving this pattern a type +}{$x_kind -> +[has_name] , where the {$prefix_kind -> +*[type] type for {$prefix} +[const_with_param] value of const parameter +[const] value of the constant +} `{$arg_name}` is specified +[underscore] , where the placeholders `_` are specified +*[empty] {\"\"} +}", style = "verbose", code = ": {type_name}", applicability = "has-placeholders" @@ -294,7 +354,18 @@ pub enum SourceKindSubdiag<'a> { prefix: &'a str, arg_name: String, }, - #[label(trait_selection_source_kind_subdiag_generic_label)] + #[label( + "cannot infer {$is_type -> +[true] type +*[false] the value +} of the {$is_type -> +[true] type +*[false] const +} {$parent_exists -> +[true] parameter `{$param_name}` declared on the {$parent_prefix} `{$parent_name}` +*[false] parameter {$param_name} +}" + )] GenericLabel { #[primary_span] span: Span, @@ -305,7 +376,10 @@ pub enum SourceKindSubdiag<'a> { parent_name: String, }, #[suggestion( - trait_selection_source_kind_subdiag_generic_suggestion, + "consider specifying the generic {$arg_count -> +[one] argument +*[other] arguments +}", style = "verbose", code = "::<{args}>", applicability = "has-placeholders" @@ -321,7 +395,7 @@ pub enum SourceKindSubdiag<'a> { #[derive(Subdiagnostic)] pub enum SourceKindMultiSuggestion<'a> { #[multipart_suggestion( - trait_selection_source_kind_fully_qualified, + "try using a fully qualified path to specify the expected types", style = "verbose", applicability = "has-placeholders" )] @@ -335,7 +409,7 @@ pub enum SourceKindMultiSuggestion<'a> { successor_pos: &'a str, }, #[multipart_suggestion( - trait_selection_source_kind_closure_return, + "try giving this closure an explicit return type", style = "verbose", applicability = "has-placeholders" )] @@ -427,7 +501,24 @@ impl Subdiagnostic for RegionOriginNote<'_> { requirement, expected_found: Some((expected, found)), } => { - label_or_note(span, fluent::trait_selection_subtype); + label_or_note( + span, + inline_fluent!( + "...so that the {$requirement -> +[method_compat] method type is compatible with trait +[type_compat] associated type is compatible with trait +[const_compat] const is compatible with trait +[expr_assignable] expression is assignable +[if_else_different] `if` and `else` have incompatible types +[no_else] `if` missing an `else` returns `()` +[fn_main_correct_type] `main` function has the correct type +[fn_lang_correct_type] lang item function has the correct type +[intrinsic_correct_type] intrinsic has the correct type +[method_correct_type] method receiver has the correct type +*[other] types are compatible +}" + ), + ); diag.arg("requirement", requirement); diag.note_expected_found("", expected, "", found); @@ -436,7 +527,24 @@ impl Subdiagnostic for RegionOriginNote<'_> { // FIXME: this really should be handled at some earlier stage. Our // handling of region checking when type errors are present is // *terrible*. - label_or_note(span, fluent::trait_selection_subtype_2); + label_or_note( + span, + inline_fluent!( + "...so that {$requirement -> +[method_compat] method type is compatible with trait +[type_compat] associated type is compatible with trait +[const_compat] const is compatible with trait +[expr_assignable] expression is assignable +[if_else_different] `if` and `else` have incompatible types +[no_else] `if` missing an `else` returns `()` +[fn_main_correct_type] `main` function has the correct type +[fn_lang_correct_type] lang item function has the correct type +[intrinsic_correct_type] intrinsic has the correct type +[method_correct_type] method receiver has the correct type +*[other] types are compatible +}" + ), + ); diag.arg("requirement", requirement); } }; @@ -464,9 +572,17 @@ impl Subdiagnostic for LifetimeMismatchLabels { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { - diag.span_label(param_span, fluent::trait_selection_declared_different); - diag.span_label(ret_span, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_returned); + diag.span_label(param_span, inline_fluent!("this parameter and the return type are declared with different lifetimes...")); + diag.span_label(ret_span, inline_fluent!("{\"\"}")); + diag.span_label( + span, + inline_fluent!( + "...but data{$label_var1_exists -> +[true] {\" \"}from `{$label_var1}` +*[false] {\"\"} +} is returned here" + ), + ); diag.arg("label_var1_exists", label_var1.is_some()); diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); } @@ -479,13 +595,33 @@ impl Subdiagnostic for LifetimeMismatchLabels { sub: label_var2, } => { if hir_equal { - diag.span_label(ty_sup, fluent::trait_selection_declared_multiple); - diag.span_label(ty_sub, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_lifetime_flow); + diag.span_label( + ty_sup, + inline_fluent!("this type is declared with multiple lifetimes..."), + ); + diag.span_label(ty_sub, inline_fluent!("{\"\"}")); + diag.span_label( + span, + inline_fluent!("...but data with one lifetime flows into the other here"), + ); } else { - diag.span_label(ty_sup, fluent::trait_selection_types_declared_different); - diag.span_label(ty_sub, fluent::trait_selection_nothing); - diag.span_label(span, fluent::trait_selection_data_flows); + diag.span_label( + ty_sup, + inline_fluent!("these two types are declared with different lifetimes..."), + ); + diag.span_label(ty_sub, inline_fluent!("{\"\"}")); + diag.span_label( + span, + inline_fluent!( + "...but data{$label_var1_exists -> +[true] {\" \"}from `{$label_var1}` +*[false] {\"\"} +} flows{$label_var2_exists -> +[true] {\" \"}into `{$label_var2}` +*[false] {\"\"} +} here" + ), + ); diag.arg("label_var1_exists", label_var1.is_some()); diag.arg("label_var1", label_var1.map(|x| x.to_string()).unwrap_or_default()); diag.arg("label_var2_exists", label_var2.is_some()); @@ -651,7 +787,15 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { visitor.suggestions.push(new_param_suggestion); } diag.multipart_suggestion_verbose( - fluent::trait_selection_lifetime_param_suggestion, + inline_fluent!( + "consider {$is_reuse -> +[true] reusing +*[false] introducing +} a named lifetime parameter{$is_impl -> +[true] {\" \"}and update trait if needed +*[false] {\"\"} +}" + ), visitor.suggestions, Applicability::MaybeIncorrect, ); @@ -661,13 +805,15 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { true }; if mk_suggestion() && self.add_note { - diag.note(fluent::trait_selection_lifetime_param_suggestion_elided); + diag.note(inline_fluent!( + "each elided lifetime in input position becomes a distinct lifetime" + )); } } } #[derive(Diagnostic)] -#[diag(trait_selection_lifetime_mismatch, code = E0623)] +#[diag("lifetime mismatch", code = E0623)] pub struct LifetimeMismatch<'a> { #[primary_span] pub span: Span, @@ -684,33 +830,42 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq { impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { - self.unmet_requirements - .push_span_label(self.binding_span, fluent::trait_selection_msl_introduces_static); - diag.span_note(self.unmet_requirements, fluent::trait_selection_msl_unmet_req); + self.unmet_requirements.push_span_label( + self.binding_span, + inline_fluent!("introduces a `'static` lifetime requirement"), + ); + diag.span_note( + self.unmet_requirements, + inline_fluent!("because this has an unmet lifetime requirement"), + ); } } // FIXME(#100717): replace with a `Option` when subdiagnostic supports that #[derive(Subdiagnostic)] pub enum DoesNotOutliveStaticFromImpl { - #[note(trait_selection_does_not_outlive_static_from_impl)] + #[note( + "...does not necessarily outlive the static lifetime introduced by the compatible `impl`" + )] Spanned { #[primary_span] span: Span, }, - #[note(trait_selection_does_not_outlive_static_from_impl)] + #[note( + "...does not necessarily outlive the static lifetime introduced by the compatible `impl`" + )] Unspanned, } #[derive(Subdiagnostic)] pub enum ImplicitStaticLifetimeSubdiag { - #[note(trait_selection_implicit_static_lifetime_note)] + #[note("this has an implicit `'static` lifetime requirement")] Note { #[primary_span] span: Span, }, #[suggestion( - trait_selection_implicit_static_lifetime_suggestion, + "consider relaxing the implicit `'static` requirement", style = "verbose", code = " + '_", applicability = "maybe-incorrect" @@ -722,7 +877,7 @@ pub enum ImplicitStaticLifetimeSubdiag { } #[derive(Diagnostic)] -#[diag(trait_selection_mismatched_static_lifetime)] +#[diag("incompatible lifetime on type")] pub struct MismatchedStaticLifetime<'a> { #[primary_span] pub cause_span: Span, @@ -738,15 +893,15 @@ pub struct MismatchedStaticLifetime<'a> { #[derive(Diagnostic)] pub enum ExplicitLifetimeRequired<'a> { - #[diag(trait_selection_explicit_lifetime_required_with_ident, code = E0621)] + #[diag("explicit lifetime required in the type of `{$simple_ident}`", code = E0621)] WithIdent { #[primary_span] - #[label] + #[label("lifetime `{$named}` required")] span: Span, simple_ident: Ident, named: String, #[suggestion( - trait_selection_explicit_lifetime_required_sugg_with_ident, + "add explicit lifetime `{$named}` to the type of `{$simple_ident}`", code = "{new_ty}", applicability = "unspecified", style = "verbose" @@ -755,14 +910,14 @@ pub enum ExplicitLifetimeRequired<'a> { #[skip_arg] new_ty: Ty<'a>, }, - #[diag(trait_selection_explicit_lifetime_required_with_param_type, code = E0621)] + #[diag("explicit lifetime required in parameter type", code = E0621)] WithParamType { #[primary_span] - #[label] + #[label("lifetime `{$named}` required")] span: Span, named: String, #[suggestion( - trait_selection_explicit_lifetime_required_sugg_with_param_type, + "add explicit lifetime `{$named}` to type", code = "{new_ty}", applicability = "unspecified", style = "verbose" @@ -789,7 +944,10 @@ impl IntoDiagArg for TyOrSig<'_> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes<'tcx> { - #[note(trait_selection_actual_impl_expl_expected_signature_two)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedSignatureTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -797,27 +955,41 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_any)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] ExpectedSignatureAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_some)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedSignatureSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_signature_nothing)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`" + )] ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_expected_passive_two)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedPassiveTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -825,27 +997,41 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_any)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...")] ExpectedPassiveAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_some)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...")] ExpectedPassiveSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_passive_nothing)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`" + )] ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_expected_other_two)] + #[note("{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] ExpectedOtherTwo { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, @@ -853,40 +1039,70 @@ pub enum ActualImplExplNotes<'tcx> { lifetime_1: usize, lifetime_2: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_any)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`..." + )] ExpectedOtherAny { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_some)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`..." + )] ExpectedOtherSome { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note(trait_selection_actual_impl_expl_expected_other_nothing)] + #[note( + "{$leading_ellipsis -> +[true] ... +*[false] {\"\"} +}`{$ty_or_sig}` must implement `{$trait_path}`" + )] ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note(trait_selection_actual_impl_expl_but_actually_implements_trait)] + #[note( + "...but it actually implements `{$trait_path}`{$has_lifetime -> +[true] , for some specific lifetime `'{$lifetime}` +*[false] {\"\"} +}" + )] ButActuallyImplementsTrait { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, }, - #[note(trait_selection_actual_impl_expl_but_actually_implemented_for_ty)] + #[note( + "...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> +[true] , for some specific lifetime `'{$lifetime}` +*[false] {\"\"} +}" + )] ButActuallyImplementedForTy { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, ty: String, }, - #[note(trait_selection_actual_impl_expl_but_actually_ty_implements)] + #[note( + "...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> +[true] , for some specific lifetime `'{$lifetime}` +*[false] {\"\"} +}" + )] ButActuallyTyImplements { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, @@ -978,15 +1194,15 @@ impl<'tcx> ActualImplExplNotes<'tcx> { } #[derive(Diagnostic)] -#[diag(trait_selection_trait_placeholder_mismatch)] +#[diag("implementation of `{$trait_def_id}` is not general enough")] pub struct TraitPlaceholderMismatch<'tcx> { #[primary_span] pub span: Span, - #[label(trait_selection_label_satisfy)] + #[label("doesn't satisfy where-clause")] pub satisfy_span: Option, - #[label(trait_selection_label_where)] + #[label("due to a where-clause on `{$def_id}`...")] pub where_span: Option, - #[label(trait_selection_label_dup)] + #[label("implementation of `{$trait_def_id}` is not general enough")] pub dup_span: Option, pub def_id: String, pub trait_def_id: String, @@ -1004,26 +1220,34 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required - type_param_span.push_span_label(span, fluent::trait_selection_tid_consider_borrowing); + type_param_span.push_span_label( + span, + inline_fluent!("consider borrowing this type parameter in the trait"), + ); } - let msg = diag.eagerly_translate(fluent::trait_selection_tid_param_help); + let msg = diag.eagerly_translate(inline_fluent!("the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`")); diag.span_help(type_param_span, msg); } } #[derive(Subdiagnostic)] -#[help(trait_selection_tid_rel_help)] +#[help( + "verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output" +)] pub struct RelationshipHelp; #[derive(Diagnostic)] -#[diag(trait_selection_trait_impl_diff)] +#[diag("`impl` item signature doesn't match `trait` item signature")] pub struct TraitImplDiff { #[primary_span] - #[label(trait_selection_found)] + #[label("found `{$found}`")] pub sp: Span, - #[label(trait_selection_expected)] + #[label("expected `{$expected}`")] pub trait_sp: Span, - #[note(trait_selection_expected_found)] + #[note( + "expected signature `{$expected}` + {\" \"}found signature `{$found}`" + )] pub note: (), #[subdiagnostic] pub param_help: ConsiderBorrowingParamHelp, @@ -1043,12 +1267,20 @@ pub struct DynTraitConstraintSuggestion { impl Subdiagnostic for DynTraitConstraintSuggestion { fn add_to_diag(self, diag: &mut Diag<'_, G>) { let mut multi_span: MultiSpan = vec![self.span].into(); - multi_span.push_span_label(self.span, fluent::trait_selection_dtcs_has_lifetime_req_label); - multi_span - .push_span_label(self.ident.span, fluent::trait_selection_dtcs_introduces_requirement); - let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_has_req_note); + multi_span.push_span_label( + self.span, + inline_fluent!("this has an implicit `'static` lifetime requirement"), + ); + multi_span.push_span_label( + self.ident.span, + inline_fluent!("calling this method introduces the `impl`'s `'static` requirement"), + ); + let msg = + diag.eagerly_translate(inline_fluent!("the used `impl` has a `'static` requirement")); diag.span_note(multi_span, msg); - let msg = diag.eagerly_translate(fluent::trait_selection_dtcs_suggestion); + let msg = diag.eagerly_translate(inline_fluent!( + "consider relaxing the implicit `'static` requirement" + )); diag.span_suggestion_verbose( self.span.shrink_to_hi(), msg, @@ -1059,12 +1291,26 @@ impl Subdiagnostic for DynTraitConstraintSuggestion { } #[derive(Diagnostic)] -#[diag(trait_selection_but_calling_introduces, code = E0772)] +#[diag("{$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$lifetime_kind -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` +} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement", code = E0772)] pub struct ButCallingIntroduces { - #[label(trait_selection_label1)] + #[label( + "{$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` + }" + )] pub param_ty_span: Span, #[primary_span] - #[label(trait_selection_label2)] + #[label("...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> + [true] `impl` of `{$impl_path}` + *[false] inherent `impl` + }")] pub cause_span: Span, pub has_param_name: bool, @@ -1087,32 +1333,61 @@ pub struct ReqIntroducedLocations { impl Subdiagnostic for ReqIntroducedLocations { fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { for sp in self.spans { - self.span.push_span_label(sp, fluent::trait_selection_ril_introduced_here); + self.span.push_span_label(sp, inline_fluent!("`'static` requirement introduced here")); } if self.add_label { - self.span.push_span_label(self.fn_decl_span, fluent::trait_selection_ril_introduced_by); + self.span.push_span_label( + self.fn_decl_span, + inline_fluent!("requirement introduced by this return type"), + ); } - self.span.push_span_label(self.cause_span, fluent::trait_selection_ril_because_of); - let msg = diag.eagerly_translate(fluent::trait_selection_ril_static_introduced_by); + self.span.push_span_label( + self.cause_span, + inline_fluent!("because of this returned expression"), + ); + let msg = diag.eagerly_translate(inline_fluent!( + "\"`'static` lifetime requirement introduced by the return type" + )); diag.span_note(self.span, msg); } } #[derive(Diagnostic)] -#[diag(trait_selection_but_needs_to_satisfy, code = E0759)] +#[diag("{$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` +} but it needs to satisfy a `'static` lifetime requirement", code = E0759)] pub struct ButNeedsToSatisfy { #[primary_span] pub sp: Span, - #[label(trait_selection_influencer)] + #[label( + "this data with {$has_lifetime -> + [true] lifetime `{$lifetime}` + *[false] an anonymous lifetime `'_` + }..." + )] pub influencer_point: Span, - #[label(trait_selection_used_here)] + #[label("...is used here...")] pub spans: Vec, - #[label(trait_selection_require)] + #[label( + "{$spans_empty -> + *[true] ...is used and required to live as long as `'static` here + [false] ...and is required to live as long as `'static` here + }" + )] pub require_span_as_label: Option, - #[note(trait_selection_require)] + #[note( + "{$spans_empty -> + *[true] ...is used and required to live as long as `'static` here + [false] ...and is required to live as long as `'static` here + }" + )] pub require_span_as_note: Option, - #[note(trait_selection_introduced_by_bound)] + #[note("`'static` lifetime requirement introduced by this bound")] pub bound: Option, pub has_param_name: bool, @@ -1123,7 +1398,7 @@ pub struct ButNeedsToSatisfy { } #[derive(Diagnostic)] -#[diag(trait_selection_outlives_content, code = E0312)] +#[diag("lifetime of reference outlives lifetime of borrowed content...", code = E0312)] pub struct OutlivesContent<'a> { #[primary_span] pub span: Span, @@ -1132,7 +1407,7 @@ pub struct OutlivesContent<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_outlives_bound, code = E0476)] +#[diag("lifetime of the source pointer does not outlive lifetime bound of the object type", code = E0476)] pub struct OutlivesBound<'a> { #[primary_span] pub span: Span, @@ -1141,7 +1416,7 @@ pub struct OutlivesBound<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_fulfill_req_lifetime, code = E0477)] +#[diag("the type `{$ty}` does not fulfill the required lifetime", code = E0477)] pub struct FulfillReqLifetime<'a> { #[primary_span] pub span: Span, @@ -1151,7 +1426,7 @@ pub struct FulfillReqLifetime<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_lf_bound_not_satisfied, code = E0478)] +#[diag("lifetime bound not satisfied", code = E0478)] pub struct LfBoundNotSatisfied<'a> { #[primary_span] pub span: Span, @@ -1160,7 +1435,7 @@ pub struct LfBoundNotSatisfied<'a> { } #[derive(Diagnostic)] -#[diag(trait_selection_ref_longer_than_data, code = E0491)] +#[diag("in type `{$ty}`, reference has a longer lifetime than the data it references", code = E0491)] pub struct RefLongerThanData<'a> { #[primary_span] pub span: Span, @@ -1172,7 +1447,7 @@ pub struct RefLongerThanData<'a> { #[derive(Subdiagnostic)] pub enum WhereClauseSuggestions { #[suggestion( - trait_selection_where_remove, + "remove the `where` clause", code = "", applicability = "machine-applicable", style = "verbose" @@ -1182,7 +1457,7 @@ pub enum WhereClauseSuggestions { span: Span, }, #[suggestion( - trait_selection_where_copy_predicates, + "copy the `where` clause predicates from the trait", code = "{space}where {trait_predicates}", applicability = "machine-applicable", style = "verbose" @@ -1198,7 +1473,7 @@ pub enum WhereClauseSuggestions { #[derive(Subdiagnostic)] pub enum SuggestRemoveSemiOrReturnBinding { #[multipart_suggestion( - trait_selection_srs_remove_and_box, + "consider removing this semicolon and boxing the expressions", applicability = "machine-applicable" )] RemoveAndBox { @@ -1214,7 +1489,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { sp: Span, }, #[suggestion( - trait_selection_srs_remove, + "consider removing this semicolon", style = "short", code = "", applicability = "machine-applicable" @@ -1224,7 +1499,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { sp: Span, }, #[suggestion( - trait_selection_srs_add, + "consider returning the local binding `{$ident}`", style = "verbose", code = "{code}", applicability = "maybe-incorrect" @@ -1235,7 +1510,7 @@ pub enum SuggestRemoveSemiOrReturnBinding { code: String, ident: Ident, }, - #[note(trait_selection_srs_add_one)] + #[note("consider returning one of these bindings")] AddOne { #[primary_span] spans: MultiSpan, @@ -1244,9 +1519,12 @@ pub enum SuggestRemoveSemiOrReturnBinding { #[derive(Subdiagnostic)] pub enum ConsiderAddingAwait { - #[help(trait_selection_await_both_futures)] + #[help("consider `await`ing on both `Future`s")] BothFuturesHelp, - #[multipart_suggestion(trait_selection_await_both_futures, applicability = "maybe-incorrect")] + #[multipart_suggestion( + "consider `await`ing on both `Future`s", + applicability = "maybe-incorrect" + )] BothFuturesSugg { #[suggestion_part(code = ".await")] first: Span, @@ -1254,7 +1532,7 @@ pub enum ConsiderAddingAwait { second: Span, }, #[suggestion( - trait_selection_await_future, + "consider `await`ing on the `Future`", code = ".await", style = "verbose", applicability = "maybe-incorrect" @@ -1263,13 +1541,13 @@ pub enum ConsiderAddingAwait { #[primary_span] span: Span, }, - #[note(trait_selection_await_note)] + #[note("calling an async function returns a future")] FutureSuggNote { #[primary_span] span: Span, }, #[multipart_suggestion( - trait_selection_await_future, + "consider `await`ing on the `Future`", style = "verbose", applicability = "maybe-incorrect" )] @@ -1281,69 +1559,79 @@ pub enum ConsiderAddingAwait { #[derive(Diagnostic)] pub enum PlaceholderRelationLfNotSatisfied { - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasBoth { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_with_sub)] + #[note("the lifetime `{$sub_symbol}` defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_with_sup)] + #[note("...must outlive the lifetime `{$sup_symbol}` defined here")] sup_span: Span, sub_symbol: Symbol, sup_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasSub { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_with_sub)] + #[note("the lifetime `{$sub_symbol}` defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_without_sup)] + #[note("...must outlive the lifetime defined here")] sup_span: Span, sub_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasSup { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_without_sub)] + #[note("the lifetime defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_with_sup)] + #[note("...must outlive the lifetime `{$sup_symbol}` defined here")] sup_span: Span, sup_symbol: Symbol, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] HasNone { #[primary_span] span: Span, - #[note(trait_selection_prlf_defined_without_sub)] + #[note("the lifetime defined here...")] sub_span: Span, - #[note(trait_selection_prlf_must_outlive_without_sup)] + #[note("...must outlive the lifetime defined here")] sup_span: Span, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, - #[diag(trait_selection_lf_bound_not_satisfied)] + #[diag("lifetime bound not satisfied")] OnlyPrimarySpan { #[primary_span] span: Span, - #[note(trait_selection_prlf_known_limitation)] + #[note( + "this is a known limitation that will be removed in the future (see issue #100013 for more information)" + )] note: (), }, } #[derive(Diagnostic)] -#[diag(trait_selection_opaque_captures_lifetime, code = E0700)] +#[diag("hidden type for `{$opaque_ty}` captures lifetime that does not appear in bounds", code = E0700)] pub struct OpaqueCapturesLifetime<'tcx> { #[primary_span] pub span: Span, - #[label] + #[label("opaque type defined here")] pub opaque_ty_span: Span, pub opaque_ty: Ty<'tcx>, } @@ -1351,7 +1639,7 @@ pub struct OpaqueCapturesLifetime<'tcx> { #[derive(Subdiagnostic)] pub enum FunctionPointerSuggestion<'a> { #[suggestion( - trait_selection_fps_use_ref, + "consider using a reference", code = "&", style = "verbose", applicability = "maybe-incorrect" @@ -1361,7 +1649,7 @@ pub enum FunctionPointerSuggestion<'a> { span: Span, }, #[suggestion( - trait_selection_fps_remove_ref, + "consider removing the reference", code = "{fn_name}", style = "verbose", applicability = "maybe-incorrect" @@ -1373,7 +1661,7 @@ pub enum FunctionPointerSuggestion<'a> { fn_name: String, }, #[suggestion( - trait_selection_fps_cast, + "consider casting to a fn pointer", code = "&({fn_name} as {sig})", style = "verbose", applicability = "maybe-incorrect" @@ -1387,7 +1675,7 @@ pub enum FunctionPointerSuggestion<'a> { sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast, + "consider casting to a fn pointer", code = " as {sig}", style = "verbose", applicability = "maybe-incorrect" @@ -1399,7 +1687,7 @@ pub enum FunctionPointerSuggestion<'a> { sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast_both, + "consider casting both fn items to fn pointers using `as {$expected_sig}`", code = " as {found_sig}", style = "hidden", applicability = "maybe-incorrect" @@ -1412,7 +1700,7 @@ pub enum FunctionPointerSuggestion<'a> { expected_sig: Binder<'a, FnSig<'a>>, }, #[suggestion( - trait_selection_fps_cast_both, + "consider casting both fn items to fn pointers using `as {$expected_sig}`", code = "&({fn_name} as {found_sig})", style = "hidden", applicability = "maybe-incorrect" @@ -1429,21 +1717,21 @@ pub enum FunctionPointerSuggestion<'a> { } #[derive(Subdiagnostic)] -#[note(trait_selection_fps_items_are_distinct)] +#[note("fn items are distinct from fn pointers")] pub struct FnItemsAreDistinct; #[derive(Subdiagnostic)] -#[note(trait_selection_fn_uniq_types)] +#[note("different fn items have unique types, even if their signatures are the same")] pub struct FnUniqTypes; #[derive(Subdiagnostic)] -#[help(trait_selection_fn_consider_casting)] +#[help("consider casting the fn item to a fn pointer: `{$casting}`")] pub struct FnConsiderCasting { pub casting: String, } #[derive(Subdiagnostic)] -#[help(trait_selection_fn_consider_casting_both)] +#[help("consider casting both fn items to fn pointers using `as {$sig}`")] pub struct FnConsiderCastingBoth<'a> { pub sig: Binder<'a, FnSig<'a>>, } @@ -1451,7 +1739,7 @@ pub struct FnConsiderCastingBoth<'a> { #[derive(Subdiagnostic)] pub enum SuggestAccessingField<'a> { #[suggestion( - trait_selection_suggest_accessing_field, + "you might have meant to use field `{$name}` whose type is `{$ty}`", code = "{snippet}.{name}", applicability = "maybe-incorrect", style = "verbose" @@ -1464,7 +1752,7 @@ pub enum SuggestAccessingField<'a> { ty: Ty<'a>, }, #[suggestion( - trait_selection_suggest_accessing_field, + "you might have meant to use field `{$name}` whose type is `{$ty}`", code = "unsafe {{ {snippet}.{name} }}", applicability = "maybe-incorrect", style = "verbose" @@ -1479,7 +1767,10 @@ pub enum SuggestAccessingField<'a> { } #[derive(Subdiagnostic)] -#[multipart_suggestion(trait_selection_stp_wrap_one, applicability = "maybe-incorrect")] +#[multipart_suggestion( + "try wrapping the pattern in `{$variant}`", + applicability = "maybe-incorrect" +)] pub struct SuggestTuplePatternOne { pub variant: String, #[suggestion_part(code = "{variant}(")] @@ -1497,7 +1788,9 @@ pub struct SuggestTuplePatternMany { impl Subdiagnostic for SuggestTuplePatternMany { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("path", self.path); - let message = diag.eagerly_translate(fluent::trait_selection_stp_wrap_many); + let message = diag.eagerly_translate(inline_fluent!( + "try wrapping the pattern in a variant of `{$path}`" + )); diag.multipart_suggestions( message, self.compatible_variants.into_iter().map(|variant| { @@ -1514,7 +1807,7 @@ impl Subdiagnostic for SuggestTuplePatternMany { #[derive(Subdiagnostic)] pub enum TypeErrorAdditionalDiags { #[suggestion( - trait_selection_meant_byte_literal, + "if you meant to write a byte literal, prefix with `b`", code = "b'{code}'", applicability = "machine-applicable" )] @@ -1524,7 +1817,7 @@ pub enum TypeErrorAdditionalDiags { code: String, }, #[suggestion( - trait_selection_meant_char_literal, + "if you meant to write a `char` literal, use single quotes", code = "'{code}'", applicability = "machine-applicable" )] @@ -1533,7 +1826,10 @@ pub enum TypeErrorAdditionalDiags { span: Span, code: String, }, - #[multipart_suggestion(trait_selection_meant_str_literal, applicability = "machine-applicable")] + #[multipart_suggestion( + "if you meant to write a string literal, use double quotes", + applicability = "machine-applicable" + )] MeantStrLiteral { #[suggestion_part(code = "\"")] start: Span, @@ -1541,7 +1837,7 @@ pub enum TypeErrorAdditionalDiags { end: Span, }, #[suggestion( - trait_selection_consider_specifying_length, + "consider specifying the actual array length", code = "{length}", applicability = "maybe-incorrect" )] @@ -1550,10 +1846,10 @@ pub enum TypeErrorAdditionalDiags { span: Span, length: u64, }, - #[note(trait_selection_try_cannot_convert)] + #[note("`?` operator cannot convert from `{$found}` to `{$expected}`")] TryCannotConvert { found: String, expected: String }, #[suggestion( - trait_selection_tuple_trailing_comma, + "use a trailing comma to create a tuple with one element", code = ",", applicability = "machine-applicable" )] @@ -1562,7 +1858,7 @@ pub enum TypeErrorAdditionalDiags { span: Span, }, #[multipart_suggestion( - trait_selection_tuple_trailing_comma, + "use a trailing comma to create a tuple with one element", applicability = "machine-applicable" )] TupleAlsoParentheses { @@ -1572,7 +1868,7 @@ pub enum TypeErrorAdditionalDiags { span_high: Span, }, #[suggestion( - trait_selection_suggest_add_let_for_letchains, + "consider adding `let`", style = "verbose", applicability = "machine-applicable", code = "let " @@ -1585,66 +1881,69 @@ pub enum TypeErrorAdditionalDiags { #[derive(Diagnostic)] pub enum ObligationCauseFailureCode { - #[diag(trait_selection_oc_method_compat, code = E0308)] + #[diag("method not compatible with trait", code = E0308)] MethodCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_type_compat, code = E0308)] + #[diag("type not compatible with trait", code = E0308)] TypeCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_const_compat, code = E0308)] + #[diag("const not compatible with trait", code = E0308)] ConstCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_try_compat, code = E0308)] + #[diag("`?` operator has incompatible types", code = E0308)] TryCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_match_compat, code = E0308)] + #[diag("`match` arms have incompatible types", code = E0308)] MatchCompat { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_if_else_different, code = E0308)] + #[diag("`if` and `else` have incompatible types", code = E0308)] IfElseDifferent { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_no_else, code = E0317)] + #[diag("`if` may be missing an `else` clause", code = E0317)] NoElse { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_no_diverge, code = E0308)] + #[diag("`else` clause of `let...else` does not diverge", code = E0308)] NoDiverge { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_fn_main_correct_type, code = E0580)] + #[diag("`main` function has wrong type", code = E0580)] FnMainCorrectType { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_fn_lang_correct_type, code = E0308)] + #[diag("{$lang_item_name -> +[panic_impl] `#[panic_handler]` +*[lang_item_name] lang item `{$lang_item_name}` +} function has wrong type", code = E0308)] FnLangCorrectType { #[primary_span] span: Span, @@ -1652,40 +1951,40 @@ pub enum ObligationCauseFailureCode { subdiags: Vec, lang_item_name: Symbol, }, - #[diag(trait_selection_oc_intrinsic_correct_type, code = E0308)] + #[diag("intrinsic has wrong type", code = E0308)] IntrinsicCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_method_correct_type, code = E0308)] + #[diag("mismatched `self` parameter type", code = E0308)] MethodCorrectType { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_closure_selfref, code = E0644)] + #[diag("closure/coroutine type that references itself", code = E0644)] ClosureSelfref { #[primary_span] span: Span, }, - #[diag(trait_selection_oc_cant_coerce_force_inline, code = E0308)] + #[diag("cannot coerce functions which must be inlined to function pointers", code = E0308)] CantCoerceForceInline { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_cant_coerce_intrinsic, code = E0308)] + #[diag("cannot coerce intrinsics to function pointers", code = E0308)] CantCoerceIntrinsic { #[primary_span] span: Span, #[subdiagnostic] subdiags: Vec, }, - #[diag(trait_selection_oc_generic, code = E0308)] + #[diag("mismatched types", code = E0308)] Generic { #[primary_span] span: Span, @@ -1697,7 +1996,7 @@ pub enum ObligationCauseFailureCode { #[derive(Subdiagnostic)] pub enum AddPreciseCapturing { #[suggestion( - trait_selection_precise_capturing_new, + "add a `use<...>` bound to explicitly capture `{$new_lifetime}`", style = "verbose", code = " + use<{concatenated_bounds}>", applicability = "machine-applicable" @@ -1709,7 +2008,7 @@ pub enum AddPreciseCapturing { concatenated_bounds: String, }, #[suggestion( - trait_selection_precise_capturing_existing, + "add `{$new_lifetime}` to the `use<...>` bound to explicitly capture it", style = "verbose", code = "{pre}{new_lifetime}{post}", applicability = "machine-applicable" @@ -1733,13 +2032,13 @@ impl Subdiagnostic for AddPreciseCapturingAndParams { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("new_lifetime", self.new_lifetime); diag.multipart_suggestion_verbose( - fluent::trait_selection_precise_capturing_new_but_apit, + inline_fluent!("add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate"), self.suggs, Applicability::MaybeIncorrect, ); diag.span_note( self.apit_spans, - fluent::trait_selection_warn_removing_apit_params_for_undercapture, + inline_fluent!("you could use a `use<...>` bound to explicitly capture `{$new_lifetime}`, but argument-position `impl Trait`s are not nameable"), ); } } @@ -1880,26 +2179,31 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture { Applicability::MaybeIncorrect }; diag.multipart_suggestion_verbose( - fluent::trait_selection_precise_capturing_overcaptures, + inline_fluent!( + "use the precise capturing `use<...>` syntax to make the captures explicit" + ), self.suggs, applicability, ); if !self.apit_spans.is_empty() { diag.span_note( self.apit_spans, - fluent::trait_selection_warn_removing_apit_params_for_overcapture, + inline_fluent!("you could use a `use<...>` bound to explicitly specify captures, but argument-position `impl Trait`s are not nameable"), ); } } } #[derive(Diagnostic)] -#[diag(trait_selection_opaque_type_non_generic_param, code = E0792)] +#[diag("expected generic {$kind} parameter, found `{$arg}`", code = E0792)] pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { pub arg: GenericArg<'tcx>, pub kind: &'a str, #[primary_span] pub span: Span, - #[label] + #[label("{STREQ($arg, \"'static\") -> + [true] cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type + *[other] this generic parameter must be used with a generic {$kind} parameter + }")] pub param_span: Span, } diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index 3471036256db7..8e86b8fae1577 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -1,11 +1,10 @@ -use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic}; +use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic, inline_fluent}; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{Span, kw}; use crate::error_reporting::infer::nice_region_error::find_anon_type; -use crate::fluent_generated as fluent; struct DescriptionCtx<'a> { span: Option, @@ -170,7 +169,40 @@ impl Subdiagnostic for RegionExplanation<'_> { diag.arg("desc_kind", self.desc.kind); diag.arg("desc_arg", self.desc.arg); - let msg = diag.eagerly_translate(fluent::trait_selection_region_explanation); + let msg = diag.eagerly_translate(inline_fluent!( + "{$pref_kind -> +*[should_not_happen] [{$pref_kind}] +[ref_valid_for] ...the reference is valid for +[content_valid_for] ...but the borrowed content is only valid for +[type_obj_valid_for] object type is valid for +[source_pointer_valid_for] source pointer is only valid for +[type_satisfy] type must satisfy +[type_outlive] type must outlive +[lf_param_instantiated_with] lifetime parameter instantiated with +[lf_param_must_outlive] but lifetime parameter must outlive +[lf_instantiated_with] lifetime instantiated with +[lf_must_outlive] but lifetime must outlive +[pointer_valid_for] the pointer is valid for +[data_valid_for] but the referenced data is only valid for +[empty] {\"\"} +}{$pref_kind -> +[empty] {\"\"} +*[other] {\" \"} +}{$desc_kind -> +*[should_not_happen] [{$desc_kind}] +[restatic] the static lifetime +[revar] lifetime {$desc_arg} +[as_defined] the lifetime `{$desc_arg}` as defined here +[as_defined_anon] the anonymous lifetime as defined here +[defined_here] the anonymous lifetime defined here +[defined_here_reg] the lifetime `{$desc_arg}` as defined here +}{$suff_kind -> +*[should_not_happen] [{$suff_kind}] +[empty]{\"\"} +[continues] ... +[req_by_binding] {\" \"}as required by this binding +}" + )); diag.restore_args(); if let Some(span) = self.desc.span { diag.span_note(span, msg); diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 561a95bad50c3..645fd17ac7096 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -34,5 +34,3 @@ pub mod opaque_types; pub mod regions; pub mod solve; pub mod traits; - -rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 9371b55b63633..512973e452870 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -7,10 +7,9 @@ use std::ops::ControlFlow; use rustc_errors::FatalError; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, LangItem, find_attr}; +use rustc_hir::{self as hir, LangItem}; use rustc_middle::query::Providers; use rustc_middle::ty::{ self, EarlyBinder, GenericArgs, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, @@ -333,7 +332,7 @@ pub fn dyn_compatibility_violations_for_assoc_item( if tcx.features().min_generic_const_args() { if !tcx.generics_of(item.def_id).is_own_empty() { errors.push(AssocConstViolation::Generic); - } else if !find_attr!(tcx.get_all_attrs(item.def_id), AttributeKind::TypeConst(_)) { + } else if !tcx.is_type_const(item.def_id) { errors.push(AssocConstViolation::NonType); } diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index f33196bab6470..2fd3a6e738cfe 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -13,7 +13,7 @@ use crate::traits::{self, FulfillmentError, Obligation, ObligationCause}; pub enum CopyImplementationError<'tcx> { InfringingFields(Vec<(&'tcx ty::FieldDef, Ty<'tcx>, InfringingFieldsReason<'tcx>)>), NotAnAdt, - HasDestructor, + HasDestructor(hir::def_id::DefId), HasUnsafeFields, } @@ -76,8 +76,8 @@ pub fn type_allowed_to_implement_copy<'tcx>( ) .map_err(CopyImplementationError::InfringingFields)?; - if adt.has_dtor(tcx) { - return Err(CopyImplementationError::HasDestructor); + if let Some(did) = adt.destructor(tcx).map(|dtor| dtor.did) { + return Err(CopyImplementationError::HasDestructor(did)); } if impl_safety.is_safe() && self_type.has_unsafe_fields() { diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 24854990fe716..46d95fdfabfed 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -1,6 +1,7 @@ //! Deeply normalize types using the old trait solver. use rustc_data_structures::stack::ensure_sufficient_stack; +use rustc_errors::inline_fluent; use rustc_hir::def::DefKind; use rustc_infer::infer::at::At; use rustc_infer::infer::{InferCtxt, InferOk}; @@ -294,7 +295,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { self.cause.span, false, |diag| { - diag.note(crate::fluent_generated::trait_selection_ty_alias_overflow); + diag.note(inline_fluent!("in case this is a recursive type alias, consider using a struct, enum, or union instead")); }, ); } diff --git a/tests/ui/asm/x86_64/global_asm_escape.rs b/tests/ui/asm/x86_64/global_asm_escape.rs new file mode 100644 index 0000000000000..59214e958a85b --- /dev/null +++ b/tests/ui/asm/x86_64/global_asm_escape.rs @@ -0,0 +1,17 @@ +//@ run-pass +//@ only-x86_64-unknown-linux-gnu +//@ ignore-backends: gcc + +// https://github.com/rust-lang/rust/issues/151950 + +unsafe extern "C" { + #[link_name = "exit@GLIBC_2.2.5"] + safe fn exit(status: i32) -> !; + safe fn my_exit(status: i32) -> !; +} + +core::arch::global_asm!(".global my_exit", "my_exit:", "jmp {}", sym exit); + +fn main() { + my_exit(0); +} diff --git a/tests/ui/asm/x86_64/naked_asm_escape.rs b/tests/ui/asm/x86_64/naked_asm_escape.rs new file mode 100644 index 0000000000000..57962993ef91f --- /dev/null +++ b/tests/ui/asm/x86_64/naked_asm_escape.rs @@ -0,0 +1,32 @@ +//@ build-fail +//@ only-x86_64-unknown-linux-gnu +//@ dont-check-compiler-stderr +//@ dont-check-compiler-stdout +//@ ignore-backends: gcc + +// https://github.com/rust-lang/rust/issues/151950 + +unsafe extern "C" { + #[link_name = "memset]; mov eax, 1; #"] + unsafe fn inject(); +} + +#[unsafe(export_name = "memset]; mov eax, 1; #")] +extern "C" fn inject_() {} + +#[unsafe(naked)] +extern "C" fn print_0() -> usize { + core::arch::naked_asm!("lea rax, [{}]", "ret", sym inject) +} + +#[unsafe(naked)] +extern "C" fn print_1() -> usize { + core::arch::naked_asm!("lea rax, [{}]", "ret", sym inject_) +} + +fn main() { + dbg!(print_0()); + dbg!(print_1()); +} + +//~? ERROR linking diff --git a/tests/ui/associated-types/issue-38821.rs b/tests/ui/associated-types/issue-38821.rs index 5212bc886f0df..35c371235e640 100644 --- a/tests/ui/associated-types/issue-38821.rs +++ b/tests/ui/associated-types/issue-38821.rs @@ -34,11 +34,11 @@ pub trait Column: Expression {} //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied +pub enum ColumnInsertValue where +//~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -pub enum ColumnInsertValue where -//~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied Col: Column, Expr: Expression::Nullable>, //~^ ERROR the trait bound `::SqlType: IntoNullable` is not satisfied diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 01329f69c3bef..07b146f8bfca4 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:40:1 + --> $DIR/issue-38821.rs:37:1 | LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` @@ -82,10 +82,13 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:10 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -95,13 +98,17 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Debug` - --> $DIR/issue-38821.rs:23:10 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ----- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ unsatisfied trait bound + = help: consider manually implementing `Debug` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, @@ -126,10 +133,13 @@ LL | Expr: Expression::Nullable>, ::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:17 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ---- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -139,13 +149,16 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Copy` - --> $DIR/issue-38821.rs:23:17 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ unsatisfied trait bound help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, @@ -199,10 +212,13 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:23 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -212,13 +228,17 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Clone` - --> $DIR/issue-38821.rs:23:23 + --> $DIR/issue-38821.rs:37:10 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ----- in this derive macro expansion +... +LL | pub enum ColumnInsertValue where + | ^^^^^^^^^^^^^^^^^ ... LL | Expr: Expression::Nullable>, - | ------------------------------------------------ unsatisfied trait bound introduced in this `derive` macro + | ------------------------------------------------ unsatisfied trait bound + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting the associated type | LL | Expr: Expression::Nullable>, ::SqlType: NotNull, diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr index d3765a7e6e6fd..327ac40503ac0 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -18,7 +18,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn foo(&self) -> Pin + '_>> { -LL + fn foo(&self) -> impl Future { +LL + fn foo(&self) -> impl std::future::Future { | warning: 1 warning emitted diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr index 3328dea37fe4d..983c946d2a70d 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -18,7 +18,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn foo(&self) -> MyFuture { -LL + fn foo(&self) -> impl Future { +LL + fn foo(&self) -> impl std::future::Future { | warning: 1 warning emitted diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.rs b/tests/ui/borrowck/derive-clone-implicit-bound.rs new file mode 100644 index 0000000000000..cd92ac1e9e598 --- /dev/null +++ b/tests/ui/borrowck/derive-clone-implicit-bound.rs @@ -0,0 +1,32 @@ +// Issue #108894 + +use std::marker::PhantomData; + +#[derive(Clone, Copy)] //~ NOTE: derived `Clone` adds implicit bounds on type parameters +pub struct TypedAddress{ +//~^ NOTE: if all bounds were met, you could clone the value +//~| NOTE: introduces an implicit `T: Clone` bound + inner: u64, + phantom: PhantomData, +} + +pub trait Memory { + fn write_value(&self, offset: TypedAddress, value: &T); + fn return_value(&self, offset: TypedAddress) -> T; + //~^ NOTE: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + //~| NOTE: in this method + //~| NOTE: this parameter takes ownership of the value + fn update_value(&self, offset: TypedAddress, update: F) + //~^ NOTE: move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait + where F: FnOnce(T) -> T //~ HELP: consider further restricting type parameter `T` + { + let old = self.return_value(offset); //~ NOTE: value moved here + //~^ NOTE: you could clone this value + let new = update(old); + self.write_value(offset, &new); //~ ERROR: use of moved value: `offset` + //~^ NOTE: value used here after move + //~| HELP: consider manually implementing `Clone` to avoid undesired bounds + } +} + +fn main() {} diff --git a/tests/ui/borrowck/derive-clone-implicit-bound.stderr b/tests/ui/borrowck/derive-clone-implicit-bound.stderr new file mode 100644 index 0000000000000..246fd1eaf0752 --- /dev/null +++ b/tests/ui/borrowck/derive-clone-implicit-bound.stderr @@ -0,0 +1,38 @@ +error[E0382]: use of moved value: `offset` + --> $DIR/derive-clone-implicit-bound.rs:26:26 + | +LL | fn update_value(&self, offset: TypedAddress, update: F) + | ------ move occurs because `offset` has type `TypedAddress`, which does not implement the `Copy` trait +... +LL | let old = self.return_value(offset); + | ------ value moved here +... +LL | self.write_value(offset, &new); + | ^^^^^^ value used here after move + | +note: consider changing this parameter type in method `return_value` to borrow instead if owning the value isn't necessary + --> $DIR/derive-clone-implicit-bound.rs:15:39 + | +LL | fn return_value(&self, offset: TypedAddress) -> T; + | ------------ in this method ^^^^^^^^^^^^^^^ this parameter takes ownership of the value +note: if all bounds were met, you could clone the value + --> $DIR/derive-clone-implicit-bound.rs:6:1 + | +LL | #[derive(Clone, Copy)] + | ----- derived `Clone` adds implicit bounds on type parameters +LL | pub struct TypedAddress{ + | ^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | + | introduces an implicit `T: Clone` bound +... +LL | let old = self.return_value(offset); + | ------ you could clone this value + = help: consider manually implementing `Clone` to avoid undesired bounds +help: consider further restricting type parameter `T` with trait `Copy` + | +LL | where F: FnOnce(T) -> T, T: Copy + | +++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. diff --git a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs index 3326af7486c5e..863bcedd01e6d 100644 --- a/tests/ui/closures/closure-move-use-after-move-diagnostic.rs +++ b/tests/ui/closures/closure-move-use-after-move-diagnostic.rs @@ -1,16 +1,16 @@ //! regression test for -struct NoCopy; //~ NOTE if `NoCopy` implemented `Clone`, you could clone the value -//~^ NOTE consider implementing `Clone` for this type +struct NoCopy; //~ NOTE: if `NoCopy` implemented `Clone`, you could clone the value +//~^ NOTE: consider implementing `Clone` for this type fn main() { let x = NoCopy; - //~^ NOTE move occurs because `x` has type `NoCopy` + //~^ NOTE: move occurs because `x` has type `NoCopy` let f = move || { - //~^ NOTE value moved into closure here + //~^ NOTE: value moved into closure here let y = x; - //~^ NOTE variable moved due to use in closure - //~| NOTE you could clone this value + //~^ NOTE: variable moved due to use in closure + //~| NOTE: you could clone this value }; let z = x; - //~^ ERROR use of moved value: `x` - //~| NOTE value used here after move + //~^ ERROR: use of moved value: `x` + //~| NOTE: value used here after move } diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs index 0614ea97b1add..1900931b3f35e 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.rs @@ -8,10 +8,10 @@ struct NotParam; struct CantParam(NotParam); impl std::marker::ConstParamTy_ for CantParam {} -//~^ error: the trait `ConstParamTy_` cannot be implemented for this type +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(std::marker::ConstParamTy, Eq, PartialEq)] -//~^ error: the trait `ConstParamTy_` cannot be implemented for this type struct CantParamDerive(NotParam); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr index fd1836802c4ae..084c64d273355 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_bad_field.stderr @@ -8,13 +8,12 @@ LL | impl std::marker::ConstParamTy_ for CantParam {} | ^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/const_param_ty_impl_bad_field.rs:13:10 + --> $DIR/const_param_ty_impl_bad_field.rs:14:8 | LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | + | ------------------------- in this derive macro expansion LL | struct CantParamDerive(NotParam); - | -------- this field does not implement `ConstParamTy_` + | ^^^^^^^^^^^^^^^ -------- this field does not implement `ConstParamTy_` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs index a1c8eccfb095f..a8f190609c043 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.rs @@ -8,13 +8,13 @@ impl std::marker::ConstParamTy_ for ImplementsConstParamTy {} struct CantParam(ImplementsConstParamTy); impl std::marker::ConstParamTy_ for CantParam {} -//~^ error: the type `CantParam` does not `#[derive(PartialEq)]` -//~| ERROR the trait bound `CantParam: Eq` is not satisfied +//~^ ERROR: the type `CantParam` does not `#[derive(PartialEq)]` +//~| ERROR: the trait bound `CantParam: Eq` is not satisfied #[derive(std::marker::ConstParamTy)] -//~^ error: the type `CantParamDerive` does not `#[derive(PartialEq)]` -//~| ERROR the trait bound `CantParamDerive: Eq` is not satisfied struct CantParamDerive(ImplementsConstParamTy); +//~^ ERROR: the type `CantParamDerive` does not `#[derive(PartialEq)]` +//~| ERROR: the trait bound `CantParamDerive: Eq` is not satisfied fn check() {} diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr index ca2a693d48ceb..1219d5f04380a 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_impl_no_structural_eq.stderr @@ -27,10 +27,12 @@ note: required by a bound in `ConstParamTy_` --> $SRC_DIR/core/src/marker.rs:LL:COL error[E0277]: the trait bound `CantParamDerive: Eq` is not satisfied - --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:8 | LL | #[derive(std::marker::ConstParamTy)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive` + | ------------------------- in this derive macro expansion +LL | struct CantParamDerive(ImplementsConstParamTy); + | ^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `CantParamDerive` | note: required by a bound in `ConstParamTy_` --> $SRC_DIR/core/src/marker.rs:LL:COL @@ -41,13 +43,15 @@ LL | struct CantParamDerive(ImplementsConstParamTy); | error[E0277]: the type `CantParamDerive` does not `#[derive(PartialEq)]` - --> $DIR/const_param_ty_impl_no_structural_eq.rs:14:10 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:8 | LL | #[derive(std::marker::ConstParamTy)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound + | ------------------------- in this derive macro expansion +LL | struct CantParamDerive(ImplementsConstParamTy); + | ^^^^^^^^^^^^^^^ unsatisfied trait bound | help: the nightly-only, unstable trait `StructuralPartialEq` is not implemented for `CantParamDerive` - --> $DIR/const_param_ty_impl_no_structural_eq.rs:17:1 + --> $DIR/const_param_ty_impl_no_structural_eq.rs:15:1 | LL | struct CantParamDerive(ImplementsConstParamTy); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs index d42ef90e1b180..e8a16be2197b2 100644 --- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs +++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.rs @@ -4,15 +4,15 @@ use std::marker::ConstParamTy; #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo([*const u8; 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo2([*mut u8; 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty #[derive(ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty struct Foo3([fn(); 1]); +//~^ ERROR the trait `ConstParamTy_` cannot be implemented for this ty fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr index 442ec6b96cefa..6c8a506d1f40a 100644 --- a/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr +++ b/tests/ui/const-generics/adt_const_params/nested_bad_const_param_ty.stderr @@ -1,44 +1,41 @@ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:6:10 + --> $DIR/nested_bad_const_param_ty.rs:7:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo([*const u8; 1]); - | -------------- this field does not implement `ConstParamTy_` + | ^^^ -------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[*const u8; 1]` requires that `*const u8: ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:8:12 + --> $DIR/nested_bad_const_param_ty.rs:7:12 | LL | struct Foo([*const u8; 1]); | ^^^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:10:10 + --> $DIR/nested_bad_const_param_ty.rs:11:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo2([*mut u8; 1]); - | ------------ this field does not implement `ConstParamTy_` + | ^^^^ ------------ this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[*mut u8; 1]` requires that `*mut u8: ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:12:13 + --> $DIR/nested_bad_const_param_ty.rs:11:13 | LL | struct Foo2([*mut u8; 1]); | ^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/nested_bad_const_param_ty.rs:14:10 + --> $DIR/nested_bad_const_param_ty.rs:15:8 | LL | #[derive(ConstParamTy)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct Foo3([fn(); 1]); - | --------- this field does not implement `ConstParamTy_` + | ^^^^ --------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[fn(); 1]` requires that `fn(): ConstParamTy_` - --> $DIR/nested_bad_const_param_ty.rs:16:13 + --> $DIR/nested_bad_const_param_ty.rs:15:13 | LL | struct Foo3([fn(); 1]); | ^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs index 5db031cb900fc..f2d972612dc64 100644 --- a/tests/ui/const-generics/adt_const_params/unsized_field-1.rs +++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.rs @@ -6,18 +6,18 @@ extern crate unsized_const_param; use std::marker::ConstParamTy; #[derive(ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct A([u8]); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct B(&'static [u8]); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type #[derive(ConstParamTy, Eq, PartialEq)] struct C(unsized_const_param::Foo); #[derive(std::marker::ConstParamTy, Eq, PartialEq)] -//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); +//~^ ERROR: the trait `ConstParamTy_` cannot be implemented for this type fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr index 134dbba0d63ab..2538b811618bb 100644 --- a/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr +++ b/tests/ui/const-generics/adt_const_params/unsized_field-1.stderr @@ -1,44 +1,41 @@ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:8:10 + --> $DIR/unsized_field-1.rs:9:8 | LL | #[derive(ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct A([u8]); - | ---- this field does not implement `ConstParamTy_` + | ^ ---- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `[u8]` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:10:10 + --> $DIR/unsized_field-1.rs:9:10 | LL | struct A([u8]); | ^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:12:10 + --> $DIR/unsized_field-1.rs:13:8 | LL | #[derive(ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^ -LL | + | ------------ in this derive macro expansion LL | struct B(&'static [u8]); - | ------------- this field does not implement `ConstParamTy_` + | ^ ------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `&'static [u8]` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:14:10 + --> $DIR/unsized_field-1.rs:13:10 | LL | struct B(&'static [u8]); | ^^^^^^^^^^^^^ error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsized_field-1.rs:19:10 + --> $DIR/unsized_field-1.rs:20:8 | LL | #[derive(std::marker::ConstParamTy, Eq, PartialEq)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | + | ------------------------- in this derive macro expansion LL | struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); - | ---------------------------------------------------------- this field does not implement `ConstParamTy_` + | ^ ---------------------------------------------------------- this field does not implement `ConstParamTy_` | note: the `ConstParamTy_` impl for `GenericNotUnsizedParam<&'static [u8]>` requires that `feature(unsized_const_params) is enabled` - --> $DIR/unsized_field-1.rs:21:10 + --> $DIR/unsized_field-1.rs:20:10 | LL | struct D(unsized_const_param::GenericNotUnsizedParam<&'static [u8]>); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs index 500e8e22b0e3d..71ac662cf580e 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.rs @@ -6,8 +6,8 @@ use std::marker::ConstParamTy; #[derive(Debug, PartialEq, Eq, ConstParamTy)] -//~^ ERROR the trait `ConstParamTy_` struct Foo { +//~^ ERROR the trait `ConstParamTy_` nested: &'static Bar, //~^ ERROR the size for values //~| ERROR the size for values diff --git a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr index aecd97ef7763c..f520413927c36 100644 --- a/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr +++ b/tests/ui/const-generics/adt_const_params/unsizing-wfcheck-issue-126272.stderr @@ -19,11 +19,13 @@ LL | struct Bar(T); | this could be changed to `T: ?Sized`... error[E0204]: the trait `ConstParamTy_` cannot be implemented for this type - --> $DIR/unsizing-wfcheck-issue-126272.rs:8:32 + --> $DIR/unsizing-wfcheck-issue-126272.rs:9:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^^^^^^^^ -... + | ------------ in this derive macro expansion +LL | struct Foo { + | ^^^ +LL | LL | nested: &'static Bar, | ----------------------------------------- this field does not implement `ConstParamTy_` | @@ -59,12 +61,13 @@ help: the trait `Debug` is implemented for `Bar` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^^^^ note: required for `Bar<(dyn Debug + 'static)>` to implement `Debug` - --> $DIR/unsizing-wfcheck-issue-126272.rs:19:10 + --> $DIR/unsizing-wfcheck-issue-126272.rs:20:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^^^^ + | ----- in this derive macro expansion LL | struct Bar(T); - | - unsatisfied trait bound introduced in this `derive` macro + | ^^^ - unsatisfied trait bound + = help: consider manually implementing `Debug` to avoid undesired bounds = note: 2 redundant requirements hidden = note: required for `&&'static Bar<(dyn Debug + 'static)>` to implement `Debug` = note: required for the cast from `&&&'static Bar<(dyn Debug + 'static)>` to `&dyn Debug` @@ -93,10 +96,13 @@ help: the trait `Eq` is implemented for `Bar` LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] | ^^ note: required for `Bar` to implement `Eq` - --> $DIR/unsizing-wfcheck-issue-126272.rs:19:28 + --> $DIR/unsizing-wfcheck-issue-126272.rs:20:8 | LL | #[derive(Debug, PartialEq, Eq, ConstParamTy)] - | ^^ unsatisfied trait bound introduced in this `derive` macro + | -- in this derive macro expansion +LL | struct Bar(T); + | ^^^ - type parameter would need to implement `Eq` + = help: consider manually implementing `Eq` to avoid undesired bounds = note: 1 redundant requirement hidden = note: required for `&'static Bar` to implement `Eq` note: required by a bound in `std::cmp::AssertParamIsEq` diff --git a/tests/ui/consts/const-blocks/trait-error.stderr b/tests/ui/consts/const-blocks/trait-error.stderr index 601d067e3d849..308d71f0f4bd6 100644 --- a/tests/ui/consts/const-blocks/trait-error.stderr +++ b/tests/ui/consts/const-blocks/trait-error.stderr @@ -5,10 +5,12 @@ LL | [Foo(String::new()); 4]; | ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` | note: required for `Foo` to implement `Copy` - --> $DIR/trait-error.rs:1:10 + --> $DIR/trait-error.rs:2:8 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ---- in this derive macro expansion +LL | struct Foo(T); + | ^^^ - type parameter would need to implement `Copy` = note: the `Copy` trait is required because this value will be copied for each element of the array help: create an inline `const` block | diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.rs b/tests/ui/derives/copy-drop-mutually-exclusive.rs index 5147605910d7b..64cd5bf594b01 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.rs +++ b/tests/ui/derives/copy-drop-mutually-exclusive.rs @@ -1,14 +1,14 @@ //! Regression test for issue #20126: Copy and Drop traits are mutually exclusive -#[derive(Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented -struct Foo; +#[derive(Copy, Clone)] +struct Foo; //~ ERROR the trait `Copy` cannot be implemented impl Drop for Foo { fn drop(&mut self) {} } -#[derive(Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented -struct Bar(::std::marker::PhantomData); +#[derive(Copy, Clone)] +struct Bar(::std::marker::PhantomData); //~ ERROR the trait `Copy` cannot be implemented impl Drop for Bar { fn drop(&mut self) {} diff --git a/tests/ui/derives/copy-drop-mutually-exclusive.stderr b/tests/ui/derives/copy-drop-mutually-exclusive.stderr index 771bbc9256958..ab2d086c7f5fc 100644 --- a/tests/ui/derives/copy-drop-mutually-exclusive.stderr +++ b/tests/ui/derives/copy-drop-mutually-exclusive.stderr @@ -1,14 +1,30 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/copy-drop-mutually-exclusive.rs:3:10 + --> $DIR/copy-drop-mutually-exclusive.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Foo; + | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/copy-drop-mutually-exclusive.rs:7:5 + | +LL | fn drop(&mut self) {} + | ^^^^^^^^^^^^^^^^^^ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/copy-drop-mutually-exclusive.rs:10:10 + --> $DIR/copy-drop-mutually-exclusive.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Bar(::std::marker::PhantomData); + | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/copy-drop-mutually-exclusive.rs:14:5 + | +LL | fn drop(&mut self) {} + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr index 13ba80243a5eb..ca968910fde43 100644 --- a/tests/ui/derives/derive-assoc-type-not-impl.stderr +++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr @@ -11,10 +11,13 @@ LL | Bar:: { x: 1 }.clone(); | ^^^^^ method cannot be called on `Bar` due to unsatisfied trait bounds | note: trait bound `NotClone: Clone` was not satisfied - --> $DIR/derive-assoc-type-not-impl.rs:6:10 + --> $DIR/derive-assoc-type-not-impl.rs:7:12 | LL | #[derive(Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | struct Bar { + | ^ type parameter would need to implement `Clone` + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NotClone` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/derives/deriving-copyclone.stderr b/tests/ui/derives/deriving-copyclone.stderr index befff8802804e..20a73ffdcfbfe 100644 --- a/tests/ui/derives/deriving-copyclone.stderr +++ b/tests/ui/derives/deriving-copyclone.stderr @@ -7,10 +7,12 @@ LL | is_copy(B { a: 1, b: C }); | required by a bound introduced by this call | note: required for `B` to implement `Copy` - --> $DIR/deriving-copyclone.rs:9:10 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ---- in this derive macro expansion +LL | struct B { + | ^ - type parameter would need to implement `Copy` note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | @@ -30,10 +32,13 @@ LL | is_clone(B { a: 1, b: C }); | required by a bound introduced by this call | note: required for `B` to implement `Clone` - --> $DIR/deriving-copyclone.rs:9:16 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | struct B { + | ^ - type parameter would need to implement `Clone` + = help: consider manually implementing `Clone` to avoid undesired bounds note: required by a bound in `is_clone` --> $DIR/deriving-copyclone.rs:19:16 | @@ -53,10 +58,12 @@ LL | is_copy(B { a: 1, b: D }); | required by a bound introduced by this call | note: required for `B` to implement `Copy` - --> $DIR/deriving-copyclone.rs:9:10 + --> $DIR/deriving-copyclone.rs:10:8 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ---- in this derive macro expansion +LL | struct B { + | ^ - type parameter would need to implement `Copy` note: required by a bound in `is_copy` --> $DIR/deriving-copyclone.rs:18:15 | diff --git a/tests/ui/derives/deriving-with-repr-packed-2.stderr b/tests/ui/derives/deriving-with-repr-packed-2.stderr index b62c67d9a9da1..6bd3fff39790a 100644 --- a/tests/ui/derives/deriving-with-repr-packed-2.stderr +++ b/tests/ui/derives/deriving-with-repr-packed-2.stderr @@ -21,10 +21,14 @@ LL | let x: Foo = Foo(NonCopy, NonCopy, NonCopy); note: the following trait bounds were not satisfied: `NonCopy: Clone` `NonCopy: Copy` - --> $DIR/deriving-with-repr-packed-2.rs:5:16 + --> $DIR/deriving-with-repr-packed-2.rs:7:16 | LL | #[derive(Copy, Clone, Default, PartialEq, Eq)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | #[repr(packed)] +LL | pub struct Foo(T, T, T); + | ^ type parameter would need to implement `Clone` + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `NonCopy` with `#[derive(Clone, Copy)]` | LL + #[derive(Clone, Copy)] diff --git a/tests/ui/derives/issue-97343.stderr b/tests/ui/derives/issue-97343.stderr index 27691f5718849..c033a3d227c12 100644 --- a/tests/ui/derives/issue-97343.stderr +++ b/tests/ui/derives/issue-97343.stderr @@ -2,12 +2,11 @@ error[E0109]: type arguments are not allowed on type parameter `Irrelevant` --> $DIR/issue-97343.rs:4:23 | LL | #[derive(Debug)] - | ----- - | | - | not allowed on type parameter `Irrelevant` - | in this derive macro expansion + | ----- in this derive macro expansion LL | pub struct Irrelevant { - | ^^^^^^^^^^ type argument not allowed + | ---------- ^^^^^^^^^^ type argument not allowed + | | + | not allowed on type parameter `Irrelevant` | note: type parameter `Irrelevant` defined here --> $DIR/issue-97343.rs:4:23 diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs index 8e5cd4248f149..f4193f18352d0 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs @@ -3,12 +3,12 @@ struct NonGeneric {} #[derive(Default)] -//~^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied -//~^^ ERROR struct takes 0 lifetime arguments but 1 lifetime argument was supplied -//~^^^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied -//~^^^^ ERROR struct takes 0 generic arguments but 1 generic argument was supplied +//~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied +//~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied struct NonGeneric<'a, const N: usize> {} -//~^ ERROR lifetime parameter `'a` is never used -//~^^ ERROR the name `NonGeneric` is defined multiple times +//~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied +//~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied +//~| ERROR: lifetime parameter `'a` is never used +//~| ERROR: the name `NonGeneric` is defined multiple times pub fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr index cf9c0d0ad3bee..0d6aaaf5186d3 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `NonGeneric` is defined multiple times - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:10:1 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:1 | LL | struct NonGeneric {} | ----------------- previous definition of the type `NonGeneric` here @@ -37,7 +37,7 @@ LL | struct NonGeneric {} | ^^^^^^^^^^ error[E0392]: lifetime parameter `'a` is never used - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:10:19 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:19 | LL | struct NonGeneric<'a, const N: usize> {} | ^^ unused lifetime parameter @@ -45,29 +45,26 @@ LL | struct NonGeneric<'a, const N: usize> {} = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:8 | -LL | #[derive(Default)] - | ^^^^^^^ expected 0 lifetime arguments -... LL | struct NonGeneric<'a, const N: usize> {} - | -- help: remove the lifetime argument + | ^^^^^^^^^^ -- help: remove the lifetime argument + | | + | expected 0 lifetime arguments | note: struct defined here, with 0 lifetime parameters --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 | LL | struct NonGeneric {} | ^^^^^^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:8 | -LL | #[derive(Default)] - | ^^^^^^^ expected 0 generic arguments -... LL | struct NonGeneric<'a, const N: usize> {} - | - help: remove the unnecessary generic argument + | ^^^^^^^^^^ - help: remove the unnecessary generic argument + | | + | expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs index f3bf299aa65f4..e946c0c5350ed 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs @@ -8,12 +8,12 @@ struct NotSM; #[derive(PartialEq, Eq)] -//~^ ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments -//~| ERROR struct takes 0 generic arguments +//~^ ERROR: struct takes 0 generic arguments struct NotSM(T); -//~^ ERROR the name `NotSM` is defined multiple times -//~| ERROR no field `0` +//~^ ERROR: struct takes 0 generic arguments +//~| ERROR: struct takes 0 generic arguments +//~| ERROR: struct takes 0 generic arguments +//~| ERROR: the name `NotSM` is defined multiple times +//~| ERROR: no field `0` fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr index 32c3cf4403169..e80cf35d81e1d 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `NotSM` is defined multiple times - --> $DIR/multiple-types-with-same-name-and-derive.rs:15:1 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:1 | LL | struct NotSM; | ------------- previous definition of the type `NotSM` here @@ -10,10 +10,10 @@ LL | struct NotSM(T); = note: `NotSM` must be defined only once in the type namespace of this module error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ expected 0 generic arguments +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 @@ -32,25 +32,25 @@ note: struct defined here, with 0 generic parameters | LL | struct NotSM; | ^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:21 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 | -LL | #[derive(PartialEq, Eq)] - | ^^ expected 0 generic arguments +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 | LL | struct NotSM; | ^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ expected 0 generic arguments +LL | struct NotSM(T); + | ^^^^^ expected 0 generic arguments | note: struct defined here, with 0 generic parameters --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 @@ -60,7 +60,7 @@ LL | struct NotSM; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0609]: no field `0` on type `&NotSM` - --> $DIR/multiple-types-with-same-name-and-derive.rs:15:17 + --> $DIR/multiple-types-with-same-name-and-derive.rs:12:17 | LL | struct NotSM(T); | ^ unknown field diff --git a/tests/ui/error-codes/E0184.rs b/tests/ui/error-codes/E0184.rs index 0c448e4ad8bcf..64cc1f0d15382 100644 --- a/tests/ui/error-codes/E0184.rs +++ b/tests/ui/error-codes/E0184.rs @@ -1,5 +1,5 @@ -#[derive(Copy)] //~ ERROR E0184 -struct Foo; +#[derive(Copy)] +struct Foo; //~ ERROR E0184 impl Drop for Foo { fn drop(&mut self) { diff --git a/tests/ui/error-codes/E0184.stderr b/tests/ui/error-codes/E0184.stderr index 1a7df9ac095ad..13294959bc3cf 100644 --- a/tests/ui/error-codes/E0184.stderr +++ b/tests/ui/error-codes/E0184.stderr @@ -1,8 +1,16 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has a destructor - --> $DIR/E0184.rs:1:10 + --> $DIR/E0184.rs:2:8 | LL | #[derive(Copy)] - | ^^^^ `Copy` not allowed on types with destructors + | ---- in this derive macro expansion +LL | struct Foo; + | ^^^ `Copy` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/E0184.rs:5:5 + | +LL | fn drop(&mut self) { + | ^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/impl_bounds.stderr b/tests/ui/generic-associated-types/impl_bounds.stderr index 7847bbd813cd5..65e1dff479e54 100644 --- a/tests/ui/generic-associated-types/impl_bounds.stderr +++ b/tests/ui/generic-associated-types/impl_bounds.stderr @@ -29,10 +29,12 @@ LL | type C = String where Self: Copy; | ^^^^ the trait `Copy` is not implemented for `T` | note: required for `Fooy` to implement `Copy` - --> $DIR/impl_bounds.rs:10:10 + --> $DIR/impl_bounds.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ---- in this derive macro expansion +LL | struct Fooy(T); + | ^^^^ - type parameter would need to implement `Copy` note: the requirement `Fooy: Copy` appears on the `impl`'s associated type `C` but not on the corresponding trait's associated type --> $DIR/impl_bounds.rs:6:10 | @@ -53,10 +55,12 @@ LL | fn d() where Self: Copy {} | ^^^^ the trait `Copy` is not implemented for `T` | note: required for `Fooy` to implement `Copy` - --> $DIR/impl_bounds.rs:10:10 + --> $DIR/impl_bounds.rs:11:8 | LL | #[derive(Copy, Clone)] - | ^^^^ unsatisfied trait bound introduced in this `derive` macro + | ---- in this derive macro expansion +LL | struct Fooy(T); + | ^^^^ - type parameter would need to implement `Copy` note: the requirement `Fooy: Copy` appears on the `impl`'s associated function `d` but not on the corresponding trait's associated function --> $DIR/impl_bounds.rs:7:8 | diff --git a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr index 8bc3c8b647c08..29975bdfcce8c 100644 --- a/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr +++ b/tests/ui/impl-trait/in-trait/bad-item-bound-within-rpitit.stderr @@ -29,7 +29,7 @@ LL | fn iter(&self) -> impl 'a + Iterator> { help: replace the return type so that it matches the trait | LL - fn iter(&self) -> impl 'a + Iterator> { -LL + fn iter(&self) -> impl Iterator::Item<'_>> + '_ { +LL + fn iter(&self) -> impl std::iter::Iterator::Item<'_>> + '_ { | error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr b/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr index 0a73a36378601..f44b34e38cfd6 100644 --- a/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr +++ b/tests/ui/impl-trait/in-trait/expeced-refree-to-map-to-reearlybound-ice-108580.stderr @@ -12,8 +12,9 @@ LL | fn bar(&self) -> impl Iterator + '_ { = note: `#[warn(refining_impl_trait_internal)]` (part of `#[warn(refining_impl_trait)]`) on by default help: replace the return type so that it matches the trait | -LL | fn bar(&self) -> impl Iterator + '_ { - | +++++++++++++++++++ +LL - fn bar(&self) -> impl Iterator + '_ { +LL + fn bar(&self) -> impl std::iter::Iterator + '_ { + | warning: 1 warning emitted diff --git a/tests/ui/impl-trait/in-trait/foreign.stderr b/tests/ui/impl-trait/in-trait/foreign.stderr index 8801ccc68b3be..f1c76f743c6e2 100644 --- a/tests/ui/impl-trait/in-trait/foreign.stderr +++ b/tests/ui/impl-trait/in-trait/foreign.stderr @@ -15,7 +15,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn bar(self) -> Arc { -LL + fn bar(self) -> impl Deref { +LL + fn bar(self) -> impl std::ops::Deref { | warning: impl trait in impl method signature does not match trait method signature @@ -34,7 +34,7 @@ LL | #[warn(refining_impl_trait)] help: replace the return type so that it matches the trait | LL - fn bar(self) -> Arc { -LL + fn bar(self) -> impl Deref { +LL + fn bar(self) -> impl std::ops::Deref { | warning: 2 warnings emitted diff --git a/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs b/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs new file mode 100644 index 0000000000000..281f4c73ac21a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-return-type-notation.rs @@ -0,0 +1,13 @@ +#![feature(return_type_notation)] +#![deny(refining_impl_trait)] + +trait Trait { + fn f() -> impl Sized; +} + +impl Trait for () { + fn f() {} + //~^ ERROR impl trait in impl method signature does not match trait method signature +} + +fn main() {} diff --git a/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr b/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr new file mode 100644 index 0000000000000..1f9a5b9e87492 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/refine-return-type-notation.stderr @@ -0,0 +1,24 @@ +error: impl trait in impl method signature does not match trait method signature + --> $DIR/refine-return-type-notation.rs:9:5 + | +LL | fn f() -> impl Sized; + | ---------- return type from trait method defined here +... +LL | fn f() {} + | ^^^^^^ + | + = note: add `#[allow(refining_impl_trait)]` if it is intended for this to be part of the public API of this crate + = note: we are soliciting feedback, see issue #121718 for more information +note: the lint level is defined here + --> $DIR/refine-return-type-notation.rs:2:9 + | +LL | #![deny(refining_impl_trait)] + | ^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(refining_impl_trait_internal)]` implied by `#[deny(refining_impl_trait)]` +help: replace the return type so that it matches the trait + | +LL | fn f()-> impl Sized {} + | +++++++++++++ + +error: aborting due to 1 previous error + diff --git a/tests/ui/issues/issue-27340.rs b/tests/ui/issues/issue-27340.rs index 53ca2bc973ff8..9966c24a7441e 100644 --- a/tests/ui/issues/issue-27340.rs +++ b/tests/ui/issues/issue-27340.rs @@ -1,7 +1,7 @@ struct Foo; #[derive(Copy, Clone)] -//~^ ERROR the trait `Copy` cannot be implemented for this type struct Bar(Foo); -//~^ ERROR `Foo: Clone` is not satisfied +//~^ ERROR: the trait `Copy` cannot be implemented for this type +//~| ERROR: `Foo: Clone` is not satisfied fn main() {} diff --git a/tests/ui/issues/issue-27340.stderr b/tests/ui/issues/issue-27340.stderr index 7cde901ffd95a..3b4ad58b1f080 100644 --- a/tests/ui/issues/issue-27340.stderr +++ b/tests/ui/issues/issue-27340.stderr @@ -1,18 +1,16 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-27340.rs:2:10 + --> $DIR/issue-27340.rs:3:8 | LL | #[derive(Copy, Clone)] - | ^^^^ -LL | + | ---- in this derive macro expansion LL | struct Bar(Foo); - | --- this field does not implement `Copy` + | ^^^ --- this field does not implement `Copy` error[E0277]: the trait bound `Foo: Clone` is not satisfied - --> $DIR/issue-27340.rs:4:12 + --> $DIR/issue-27340.rs:3:12 | LL | #[derive(Copy, Clone)] | ----- in this derive macro expansion -LL | LL | struct Bar(Foo); | ^^^ the trait `Clone` is not implemented for `Foo` | diff --git a/tests/ui/malformed/malformed-derive-entry.rs b/tests/ui/malformed/malformed-derive-entry.rs index 77fa2f566a8fc..f9dc98d9d270f 100644 --- a/tests/ui/malformed/malformed-derive-entry.rs +++ b/tests/ui/malformed/malformed-derive-entry.rs @@ -1,14 +1,14 @@ #[derive(Copy(Bad))] -//~^ ERROR traits in `#[derive(...)]` don't accept arguments -//~| ERROR the trait bound +//~^ ERROR: traits in `#[derive(...)]` don't accept arguments struct Test1; +//~^ ERROR: the trait bound #[derive(Copy="bad")] -//~^ ERROR traits in `#[derive(...)]` don't accept values -//~| ERROR the trait bound +//~^ ERROR: traits in `#[derive(...)]` don't accept values struct Test2; +//~^ ERROR: the trait bound -#[derive] //~ ERROR malformed `derive` attribute input +#[derive] //~ ERROR: malformed `derive` attribute input struct Test4; fn main() {} diff --git a/tests/ui/malformed/malformed-derive-entry.stderr b/tests/ui/malformed/malformed-derive-entry.stderr index 02036e8d4c90b..a5d7c3a4f8aaa 100644 --- a/tests/ui/malformed/malformed-derive-entry.stderr +++ b/tests/ui/malformed/malformed-derive-entry.stderr @@ -17,10 +17,13 @@ LL | #[derive] | ^^^^^^^^^ help: must be of the form: `#[derive(Trait1, Trait2, ...)]` error[E0277]: the trait bound `Test1: Clone` is not satisfied - --> $DIR/malformed-derive-entry.rs:1:10 + --> $DIR/malformed-derive-entry.rs:3:8 | LL | #[derive(Copy(Bad))] - | ^^^^ the trait `Clone` is not implemented for `Test1` + | ---- in this derive macro expansion +LL | +LL | struct Test1; + | ^^^^^ the trait `Clone` is not implemented for `Test1` | note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL @@ -31,10 +34,13 @@ LL | struct Test1; | error[E0277]: the trait bound `Test2: Clone` is not satisfied - --> $DIR/malformed-derive-entry.rs:6:10 + --> $DIR/malformed-derive-entry.rs:8:8 | LL | #[derive(Copy="bad")] - | ^^^^ the trait `Clone` is not implemented for `Test2` + | ---- in this derive macro expansion +LL | +LL | struct Test2; + | ^^^^^ the trait `Clone` is not implemented for `Test2` | note: required by a bound in `Copy` --> $SRC_DIR/core/src/marker.rs:LL:COL diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr index 301f3c3a458de..5de99cc6ca6ae 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr @@ -13,7 +13,8 @@ note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned i | LL | let mut x: HashSet = v.clone(); | ^ - = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied +help: `Clone` is not implemented because a trait bound is not satisfied + --> $SRC_DIR/std/src/collections/hash/set.rs:LL:COL help: consider annotating `Day` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr index 301f3c3a458de..5de99cc6ca6ae 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr @@ -13,7 +13,8 @@ note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned i | LL | let mut x: HashSet = v.clone(); | ^ - = help: `Clone` is not implemented because the trait bound `Day: Clone` is not satisfied +help: `Clone` is not implemented because a trait bound is not satisfied + --> $SRC_DIR/std/src/collections/hash/set.rs:LL:COL help: consider annotating `Day` with `#[derive(Clone)]` | LL + #[derive(Clone)] diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.rs b/tests/ui/moves/issue-72649-uninit-in-loop.rs index 8f2e01bdf1aba..f115656d7c0dd 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.rs +++ b/tests/ui/moves/issue-72649-uninit-in-loop.rs @@ -70,6 +70,7 @@ fn moved_loop_2() { fn uninit_1() { loop { let value: NonCopy; //~ NOTE declared here + //~^ HELP consider assigning a value let _used = value; //~ ERROR binding `value` isn't initialized //~^ NOTE `value` used here but it isn't initialized } @@ -77,6 +78,7 @@ fn uninit_1() { fn uninit_2() { let mut value: NonCopy; //~ NOTE declared here + //~^ HELP consider assigning a value loop { let _used = value; //~ ERROR binding `value` isn't initialized //~^ NOTE `value` used here but it isn't initialized diff --git a/tests/ui/moves/issue-72649-uninit-in-loop.stderr b/tests/ui/moves/issue-72649-uninit-in-loop.stderr index 3a93769ac4549..8bde3b5c042db 100644 --- a/tests/ui/moves/issue-72649-uninit-in-loop.stderr +++ b/tests/ui/moves/issue-72649-uninit-in-loop.stderr @@ -83,10 +83,11 @@ LL | let _used2 = value; | ----- you could clone this value error[E0381]: used binding `value` isn't initialized - --> $DIR/issue-72649-uninit-in-loop.rs:73:21 + --> $DIR/issue-72649-uninit-in-loop.rs:74:21 | LL | let value: NonCopy; | ----- binding declared here but left uninitialized +LL | LL | let _used = value; | ^^^^^ `value` used here but it isn't initialized | @@ -96,11 +97,11 @@ LL | let value: NonCopy = /* value */; | +++++++++++++ error[E0381]: used binding `value` isn't initialized - --> $DIR/issue-72649-uninit-in-loop.rs:81:21 + --> $DIR/issue-72649-uninit-in-loop.rs:83:21 | LL | let mut value: NonCopy; | --------- binding declared here but left uninitialized -LL | loop { +... LL | let _used = value; | ^^^^^ `value` used here but it isn't initialized | diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs index d420f2641daf5..0c66b47b39418 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.rs @@ -12,12 +12,11 @@ struct PriorityQueueEntry { } #[derive(PartialOrd, AddImpl)] -//~^ ERROR can't compare `PriorityQueue` with `PriorityQueue` -//~| ERROR the trait bound `PriorityQueue: Eq` is not satisfied -//~| ERROR can't compare `T` with `T` -//~| ERROR no method named `cmp` found for struct `BinaryHeap>` -//~| ERROR no field `height` on type `&PriorityQueue` - +//~^ ERROR: the trait bound `PriorityQueue: Eq` is not satisfied +//~| ERROR: can't compare `T` with `T` +//~| ERROR: no method named `cmp` found for struct `BinaryHeap>` +//~| ERROR: no field `height` on type `&PriorityQueue` struct PriorityQueue(BinaryHeap>); -//~^ ERROR can't compare `BinaryHeap>` with `_` +//~^ ERROR: can't compare `PriorityQueue` with `PriorityQueue` +//~| ERROR: can't compare `BinaryHeap>` with `_` fn main() {} diff --git a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr index b7aed4a8485a8..b53ebe9f72718 100644 --- a/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr +++ b/tests/ui/proc-macro/issue-104884-trait-impl-sugg-err.stderr @@ -1,11 +1,14 @@ error[E0277]: can't compare `PriorityQueue` with `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:8 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ no implementation for `PriorityQueue == PriorityQueue` + | ---------- in this derive macro expansion +... +LL | struct PriorityQueue(BinaryHeap>); + | ^^^^^^^^^^^^^ no implementation for `PriorityQueue == PriorityQueue` | help: the trait `PartialEq` is not implemented for `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:1 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:1 | LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +22,7 @@ LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ unsatisfied trait bound | help: the trait `Eq` is not implemented for `PriorityQueue` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:1 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:1 | LL | struct PriorityQueue(BinaryHeap>); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,15 +37,19 @@ LL | #[derive(PartialOrd, AddImpl)] | ^^^^^^^ no implementation for `T < T` and `T > T` | note: required for `PriorityQueue` to implement `PartialOrd` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:14:10 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:8 | LL | #[derive(PartialOrd, AddImpl)] - | ^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ---------- in this derive macro expansion +... +LL | struct PriorityQueue(BinaryHeap>); + | ^^^^^^^^^^^^^ - type parameter would need to implement `PartialOrd` + = help: consider manually implementing `PartialOrd` to avoid undesired bounds note: required by a bound in `Ord` --> $SRC_DIR/core/src/cmp.rs:LL:COL error[E0277]: can't compare `BinaryHeap>` with `_` - --> $DIR/issue-104884-trait-impl-sugg-err.rs:21:25 + --> $DIR/issue-104884-trait-impl-sugg-err.rs:19:25 | LL | #[derive(PartialOrd, AddImpl)] | ---------- in this derive macro expansion diff --git a/tests/ui/range/range_traits-2.rs b/tests/ui/range/range_traits-2.rs index 234d7a64dc8b0..7dd91243082c5 100644 --- a/tests/ui/range/range_traits-2.rs +++ b/tests/ui/range/range_traits-2.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(Range); +#[derive(Copy, Clone)] +struct R(Range); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-2.stderr b/tests/ui/range/range_traits-2.stderr index 2001c85c4348a..f38539cc648c0 100644 --- a/tests/ui/range/range_traits-2.stderr +++ b/tests/ui/range/range_traits-2.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-2.rs:3:10 + --> $DIR/range_traits-2.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(Range); - | ------------ this field does not implement `Copy` + | ^ ------------ this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-3.rs b/tests/ui/range/range_traits-3.rs index 2d597cce5ad56..79ba1842f62f5 100644 --- a/tests/ui/range/range_traits-3.rs +++ b/tests/ui/range/range_traits-3.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(RangeFrom); +#[derive(Copy, Clone)] +struct R(RangeFrom); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-3.stderr b/tests/ui/range/range_traits-3.stderr index 71210379c79cd..1f3768ad8d84b 100644 --- a/tests/ui/range/range_traits-3.stderr +++ b/tests/ui/range/range_traits-3.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-3.rs:3:10 + --> $DIR/range_traits-3.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(RangeFrom); - | ---------------- this field does not implement `Copy` + | ^ ---------------- this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/range/range_traits-6.rs b/tests/ui/range/range_traits-6.rs index bce106bbfe79b..72c6cecc88d69 100644 --- a/tests/ui/range/range_traits-6.rs +++ b/tests/ui/range/range_traits-6.rs @@ -1,6 +1,6 @@ use std::ops::*; -#[derive(Copy, Clone)] //~ ERROR Copy -struct R(RangeInclusive); +#[derive(Copy, Clone)] +struct R(RangeInclusive); //~ ERROR Copy fn main() {} diff --git a/tests/ui/range/range_traits-6.stderr b/tests/ui/range/range_traits-6.stderr index a58022ef7e4fd..53fe2fed0a616 100644 --- a/tests/ui/range/range_traits-6.stderr +++ b/tests/ui/range/range_traits-6.stderr @@ -1,10 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/range_traits-6.rs:3:10 + --> $DIR/range_traits-6.rs:4:8 | LL | #[derive(Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | struct R(RangeInclusive); - | --------------------- this field does not implement `Copy` + | ^ --------------------- this field does not implement `Copy` error: aborting due to 1 previous error diff --git a/tests/ui/span/E0204.rs b/tests/ui/span/E0204.rs index 8793a05c8a85a..841bd5e32b8a1 100644 --- a/tests/ui/span/E0204.rs +++ b/tests/ui/span/E0204.rs @@ -4,8 +4,8 @@ struct Foo { impl Copy for Foo { } //~ ERROR cannot be implemented for this type -#[derive(Copy)] //~ ERROR cannot be implemented for this type -struct Foo2<'a> { +#[derive(Copy)] +struct Foo2<'a> { //~ ERROR cannot be implemented for this type ty: &'a mut bool, } @@ -16,8 +16,8 @@ enum EFoo { impl Copy for EFoo { } //~ ERROR cannot be implemented for this type -#[derive(Copy)] //~ ERROR cannot be implemented for this type -enum EFoo2<'a> { +#[derive(Copy)] +enum EFoo2<'a> { //~ ERROR cannot be implemented for this type Bar(&'a mut bool), Baz, } diff --git a/tests/ui/span/E0204.stderr b/tests/ui/span/E0204.stderr index fe375b94781b5..a0b51be178634 100644 --- a/tests/ui/span/E0204.stderr +++ b/tests/ui/span/E0204.stderr @@ -8,11 +8,12 @@ LL | impl Copy for Foo { } | ^^^ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/E0204.rs:7:10 + --> $DIR/E0204.rs:8:8 | LL | #[derive(Copy)] - | ^^^^ + | ---- in this derive macro expansion LL | struct Foo2<'a> { + | ^^^^ LL | ty: &'a mut bool, | ---------------- this field does not implement `Copy` @@ -26,11 +27,12 @@ LL | impl Copy for EFoo { } | ^^^^ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/E0204.rs:19:10 + --> $DIR/E0204.rs:20:6 | LL | #[derive(Copy)] - | ^^^^ + | ---- in this derive macro expansion LL | enum EFoo2<'a> { + | ^^^^^ LL | Bar(&'a mut bool), | ------------ this field does not implement `Copy` diff --git a/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs b/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs index 083d73711a517..78b4c017251ef 100644 --- a/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs +++ b/tests/ui/suggestions/derive-clone-already-present-issue-146515.rs @@ -2,8 +2,8 @@ use std::rc::Rc; -#[derive(Clone)] -struct ContainsRc { +#[derive(Clone)] //~ NOTE in this expansion +struct ContainsRc { //~ NOTE derive introduces an implicit `T: Clone` bound value: Rc, } @@ -14,7 +14,6 @@ fn clone_me(x: &ContainsRc) -> ContainsRc { //~| NOTE expected `ContainsRc`, found `&ContainsRc` //~| NOTE expected struct `ContainsRc<_>` //~| NOTE `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead - //~| NOTE the trait `Clone` must be implemented } fn main() {} diff --git a/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr b/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr index 516ef38f668dc..6ecf4e7ca9439 100644 --- a/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr +++ b/tests/ui/suggestions/derive-clone-already-present-issue-146515.stderr @@ -14,9 +14,14 @@ note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned | LL | x.clone() | ^ - = help: `Clone` is not implemented because the trait bound `T: Clone` is not satisfied -note: the trait `Clone` must be implemented - --> $SRC_DIR/core/src/clone.rs:LL:COL +help: `Clone` is not implemented because a trait bound is not satisfied + --> $DIR/derive-clone-already-present-issue-146515.rs:6:19 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRc { + | ^ derive introduces an implicit `T: Clone` bound + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed index 4dc362f947875..17259dd687c6c 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.fixed +++ b/tests/ui/suggestions/derive-clone-for-eq.fixed @@ -1,8 +1,8 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs index b3635000f1658..3e4331745be87 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.rs +++ b/tests/ui/suggestions/derive-clone-for-eq.rs @@ -1,8 +1,8 @@ //@ run-rustfix // https://github.com/rust-lang/rust/issues/79076 -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr index eb0355853daac..bed5ff90c1949 100644 --- a/tests/ui/suggestions/derive-clone-for-eq.stderr +++ b/tests/ui/suggestions/derive-clone-for-eq.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/derive-clone-for-eq.rs:4:17 + --> $DIR/derive-clone-for-eq.rs:5:12 | LL | #[derive(Clone, Eq)] - | ^^ the trait `Clone` is not implemented for `T` + | -- in this derive macro expansion +LL | pub struct Struct(T); + | ^^^^^^ the trait `Clone` is not implemented for `T` | note: required for `Struct` to implement `PartialEq` --> $DIR/derive-clone-for-eq.rs:7:19 diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr index a48dd30d008a6..791e2d19f2f96 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-2.stderr @@ -24,12 +24,13 @@ LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Debug` - --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:10 + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^ ---- unsatisfied trait bound + = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider further restricting type parameter `K` with trait `Copy` | @@ -65,12 +66,13 @@ LL | pub size: Vector2, | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Clone` - --> $DIR/missing-bound-in-derive-copy-impl-2.rs:4:23 + --> $DIR/missing-bound-in-derive-copy-impl-2.rs:5:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^ ---- unsatisfied trait bound + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider further restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed index 74df1d7c7cfdd..bd1785e351123 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.fixed @@ -7,8 +7,8 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB{ +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` //~^ ERROR `K` doesn't implement `Debug` pub size: Vector2 //~ ERROR `K` doesn't implement `Debug` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs index 8550a4d724761..36502044bd467 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.rs @@ -7,8 +7,8 @@ pub struct Vector2{ pub y: T } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB{ +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~ ERROR `K` doesn't implement `Debug` //~^ ERROR `K` doesn't implement `Debug` pub size: Vector2 //~ ERROR `K` doesn't implement `Debug` diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr index e3375b67c86dd..cc80e7297e48a 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl-3.stderr @@ -1,9 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-derive-copy-impl-3.rs:10:17 + --> $DIR/missing-bound-in-derive-copy-impl-3.rs:11:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ -LL | pub struct AABB{ + | ---- in this derive macro expansion +LL | pub struct AABB { + | ^^^^ LL | pub loc: Vector2, | ------------------- this field does not implement `Copy` | @@ -14,7 +15,7 @@ LL | pub loc: Vector2, | ^^^^^^^^^^ help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++ error[E0277]: `K` doesn't implement `Debug` @@ -30,7 +31,7 @@ LL | pub struct Vector2{ | ^^^^^ required by this bound in `Vector2` help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error[E0277]: `K` doesn't implement `Debug` @@ -38,13 +39,13 @@ error[E0277]: `K` doesn't implement `Debug` | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion -LL | pub struct AABB{ +LL | pub struct AABB { LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `K` | help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error[E0277]: `K` doesn't implement `Debug` @@ -58,7 +59,7 @@ LL | pub size: Vector2 | help: consider further restricting type parameter `K` with trait `Debug` | -LL | pub struct AABB{ +LL | pub struct AABB { | +++++++++++++++++ error: aborting due to 4 previous errors diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs index 0ffc1b8f7a25e..60a9074e5c0d9 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.rs @@ -6,8 +6,8 @@ pub struct Vector2 { pub y: T, } -#[derive(Debug, Copy, Clone)] //~ ERROR the trait `Copy` cannot be implemented for this type -pub struct AABB { +#[derive(Debug, Copy, Clone)] +pub struct AABB { //~ ERROR the trait `Copy` cannot be implemented for this type pub loc: Vector2, //~^ ERROR doesn't implement `Debug` //~| ERROR `K: Copy` is not satisfied diff --git a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr index 645d6ebb3961f..55d6391f975e6 100644 --- a/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr +++ b/tests/ui/suggestions/missing-bound-in-derive-copy-impl.stderr @@ -1,9 +1,10 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/missing-bound-in-derive-copy-impl.rs:9:17 + --> $DIR/missing-bound-in-derive-copy-impl.rs:10:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ + | ---- in this derive macro expansion LL | pub struct AABB { + | ^^^^ LL | pub loc: Vector2, | ------------------- this field does not implement `Copy` | @@ -59,12 +60,13 @@ LL | pub loc: Vector2, | ^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Debug` - --> $DIR/missing-bound-in-derive-copy-impl.rs:3:10 + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^ ---- unsatisfied trait bound + = help: consider manually implementing `Debug` to avoid undesired bounds = note: required for the cast from `&Vector2` to `&dyn Debug` help: consider restricting type parameter `K` with trait `Copy` | @@ -128,12 +130,13 @@ LL | pub size: Vector2, | ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `K` | note: required for `Vector2` to implement `Clone` - --> $DIR/missing-bound-in-derive-copy-impl.rs:3:23 + --> $DIR/missing-bound-in-derive-copy-impl.rs:4:12 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ + | ----- in this derive macro expansion LL | pub struct Vector2 { - | ---- unsatisfied trait bound introduced in this `derive` macro + | ^^^^^^^ ---- unsatisfied trait bound + = help: consider manually implementing `Clone` to avoid undesired bounds help: consider restricting type parameter `K` with trait `Copy` | LL | pub struct AABB { diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.rs b/tests/ui/traits/derive-implicit-bound-on-clone.rs new file mode 100644 index 0000000000000..a4c9e88ef5765 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound-on-clone.rs @@ -0,0 +1,24 @@ +// Issue #146515 +use std::rc::Rc; + +#[derive(Clone)] +struct ContainsRc { //~ HELP `Clone` is not implemented + value: Rc<(T, K)>, +} + +fn clone_me(x: &ContainsRc) -> ContainsRc { + x.clone() //~ ERROR E0308 + //~^ HELP consider manually implementing `Clone` +} + +#[derive(Clone)] +struct ContainsRcSingle { //~ HELP `Clone` is not implemented + value: Rc, +} + +fn clone_me_single(x: &ContainsRcSingle) -> ContainsRcSingle { + x.clone() //~ ERROR E0308 + //~^ HELP consider manually implementing `Clone` +} + +fn main() {} diff --git a/tests/ui/traits/derive-implicit-bound-on-clone.stderr b/tests/ui/traits/derive-implicit-bound-on-clone.stderr new file mode 100644 index 0000000000000..2fb039f965288 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound-on-clone.stderr @@ -0,0 +1,53 @@ +error[E0308]: mismatched types + --> $DIR/derive-implicit-bound-on-clone.rs:10:5 + | +LL | fn clone_me(x: &ContainsRc) -> ContainsRc { + | ---------------- expected `ContainsRc` because of return type +LL | x.clone() + | ^^^^^^^^^ expected `ContainsRc`, found `&ContainsRc` + | + = note: expected struct `ContainsRc<_, _>` + found reference `&ContainsRc<_, _>` +note: `ContainsRc` does not implement `Clone`, so `&ContainsRc` was cloned instead + --> $DIR/derive-implicit-bound-on-clone.rs:10:5 + | +LL | x.clone() + | ^ +help: `Clone` is not implemented because the some trait bounds could not be satisfied + --> $DIR/derive-implicit-bound-on-clone.rs:5:19 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRc { + | ^ ^ derive introduces an implicit unsatisfied trait bound `K: Clone` + | | + | derive introduces an implicit unsatisfied trait bound `T: Clone` + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds + +error[E0308]: mismatched types + --> $DIR/derive-implicit-bound-on-clone.rs:20:5 + | +LL | fn clone_me_single(x: &ContainsRcSingle) -> ContainsRcSingle { + | ------------------- expected `ContainsRcSingle` because of return type +LL | x.clone() + | ^^^^^^^^^ expected `ContainsRcSingle`, found `&ContainsRcSingle` + | + = note: expected struct `ContainsRcSingle<_>` + found reference `&ContainsRcSingle<_>` +note: `ContainsRcSingle` does not implement `Clone`, so `&ContainsRcSingle` was cloned instead + --> $DIR/derive-implicit-bound-on-clone.rs:20:5 + | +LL | x.clone() + | ^ +help: `Clone` is not implemented because a trait bound is not satisfied + --> $DIR/derive-implicit-bound-on-clone.rs:15:25 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct ContainsRcSingle { + | ^ derive introduces an implicit `T: Clone` bound + = help: consider manually implementing `Clone` to avoid the implicit type parameter bounds + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/traits/derive-implicit-bound.rs b/tests/ui/traits/derive-implicit-bound.rs new file mode 100644 index 0000000000000..22fb68f37c5c4 --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound.rs @@ -0,0 +1,34 @@ +// Second case reported in issue #108894. + +use std::marker::PhantomData; + +#[derive(PartialEq, Eq)] +pub struct Id(PhantomData); + +// manual implementation which would break the usage of const patterns +// impl PartialEq for Id { fn eq(&self, _: &Id) -> bool { true } } +// impl Eq for Id {} + +// This derive is undesired but cannot be removed without +// breaking the usages below +// #[derive(PartialEq, Eq)] +struct SomeNode(); + +fn accept_eq(_: &impl PartialEq) { } + +fn main() { + let node = Id::(PhantomData); + + // this will only work if + // - `Partial/Eq` is implemented manually, or + // - `SomeNode` also needlessly(?) implements `Partial/Eq` + accept_eq(&node); //~ ERROR can't compare `SomeNode` with `SomeNode` + + const CONST_ID: Id:: = Id::(PhantomData); + // this will work only when `Partial/Eq` is being derived + // otherwise: error: to use a constant of type `Id` in a pattern, + // `Id` must be annotated with `#[derive(PartialEq, Eq)]` + match node { + CONST_ID => {} + } +} diff --git a/tests/ui/traits/derive-implicit-bound.stderr b/tests/ui/traits/derive-implicit-bound.stderr new file mode 100644 index 0000000000000..fe2bc77b9529c --- /dev/null +++ b/tests/ui/traits/derive-implicit-bound.stderr @@ -0,0 +1,31 @@ +error[E0277]: can't compare `SomeNode` with `SomeNode` + --> $DIR/derive-implicit-bound.rs:25:15 + | +LL | accept_eq(&node); + | --------- ^^^^^ no implementation for `SomeNode == SomeNode` + | | + | required by a bound introduced by this call + | + = help: the trait `PartialEq` is not implemented for `SomeNode` +note: required for `Id` to implement `PartialEq` + --> $DIR/derive-implicit-bound.rs:6:12 + | +LL | #[derive(PartialEq, Eq)] + | --------- in this derive macro expansion +LL | pub struct Id(PhantomData); + | ^^ - type parameter would need to implement `PartialEq` + = help: consider manually implementing `PartialEq` to avoid undesired bounds +note: required by a bound in `accept_eq` + --> $DIR/derive-implicit-bound.rs:17:23 + | +LL | fn accept_eq(_: &impl PartialEq) { } + | ^^^^^^^^^ required by this bound in `accept_eq` +help: consider annotating `SomeNode` with `#[derive(PartialEq)]` + | +LL + #[derive(PartialEq)] +LL | struct SomeNode(); + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index d45668312218b..6b04004621d82 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,6 +1,4 @@ -#[derive(Clone)] -//~^ ERROR expected a type, found a trait -//~| ERROR expected a type, found a trait -struct Foo; -trait Foo {} //~ ERROR the name `Foo` is defined multiple times +#[derive(Clone)] //~ ERROR: expected a type, found a trait +struct Foo; //~ ERROR: expected a type, found a trait +trait Foo {} //~ ERROR: the name `Foo` is defined multiple times fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index 815787c3bfecb..57661fda73079 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Foo` is defined multiple times - --> $DIR/issue-106072.rs:5:1 + --> $DIR/issue-106072.rs:3:1 | LL | struct Foo; | ----------- previous definition of the type `Foo` here @@ -9,18 +9,18 @@ LL | trait Foo {} = note: `Foo` must be defined only once in the type namespace of this module error[E0782]: expected a type, found a trait - --> $DIR/issue-106072.rs:1:10 + --> $DIR/issue-106072.rs:2:8 | LL | #[derive(Clone)] - | ^^^^^ + | ----- in this derive macro expansion +LL | struct Foo; + | ^^^ error[E0782]: expected a type, found a trait --> $DIR/issue-106072.rs:1:10 | LL | #[derive(Clone)] | ^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/traits/issue-50480.rs b/tests/ui/traits/issue-50480.rs index ccd35a850f2d7..2f62906e9df3d 100644 --- a/tests/ui/traits/issue-50480.rs +++ b/tests/ui/traits/issue-50480.rs @@ -1,18 +1,17 @@ #[derive(Clone, Copy)] -//~^ ERROR the trait `Copy` cannot be implemented for this type struct Foo(N, NotDefined, ::Item, Vec, String); -//~^ ERROR cannot find type `NotDefined` in this scope +//~^ ERROR the trait `Copy` cannot be implemented for this type +//~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR `i32` is not an iterator //~| ERROR `i32` is not an iterator -#[derive(Clone, Copy)] -//~^ ERROR the trait `Copy` cannot be implemented for this type -//~| ERROR `i32` is not an iterator +#[derive(Clone, Copy)] //~ ERROR `i32` is not an iterator struct Bar(T, N, NotDefined, ::Item, Vec, String); -//~^ ERROR cannot find type `NotDefined` in this scope +//~^ ERROR the trait `Copy` cannot be implemented for this type +//~| ERROR cannot find type `NotDefined` in this scope //~| ERROR cannot find type `N` in this scope //~| ERROR `i32` is not an iterator //~| ERROR `i32` is not an iterator diff --git a/tests/ui/traits/issue-50480.stderr b/tests/ui/traits/issue-50480.stderr index 32c8b2cf3ac1f..1fb5e8b007830 100644 --- a/tests/ui/traits/issue-50480.stderr +++ b/tests/ui/traits/issue-50480.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:3:12 + --> $DIR/issue-50480.rs:2:12 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^ not found in this scope @@ -10,13 +10,13 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:3:15 + --> $DIR/issue-50480.rs:2:15 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:3:12 + --> $DIR/issue-50480.rs:2:12 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^ not found in this scope @@ -27,7 +27,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:3:15 + --> $DIR/issue-50480.rs:2:15 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope @@ -38,7 +38,7 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, St | ++++++++++++ error[E0425]: cannot find type `N` in this scope - --> $DIR/issue-50480.rs:14:18 + --> $DIR/issue-50480.rs:12:18 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | - ^ @@ -56,13 +56,13 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, Strin | +++ error[E0425]: cannot find type `NotDefined` in this scope - --> $DIR/issue-50480.rs:14:21 + --> $DIR/issue-50480.rs:12:21 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^ not found in this scope error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:27 + --> $DIR/issue-50480.rs:2:27 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator @@ -70,29 +70,27 @@ LL | struct Foo(N, NotDefined, ::Item, Vec, String); = help: the trait `Iterator` is not implemented for `i32` error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:1:17 + --> $DIR/issue-50480.rs:2:8 | LL | #[derive(Clone, Copy)] - | ^^^^ -LL | + | ---- in this derive macro expansion LL | struct Foo(N, NotDefined, ::Item, Vec, String); - | -------- ------ this field does not implement `Copy` + | ^^^ -------- ------ this field does not implement `Copy` | | | this field does not implement `Copy` error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/issue-50480.rs:11:17 + --> $DIR/issue-50480.rs:12:8 | LL | #[derive(Clone, Copy)] - | ^^^^ -... + | ---- in this derive macro expansion LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); - | -------- ------ this field does not implement `Copy` + | ^^^ -------- ------ this field does not implement `Copy` | | | this field does not implement `Copy` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:14:33 + --> $DIR/issue-50480.rs:12:33 | LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator @@ -100,7 +98,7 @@ LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); = help: the trait `Iterator` is not implemented for `i32` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:3:28 + --> $DIR/issue-50480.rs:2:28 | LL | struct Foo(N, NotDefined, ::Item, Vec, String); | ^^^ `i32` is not an iterator @@ -116,11 +114,10 @@ LL | #[derive(Clone, Copy)] = help: the trait `Iterator` is not implemented for `i32` error[E0277]: `i32` is not an iterator - --> $DIR/issue-50480.rs:14:33 + --> $DIR/issue-50480.rs:12:33 | LL | #[derive(Clone, Copy)] | ----- in this derive macro expansion -... LL | struct Bar(T, N, NotDefined, ::Item, Vec, String); | ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator | diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs index 2b4f7ba9fa29e..ceef87d76abb6 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.rs @@ -12,8 +12,8 @@ // we already face this difficulty, probably. If we need to fix this by reducing the error margin, // we should improve compiletest. -#[derive(Clone, Eq)] //~ ERROR [E0277] -pub struct Struct(T); +#[derive(Clone, Eq)] +pub struct Struct(T); //~ ERROR [E0277] impl PartialEq for Struct where diff --git a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr index 290b1df1665d3..912286a48fafe 100644 --- a/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr +++ b/tests/ui/traits/next-solver/global-cache-and-parallel-frontend.stderr @@ -1,8 +1,10 @@ error[E0277]: the trait bound `T: Clone` is not satisfied - --> $DIR/global-cache-and-parallel-frontend.rs:15:17 + --> $DIR/global-cache-and-parallel-frontend.rs:16:12 | LL | #[derive(Clone, Eq)] - | ^^ the trait `Clone` is not implemented for `T` + | -- in this derive macro expansion +LL | pub struct Struct(T); + | ^^^^^^ the trait `Clone` is not implemented for `T` | note: required for `Struct` to implement `PartialEq` --> $DIR/global-cache-and-parallel-frontend.rs:18:19 diff --git a/tests/ui/union/union-derive-clone.stderr b/tests/ui/union/union-derive-clone.stderr index 18f862aaa7d6e..62ef35b761922 100644 --- a/tests/ui/union/union-derive-clone.stderr +++ b/tests/ui/union/union-derive-clone.stderr @@ -25,10 +25,13 @@ LL | let w = u.clone(); | ^^^^^ method cannot be called on `U5` due to unsatisfied trait bounds | note: trait bound `CloneNoCopy: Copy` was not satisfied - --> $DIR/union-derive-clone.rs:25:10 + --> $DIR/union-derive-clone.rs:26:10 | LL | #[derive(Clone, Copy)] - | ^^^^^ unsatisfied trait bound introduced in this `derive` macro + | ----- in this derive macro expansion +LL | union U5 { + | ^ type parameter would need to implement `Clone` + = help: consider manually implementing the trait to avoid undesired bounds help: consider annotating `CloneNoCopy` with `#[derive(Clone, Copy)]` | LL + #[derive(Clone, Copy)]