diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index c863acde7b0..2b01aca2ee4 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -461,8 +461,8 @@ pub trait LayoutCalculator { let all_indices = variants.indices(); let needs_disc = |index: VariantIdx| index != largest_variant_index && !absent(&variants[index]); - let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap().index() - ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap().index(); + let niche_variants = all_indices.clone().find(|v| needs_disc(*v)).unwrap() + ..=all_indices.rev().find(|v| needs_disc(*v)).unwrap(); let count = niche_variants.size_hint().1.unwrap() as u128; @@ -560,8 +560,7 @@ pub trait LayoutCalculator { tag: niche_scalar, tag_encoding: TagEncoding::Niche { untagged_variant: largest_variant_index, - niche_variants: (VariantIdx::new(*niche_variants.start()) - ..=VariantIdx::new(*niche_variants.end())), + niche_variants, niche_start, }, tag_field: 0, diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 7a3defd2a5d..402ea6ff48f 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -11,7 +11,7 @@ use bitflags::bitflags; use rustc_data_structures::intern::Interned; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::StableOrd; -use rustc_index::vec::{Idx, IndexSlice, IndexVec}; +use rustc_index::vec::{IndexSlice, IndexVec}; #[cfg(feature = "nightly")] use rustc_macros::HashStable_Generic; #[cfg(feature = "nightly")] diff --git a/compiler/rustc_ast/src/node_id.rs b/compiler/rustc_ast/src/node_id.rs index daa82996b3d..d16741757d1 100644 --- a/compiler/rustc_ast/src/node_id.rs +++ b/compiler/rustc_ast/src/node_id.rs @@ -9,14 +9,14 @@ rustc_index::newtype_index! { /// /// [`DefId`]: rustc_span::def_id::DefId #[debug_format = "NodeId({})"] - pub struct NodeId {} + pub struct NodeId { + /// The [`NodeId`] used to represent the root of the crate. + const CRATE_NODE_ID = 0; + } } rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeMapEntry, NodeId); -/// The [`NodeId`] used to represent the root of the crate. -pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0); - /// When parsing and at the beginning of doing expansions, we initially give all AST nodes /// this dummy AST [`NodeId`]. Then, during a later phase of expansion, we renumber them /// to have small, positive IDs. diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index a3b6b5e8138..0b8123c9703 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -56,18 +56,6 @@ borrowck_returned_lifetime_short = borrowck_used_impl_require_static = the used `impl` has a `'static` requirement -borrowck_capture_kind_label = - capture is {$kind_desc} because of use here - -borrowck_var_borrow_by_use_place_in_generator = - borrow occurs due to use of {$place} in closure in generator - -borrowck_var_borrow_by_use_place_in_closure = - borrow occurs due to use of {$place} in closure - -borrowck_var_borrow_by_use_place = - borrow occurs due to use of {$place} - borrowck_borrow_due_to_use_generator = borrow occurs due to use in generator @@ -101,12 +89,63 @@ borrowck_capture_mut = borrowck_capture_move = capture is moved because of use here +borrowck_var_borrow_by_use_place_in_generator = + {$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in generator + +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_in_generator = + borrow occurs due to use in generator + +borrowck_var_borrow_by_use_in_closure = + borrow occurs due to use in closure + borrowck_var_move_by_use_place_in_generator = move occurs due to use of {$place} in generator borrowck_var_move_by_use_place_in_closure = move occurs due to use of {$place} in closure +borrowck_var_move_by_use_in_generator = + move occurs due to use in generator + +borrowck_var_move_by_use_in_closure = + move occurs due to use in closure + +borrowck_partial_var_move_by_use_in_generator = + variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in generator + +borrowck_partial_var_move_by_use_in_closure = + variable {$is_partial -> + [true] partially moved + *[false] moved + } due to use in closure + +borrowck_var_first_borrow_by_use_place_in_generator = + first borrow occurs due to use of {$place} in generator + +borrowck_var_first_borrow_by_use_place_in_closure = + first borrow occurs due to use of {$place} in closure + +borrowck_var_second_borrow_by_use_place_in_generator = + second borrow occurs due to use of {$place} in generator + +borrowck_var_second_borrow_by_use_place_in_closure = + second borrow occurs due to use of {$place} in closure + +borrowck_var_mutable_borrow_by_use_place_in_closure = + mutable borrow occurs due to use of {$place} in closure + borrowck_cannot_move_when_borrowed = cannot move out of {$place -> [value] value @@ -127,3 +166,90 @@ borrowck_opaque_type_non_generic_param = [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 } + +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_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_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_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_consider_borrow_type_contents = + help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents + +borrowck_moved_a_fn_once_in_call = + this value implements `FnOnce`, which causes it to be moved when called + +borrowck_calling_operator_moves_lhs = + calling this operator moves the left-hand side + +borrowck_func_take_self_moved_place = + `{$func}` takes ownership of the receiver `self`, which moves {$place_name} + +borrowck_suggest_iterate_over_slice = + consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop + +borrowck_suggest_create_freash_reborrow = + consider reborrowing the `Pin` instead of moving it + +borrowck_value_capture_here = + value captured {$is_within -> + [true] here by generator + *[false] here + } + +borrowck_move_out_place_here = + {$place} is moved here + +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_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 diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 6259ae47e89..a4a3c738f47 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -30,8 +30,8 @@ use crate::borrow_set::TwoPhaseActivation; use crate::borrowck_errors; use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead; -use crate::diagnostics::find_all_local_uses; use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref; +use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt}; use crate::{ borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, @@ -183,13 +183,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let move_spans = self.move_spans(moved_place.as_ref(), move_out.source); let move_span = move_spans.args_or_use(); - let move_msg = if move_spans.for_closure() { " into closure" } else { "" }; + let is_move_msg = move_spans.for_closure(); - let loop_message = if location == move_out.source || move_site.traversed_back_edge { - ", in previous iteration of loop" - } else { - "" - }; + let is_loop_message = location == move_out.source || move_site.traversed_back_edge; if location == move_out.source { is_loop_move = true; @@ -206,17 +202,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } + let msg_opt = CapturedMessageOpt { + is_partial_move, + is_loop_message, + is_move_msg, + is_loop_move, + maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations + .is_empty(), + }; self.explain_captures( &mut err, span, move_span, move_spans, *moved_place, - partially_str, - loop_message, - move_msg, - is_loop_move, - maybe_reinitialized_locations.is_empty(), + msg_opt, ); } seen_spans.insert(move_span); @@ -282,12 +282,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } if needs_note { - let span = if let Some(local) = place.as_local() { - Some(self.body.local_decls[local].source_info.span) + if let Some(local) = place.as_local() { + let span = self.body.local_decls[local].source_info.span; + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move, + ty, + place: ¬e_msg, + span, + }); } else { - None + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note { + is_partial_move, + ty, + place: ¬e_msg, + }); }; - self.note_type_does_not_implement_copy(&mut err, ¬e_msg, ty, span, partial_str); } if let UseSpans::FnSelfUse { @@ -827,11 +836,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow); - move_spans.var_span_label( - &mut err, - format!("move occurs due to use{}", move_spans.describe()), - "moved", - ); + move_spans.var_subdiag(None, &mut err, None, |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => MoveUseInGenerator { var_span }, + None => MoveUseInClosure { var_span }, + } + }); self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( @@ -868,13 +879,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_span, &self.describe_any_place(borrow.borrowed_place.as_ref()), ); - borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| { + borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; let place = &borrow.borrowed_place; let desc_place = self.describe_any_place(place.as_ref()); match kind { - Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span }, - None => BorrowUsePlaceClosure { place: desc_place, var_span }, + Some(_) => { + BorrowUsePlaceGenerator { place: desc_place, var_span, is_single_var: true } + } + None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true }, } }); @@ -988,16 +1001,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { immutable_section_description, "mutably borrow", ); - borrow_spans.var_span_label( + borrow_spans.var_subdiag( + None, &mut err, - format!( - "borrow occurs due to use of {}{}", - desc_place, - borrow_spans.describe(), - ), - "immutable", + Some(BorrowKind::Unique), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUsePlaceGenerator { + place: desc_place, + var_span, + is_single_var: true, + }, + None => BorrowUsePlaceClosure { + place: desc_place, + var_span, + is_single_var: true, + }, + } + }, ); - return err; } else { first_borrow_desc = "immutable "; @@ -1070,32 +1093,48 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; if issued_spans == borrow_spans { - borrow_spans.var_span_label( - &mut err, - format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe(),), - gen_borrow_kind.describe_mutability(), - ); + borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUsePlaceGenerator { + place: desc_place, + var_span, + is_single_var: false, + }, + None => { + BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false } + } + } + }); } else { - let borrow_place = &issued_borrow.borrowed_place; - let borrow_place_desc = self.describe_any_place(borrow_place.as_ref()); - issued_spans.var_span_label( + issued_spans.var_subdiag( + Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic), &mut err, - format!( - "first borrow occurs due to use of {}{}", - borrow_place_desc, - issued_spans.describe(), - ), - issued_borrow.kind.describe_mutability(), + Some(issued_borrow.kind), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + let borrow_place = &issued_borrow.borrowed_place; + let borrow_place_desc = self.describe_any_place(borrow_place.as_ref()); + match kind { + Some(_) => { + FirstBorrowUsePlaceGenerator { place: borrow_place_desc, var_span } + } + None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span }, + } + }, ); - borrow_spans.var_span_label( + borrow_spans.var_subdiag( + Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic), &mut err, - format!( - "second borrow occurs due to use of {}{}", - desc_place, - borrow_spans.describe(), - ), - gen_borrow_kind.describe_mutability(), + Some(gen_borrow_kind), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => SecondBorrowUsePlaceGenerator { place: desc_place, var_span }, + None => SecondBorrowUsePlaceClosure { place: desc_place, var_span }, + } + }, ); } @@ -1731,9 +1770,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name)); - let within = if borrow_spans.for_generator() { " by generator" } else { "" }; - - borrow_spans.args_span_label(&mut err, format!("value captured here{}", within)); + borrow_spans.args_subdiag(&mut err, |args_span| { + crate::session_diagnostics::CaptureArgLabel::Capture { + is_within: borrow_spans.for_generator(), + args_span, + } + }); explanation.add_explanation_to_diagnostic( self.infcx.tcx, @@ -1947,9 +1989,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ); - let within = if borrow_spans.for_generator() { " by generator" } else { "" }; - - borrow_spans.args_span_label(&mut err, format!("value captured here{}", within)); + borrow_spans.args_subdiag(&mut err, |args_span| { + crate::session_diagnostics::CaptureArgLabel::Capture { + is_within: borrow_spans.for_generator(), + args_span, + } + }); err } @@ -2382,11 +2427,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { section, "assign", ); - loan_spans.var_span_label( - &mut err, - format!("borrow occurs due to use{}", loan_spans.describe()), - loan.kind.describe_mutability(), - ); + + loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUseInGenerator { var_span }, + None => BorrowUseInClosure { var_span }, + } + }); self.buffer_error(err); @@ -2396,11 +2444,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place); - loan_spans.var_span_label( - &mut err, - format!("borrow occurs due to use{}", loan_spans.describe()), - loan.kind.describe_mutability(), - ); + loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUseInGenerator { var_span }, + None => BorrowUseInClosure { var_span }, + } + }); self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic( self.infcx.tcx, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index dd003b5b040..4a85df9f8c0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1,5 +1,9 @@ //! Borrow checker diagnostics. +use crate::session_diagnostics::{ + CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause, + CaptureVarKind, CaptureVarPathUseCause, OnClosureNote, +}; use itertools::Itertools; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; @@ -117,13 +121,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() { let did = did.expect_local(); if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { - diag.span_note( - *span, - &format!( - "closure cannot be invoked more than once because it moves the \ - variable `{}` out of its environment", - ty::place_to_string_for_capture(self.infcx.tcx, hir_place) - ), + diag.eager_subdiagnostic( + &self.infcx.tcx.sess.parse_sess.span_diagnostic, + OnClosureNote::InvokedTwice { + place_name: &ty::place_to_string_for_capture( + self.infcx.tcx, + hir_place, + ), + span: *span, + }, ); return true; } @@ -137,13 +143,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() { let did = did.expect_local(); if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { - diag.span_note( - *span, - &format!( - "closure cannot be moved more than once as it is not `Copy` due to \ - moving the variable `{}` out of its environment", - ty::place_to_string_for_capture(self.infcx.tcx, hir_place) - ), + diag.eager_subdiagnostic( + &self.infcx.tcx.sess.parse_sess.span_diagnostic, + OnClosureNote::MovedTwice { + place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place), + span: *span, + }, ); return true; } @@ -380,25 +385,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - /// Add a note that a type does not implement `Copy` - pub(super) fn note_type_does_not_implement_copy( - &self, - err: &mut Diagnostic, - place_desc: &str, - ty: Ty<'tcx>, - span: Option, - move_prefix: &str, - ) { - let message = format!( - "{move_prefix}move occurs because {place_desc} has type `{ty}`, which does not implement the `Copy` trait", - ); - if let Some(span) = span { - err.span_label(span, message); - } else { - err.note(&message); - } - } - pub(super) fn borrowed_content_source( &self, deref_base: PlaceRef<'tcx>, @@ -582,9 +568,13 @@ impl UseSpans<'_> { } /// Add a span label to the arguments of the closure, if it exists. - pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into) { + pub(super) fn args_subdiag( + self, + err: &mut Diagnostic, + f: impl FnOnce(Span) -> CaptureArgLabel, + ) { if let UseSpans::ClosureUse { args_span, .. } = self { - err.span_label(args_span, message); + err.subdiagnostic(f(args_span)); } } @@ -595,8 +585,8 @@ impl UseSpans<'_> { err: &mut Diagnostic, action: crate::InitializationRequiringAction, ) { - use crate::session_diagnostics::CaptureVarPathUseCause::*; use crate::InitializationRequiringAction::*; + use CaptureVarPathUseCause::*; if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self { match generator_kind { Some(_) => { @@ -619,34 +609,14 @@ impl UseSpans<'_> { } } - /// Add a span label to the use of the captured variable, if it exists. - pub(super) fn var_span_label( - self, - err: &mut Diagnostic, - message: impl Into, - kind_desc: impl Into, - ) { - if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self { - if capture_kind_span == path_span { - err.span_label(capture_kind_span, message); - } else { - let capture_kind_label = - format!("capture is {} because of use here", kind_desc.into()); - let path_label = message; - err.span_label(capture_kind_span, capture_kind_label); - err.span_label(path_span, path_label); - } - } - } - /// Add a subdiagnostic to the use of the captured variable, if it exists. pub(super) fn var_subdiag( self, + handler: Option<&rustc_errors::Handler>, err: &mut Diagnostic, kind: Option, - f: impl Fn(Option, Span) -> crate::session_diagnostics::CaptureVarCause, + f: impl FnOnce(Option, Span) -> CaptureVarCause, ) { - use crate::session_diagnostics::CaptureVarKind::*; if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self { if capture_kind_span != path_span { err.subdiagnostic(match kind { @@ -654,17 +624,21 @@ impl UseSpans<'_> { rustc_middle::mir::BorrowKind::Shared | rustc_middle::mir::BorrowKind::Shallow | rustc_middle::mir::BorrowKind::Unique => { - Immute { kind_span: capture_kind_span } + CaptureVarKind::Immut { kind_span: capture_kind_span } } rustc_middle::mir::BorrowKind::Mut { .. } => { - Mut { kind_span: capture_kind_span } + CaptureVarKind::Mut { kind_span: capture_kind_span } } }, - None => Move { kind_span: capture_kind_span }, + None => CaptureVarKind::Move { kind_span: capture_kind_span }, }); }; - err.subdiagnostic(f(generator_kind, path_span)); + let diag = f(generator_kind, path_span); + match handler { + Some(hd) => err.eager_subdiagnostic(hd, diag), + None => err.subdiagnostic(diag), + }; } } @@ -684,20 +658,6 @@ impl UseSpans<'_> { } } - /// Describe the span associated with a use of a place. - pub(super) fn describe(&self) -> &str { - match *self { - UseSpans::ClosureUse { generator_kind, .. } => { - if generator_kind.is_some() { - " in generator" - } else { - " in closure" - } - } - _ => "", - } - } - pub(super) fn or_else(self, if_other: F) -> Self where F: FnOnce() -> Self, @@ -788,6 +748,15 @@ impl<'tcx> BorrowedContentSource<'tcx> { } } +///helper struct for explain_captures() +struct CapturedMessageOpt { + is_partial_move: bool, + is_loop_message: bool, + is_move_msg: bool, + is_loop_move: bool, + maybe_reinitialized_locations_is_empty: bool, +} + impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Finds the spans associated to a move or copy of move_place at location. pub(super) fn move_spans( @@ -1027,12 +996,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span: Span, move_spans: UseSpans<'tcx>, moved_place: Place<'tcx>, - partially_str: &str, - loop_message: &str, - move_msg: &str, - is_loop_move: bool, - maybe_reinitialized_locations_is_empty: bool, + msg_opt: CapturedMessageOpt, ) { + let CapturedMessageOpt { + is_partial_move: is_partial, + is_loop_message, + is_move_msg, + is_loop_move, + maybe_reinitialized_locations_is_empty, + } = msg_opt; if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans { let place_name = self .describe_place(moved_place.as_ref()) @@ -1042,30 +1014,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { CallKind::FnCall { fn_trait_id, .. } if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() => { - err.span_label( + err.subdiagnostic(CaptureReasonLabel::Call { fn_call_span, - &format!( - "{place_name} {partially_str}moved due to this call{loop_message}", - ), - ); - err.span_note( - var_span, - "this value implements `FnOnce`, which causes it to be moved when called", - ); + place_name: &place_name, + is_partial, + is_loop_message, + }); + err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span }); } CallKind::Operator { self_arg, .. } => { let self_arg = self_arg.unwrap(); - err.span_label( + err.subdiagnostic(CaptureReasonLabel::OperatorUse { fn_call_span, - &format!( - "{place_name} {partially_str}moved due to usage in operator{loop_message}", - ), - ); + place_name: &place_name, + is_partial, + is_loop_message, + }); if self.fn_self_span_reported.insert(fn_span) { - err.span_note( - self_arg.span, - "calling this operator moves the left-hand side", - ); + err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator { + span: self_arg.span, + }); } } CallKind::Normal { self_arg, desugaring, method_did, method_substs } => { @@ -1086,23 +1054,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => false, }; if suggest { - err.span_suggestion_verbose( - move_span.shrink_to_lo(), - &format!( - "consider iterating over a slice of the `{ty}`'s content to \ - avoid moving into the `for` loop", - ), - "&", - Applicability::MaybeIncorrect, - ); + err.subdiagnostic(CaptureReasonSuggest::IterateSlice { + ty, + span: move_span.shrink_to_lo(), + }); } - err.span_label( + err.subdiagnostic(CaptureReasonLabel::ImplicitCall { fn_call_span, - &format!( - "{place_name} {partially_str}moved due to this implicit call to `.into_iter()`{loop_message}", - ), - ); + place_name: &place_name, + is_partial, + is_loop_message, + }); // If the moved place was a `&mut` ref, then we can // suggest to reborrow it where it was moved, so it // will still be valid by the time we get to the usage. @@ -1125,13 +1088,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } } else { - err.span_label( + err.subdiagnostic(CaptureReasonLabel::MethodCall { fn_call_span, - &format!( - "{place_name} {partially_str}moved due to this method call{loop_message}", - ), - ); - + place_name: &place_name, + is_partial, + is_loop_message, + }); let infcx = tcx.infer_ctxt().build(); // Erase and shadow everything that could be passed to the new infcx. let ty = tcx.erase_regions(moved_place.ty(self.body, tcx).ty); @@ -1147,12 +1109,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) && infcx.can_eq(self.param_env, ty, self_ty) { - err.span_suggestion_verbose( - fn_call_span.shrink_to_lo(), - "consider reborrowing the `Pin` instead of moving it", - "as_mut().".to_string(), - Applicability::MaybeIncorrect, - ); + err.eager_subdiagnostic( + &self.infcx.tcx.sess.parse_sess.span_diagnostic, + CaptureReasonSuggest::FreshReborrow { + span: fn_call_span.shrink_to_lo(), + }); } if let Some(clone_trait) = tcx.lang_items().clone_trait() && let trait_ref = tcx.mk_trait_ref(clone_trait, [ty]) @@ -1177,10 +1138,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // error messages. if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) { let func = tcx.def_path_str(method_did); - err.span_note( - self_arg.span, - &format!("`{func}` takes ownership of the receiver `self`, which moves {place_name}") - ); + err.subdiagnostic(CaptureReasonNote::FuncTakeSelf { + func, + place_name, + span: self_arg.span, + }); } let parent_did = tcx.parent(method_did); let parent_self_ty = @@ -1194,30 +1156,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result)) }); if is_option_or_result && maybe_reinitialized_locations_is_empty { - err.span_label( - var_span, - "help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents", - ); + err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span }); } } // Other desugarings takes &self, which cannot cause a move _ => {} } } else { - if move_span != span || !loop_message.is_empty() { - err.span_label( + if move_span != span || is_loop_message { + err.subdiagnostic(CaptureReasonLabel::MovedHere { move_span, - format!("value {partially_str}moved{move_msg} here{loop_message}"), - ); + is_partial, + is_move_msg, + is_loop_message, + }); } // If the move error occurs due to a loop, don't show // another message for the same span - if loop_message.is_empty() { - move_spans.var_span_label( - err, - format!("variable {partially_str}moved due to use{}", move_spans.describe()), - "moved", - ); + if !is_loop_message { + move_spans.var_subdiag(None, err, None, |kind, var_span| match kind { + Some(_) => CaptureVarCause::PartialMoveUseInGenerator { var_span, is_partial }, + None => CaptureVarCause::PartialMoveUseInClosure { var_span, is_partial }, + }) } } } diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 3662bec0c76..67af96a71e3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -6,6 +6,7 @@ use rustc_mir_dataflow::move_paths::{ }; use rustc_span::{BytePos, Span}; +use crate::diagnostics::CapturedMessageOpt; use crate::diagnostics::{DescribePlaceOpt, UseSpans}; use crate::prefixes::PrefixSet; use crate::MirBorrowckCtxt; @@ -397,10 +398,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } }; + let msg_opt = CapturedMessageOpt { + is_partial_move: false, + is_loop_message: false, + is_move_msg: false, + is_loop_move: false, + maybe_reinitialized_locations_is_empty: true, + }; if let Some(use_spans) = use_spans { - self.explain_captures( - &mut err, span, span, use_spans, move_place, "", "", "", false, true, - ); + self.explain_captures(&mut err, span, span, use_spans, move_place, msg_opt); } err } @@ -416,13 +422,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { None => "value".to_string(), }; - self.note_type_does_not_implement_copy( - err, - &place_desc, - place_ty, - Some(span), - "", - ); + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: place_ty, + place: &place_desc, + span, + }); } else { binds_to.sort(); binds_to.dedup(); @@ -444,9 +449,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some(desc) => format!("`{desc}`"), None => "value".to_string(), }; - self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), ""); + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: place_ty, + place: &place_desc, + span, + }); - use_spans.args_span_label(err, format!("{place_desc} is moved here")); + use_spans.args_subdiag(err, |args_span| { + crate::session_diagnostics::CaptureArgLabel::MoveOutPlace { + place: place_desc, + args_span, + } + }); } } } @@ -534,13 +549,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if binds_to.len() == 1 { - self.note_type_does_not_implement_copy( - err, - &format!("`{}`", self.local_names[*local].unwrap()), - bind_to.ty, - Some(binding_span), - "", - ); + let place_desc = &format!("`{}`", self.local_names[*local].unwrap()); + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: bind_to.ty, + place: &place_desc, + span: binding_span, + }); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 9c907147e5a..eb5f166548d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -231,14 +231,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } if suggest { - borrow_spans.var_span_label( - &mut err, - format!( - "mutable borrow occurs due to use of {} in closure", - self.describe_any_place(access_place.as_ref()), - ), - "mutable", - ); + borrow_spans.var_subdiag( + None, + &mut err, + Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }), + |_kind, var_span| { + let place = self.describe_any_place(access_place.as_ref()); + crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure { + place, + var_span, + } + }, + ); } borrow_span } diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 376415e3d32..aa7cf3578ea 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -3,7 +3,7 @@ use crate::region_infer::RegionInferenceContext; use crate::Upvar; -use rustc_index::vec::{Idx, IndexSlice}; +use rustc_index::vec::IndexSlice; use rustc_middle::mir::{Body, Local}; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_span::source_map::Span; @@ -117,7 +117,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { argument_index: usize, ) -> (Option, Span) { let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs(); - let argument_local = Local::new(implicit_inputs + argument_index + 1); + let argument_local = Local::from_usize(implicit_inputs + argument_index + 1); debug!("get_argument_name_and_span_for_region: argument_local={argument_local:?}"); let argument_name = local_names[argument_local]; diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs index 02ffb51fbb7..87fad9a355d 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -4,7 +4,6 @@ use crate::location::{LocationIndex, LocationTable}; use crate::BorrowIndex; use polonius_engine::AllFacts as PoloniusFacts; use polonius_engine::Atom; -use rustc_index::vec::Idx; use rustc_middle::mir::Local; use rustc_middle::ty::{RegionVid, TyCtxt}; use rustc_mir_dataflow::move_paths::MovePathIndex; @@ -93,13 +92,13 @@ impl AllFactsExt for AllFacts { impl Atom for BorrowIndex { fn index(self) -> usize { - Idx::index(self) + self.as_usize() } } impl Atom for LocationIndex { fn index(self) -> usize { - Idx::index(self) + self.as_usize() } } diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs index 288b7d85be2..08fa912f368 100644 --- a/compiler/rustc_borrowck/src/location.rs +++ b/compiler/rustc_borrowck/src/location.rs @@ -1,6 +1,6 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::vec::IndexVec; use rustc_middle::mir::{BasicBlock, Body, Location}; /// Maps between a MIR Location, which identifies a particular @@ -50,19 +50,19 @@ impl LocationTable { } pub fn all_points(&self) -> impl Iterator { - (0..self.num_points).map(LocationIndex::new) + (0..self.num_points).map(LocationIndex::from_usize) } pub fn start_index(&self, location: Location) -> LocationIndex { let Location { block, statement_index } = location; let start_index = self.statements_before_block[block]; - LocationIndex::new(start_index + statement_index * 2) + LocationIndex::from_usize(start_index + statement_index * 2) } pub fn mid_index(&self, location: Location) -> LocationIndex { let Location { block, statement_index } = location; let start_index = self.statements_before_block[block]; - LocationIndex::new(start_index + statement_index * 2 + 1) + LocationIndex::from_usize(start_index + statement_index * 2 + 1) } pub fn to_location(&self, index: LocationIndex) -> RichLocation { diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 59a3ab3189d..73b8765e57d 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -7,8 +7,8 @@ use rustc_hir::def_id::LocalDefId; use rustc_index::vec::IndexSlice; use rustc_middle::mir::{create_dump_file, dump_enabled, dump_mir, PassWhere}; use rustc_middle::mir::{ - BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, - Promoted, + Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, + START_BLOCK, }; use rustc_middle::ty::{self, OpaqueHiddenType, TyCtxt}; use rustc_span::symbol::sym; @@ -94,8 +94,8 @@ fn populate_polonius_move_facts( } } - let fn_entry_start = location_table - .start_index(Location { block: BasicBlock::from_u32(0u32), statement_index: 0 }); + let fn_entry_start = + location_table.start_index(Location { block: START_BLOCK, statement_index: 0 }); // initialized_at for init in move_data.inits.iter() { diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index a3678929099..bb95101845f 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -184,7 +184,7 @@ pub(crate) enum CaptureVarPathUseCause { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarKind { #[label(borrowck_capture_immute)] - Immute { + Immut { #[primary_span] kind_span: Span, }, @@ -204,16 +204,80 @@ pub(crate) enum CaptureVarKind { pub(crate) enum CaptureVarCause { #[label(borrowck_var_borrow_by_use_place_in_generator)] BorrowUsePlaceGenerator { + is_single_var: bool, place: String, #[primary_span] var_span: Span, }, #[label(borrowck_var_borrow_by_use_place_in_closure)] BorrowUsePlaceClosure { + is_single_var: bool, place: String, #[primary_span] var_span: Span, }, + #[label(borrowck_var_borrow_by_use_in_generator)] + BorrowUseInGenerator { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_borrow_by_use_in_closure)] + BorrowUseInClosure { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_move_by_use_in_generator)] + MoveUseInGenerator { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_move_by_use_in_closure)] + MoveUseInClosure { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_first_borrow_by_use_place_in_generator)] + FirstBorrowUsePlaceGenerator { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_first_borrow_by_use_place_in_closure)] + FirstBorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_second_borrow_by_use_place_in_generator)] + SecondBorrowUsePlaceGenerator { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_second_borrow_by_use_place_in_closure)] + SecondBorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_mutable_borrow_by_use_place_in_closure)] + MutableBorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_partial_var_move_by_use_in_generator)] + PartialMoveUseInGenerator { + #[primary_span] + var_span: Span, + is_partial: bool, + }, + #[label(borrowck_partial_var_move_by_use_in_closure)] + PartialMoveUseInClosure { + #[primary_span] + var_span: Span, + is_partial: bool, + }, } #[derive(Diagnostic)] @@ -239,3 +303,144 @@ pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { #[label] pub param_span: Span, } + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureReasonLabel<'a> { + #[label(borrowck_moved_due_to_call)] + Call { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_moved_due_to_usage_in_operator)] + OperatorUse { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_moved_due_to_implicit_into_iter_call)] + ImplicitCall { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_moved_due_to_method_call)] + MethodCall { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_value_moved_here)] + MovedHere { + #[primary_span] + move_span: Span, + is_partial: bool, + is_move_msg: bool, + is_loop_message: bool, + }, + #[label(borrowck_consider_borrow_type_contents)] + BorrowContent { + #[primary_span] + var_span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureReasonNote { + #[note(borrowck_moved_a_fn_once_in_call)] + FnOnceMoveInCall { + #[primary_span] + var_span: Span, + }, + #[note(borrowck_calling_operator_moves_lhs)] + LhsMoveByOperator { + #[primary_span] + span: Span, + }, + #[note(borrowck_func_take_self_moved_place)] + FuncTakeSelf { + func: String, + place_name: String, + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureReasonSuggest<'tcx> { + #[suggestion( + borrowck_suggest_iterate_over_slice, + applicability = "maybe-incorrect", + code = "&", + style = "verbose" + )] + IterateSlice { + ty: Ty<'tcx>, + #[primary_span] + span: Span, + }, + #[suggestion( + borrowck_suggest_create_freash_reborrow, + applicability = "maybe-incorrect", + code = "as_mut().", + style = "verbose" + )] + FreshReborrow { + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureArgLabel { + #[label(borrowck_value_capture_here)] + Capture { + is_within: bool, + #[primary_span] + args_span: Span, + }, + #[label(borrowck_move_out_place_here)] + MoveOutPlace { + place: String, + #[primary_span] + args_span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum OnClosureNote<'a> { + #[note(borrowck_closure_invoked_twice)] + InvokedTwice { + place_name: &'a str, + #[primary_span] + span: Span, + }, + #[note(borrowck_closure_moved_twice)] + MovedTwice { + place_name: &'a str, + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum TypeNoCopy<'a, 'tcx> { + #[label(borrowck_ty_no_impl_copy)] + Label { + is_partial_move: bool, + ty: Ty<'tcx>, + place: &'a str, + #[primary_span] + span: Span, + }, + #[note(borrowck_ty_no_impl_copy)] + Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, +} diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs index 17e702eb8c5..9250b8d3eaf 100644 --- a/compiler/rustc_borrowck/src/type_check/input_output.rs +++ b/compiler/rustc_borrowck/src/type_check/input_output.rs @@ -7,7 +7,6 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). -use rustc_index::vec::Idx; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty}; @@ -83,7 +82,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } // In MIR, argument N is stored in local N+1. - let local = Local::new(argument_index + 1); + let local = Local::from_usize(argument_index + 1); let mir_input_ty = body.local_decls[local].ty; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 70fddb1057c..74241f722a6 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -19,7 +19,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::BodyOwnerKind; -use rustc_index::vec::{Idx, IndexVec}; +use rustc_index::vec::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt}; @@ -289,7 +289,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// Returns an iterator over all the RegionVids corresponding to /// universally quantified free regions. pub fn universal_regions(&self) -> impl Iterator { - (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::new) + (FIRST_GLOBAL_INDEX..self.num_universals).map(RegionVid::from_usize) } /// Returns `true` if `r` is classified as an local region. diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index dd86977817f..a0a8246be15 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -12,7 +12,6 @@ use crate::MemFlags; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_index::vec::Idx; use rustc_middle::mir::{self, AssertKind, SwitchTargets}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; @@ -369,7 +368,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if self.fn_abi.c_variadic { // The `VaList` "spoofed" argument is just after all the real arguments. let va_list_arg_idx = self.fn_abi.args.len(); - match self.locals[mir::Local::new(1 + va_list_arg_idx)] { + match self.locals[mir::Local::from_usize(1 + va_list_arg_idx)] { LocalRef::Place(va_list) => { bx.va_end(va_list.llval); } diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 557e721249d..015a9beab83 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -211,18 +211,19 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let variant_index_relative = u32::try_from(variant_index_relative) .expect("we checked that this fits into a u32"); // Then computing the absolute variant idx should not overflow any more. - let variant_index = variants_start - .checked_add(variant_index_relative) - .expect("overflow computing absolute variant idx"); - let variants_len = op + let variant_index = VariantIdx::from_u32( + variants_start + .checked_add(variant_index_relative) + .expect("overflow computing absolute variant idx"), + ); + let variants = op .layout .ty .ty_adt_def() .expect("tagged layout for non adt") - .variants() - .len(); - assert!(usize::try_from(variant_index).unwrap() < variants_len); - VariantIdx::from_u32(variant_index) + .variants(); + assert!(variant_index < variants.next_index()); + variant_index } else { untagged_variant } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 13442c31649..525acfdaa81 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -17,7 +17,6 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{BytePos, Span, DUMMY_SP}; -use rustc_target::abi::FieldIdx; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::ObligationCause; @@ -875,7 +874,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant.fields.len() == 1 }) .filter_map(|variant| { - let sole_field = &variant.fields[FieldIdx::from_u32(0)]; + let sole_field = &variant.single_field(); let field_is_local = sole_field.did.is_local(); let field_is_accessible = diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 106f5bcd755..0fdb29a5e48 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -4,7 +4,7 @@ use rustc_hir as hir; use rustc_index::vec::Idx; use rustc_middle::ty::layout::{LayoutError, SizeSkeleton}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_target::abi::{FieldIdx, Pointer, VariantIdx}; +use rustc_target::abi::{Pointer, VariantIdx}; use super::FnCtxt; @@ -28,7 +28,7 @@ fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { } if def.variant(data_idx).fields.len() == 1 { - return def.variant(data_idx).fields[FieldIdx::from_u32(0)].ty(tcx, substs); + return def.variant(data_idx).single_field().ty(tcx, substs); } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 4dc5fc451dd..d885d040707 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -10,7 +10,6 @@ use rustc_middle::traits::{ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self as ty, GenericArgKind, IsSuggestable, Ty, TypeVisitableExt}; use rustc_span::{sym, BytePos, Span}; -use rustc_target::abi::FieldIdx; use crate::errors::{ ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes, @@ -114,7 +113,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn) }) .filter_map(|variant| { - let sole_field = &variant.fields[FieldIdx::from_u32(0)]; + let sole_field = &variant.single_field(); let sole_field_ty = sole_field.ty(self.tcx, substs); if self.same_type_modulo_infer(sole_field_ty, exp_found.found) { let variant_path = diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 80a64e59c0f..d677d51881e 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -569,36 +569,50 @@ trait UnusedDelimLint { } } - // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }` - let lhs_needs_parens = { + // Check if LHS needs parens to prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }`. + { let mut innermost = inner; loop { innermost = match &innermost.kind { - ExprKind::Binary(_, lhs, _rhs) => lhs, + ExprKind::Binary(_op, lhs, _rhs) => lhs, ExprKind::Call(fn_, _params) => fn_, ExprKind::Cast(expr, _ty) => expr, ExprKind::Type(expr, _ty) => expr, ExprKind::Index(base, _subscript) => base, - _ => break false, + _ => break, }; if !classify::expr_requires_semi_to_be_stmt(innermost) { - break true; + return true; } } - }; + } - lhs_needs_parens - || (followed_by_block - && match &inner.kind { - ExprKind::Ret(_) - | ExprKind::Break(..) - | ExprKind::Yield(..) - | ExprKind::Yeet(..) => true, - ExprKind::Range(_lhs, Some(rhs), _limits) => { - matches!(rhs.kind, ExprKind::Block(..)) - } - _ => parser::contains_exterior_struct_lit(&inner), - }) + // Check if RHS needs parens to prevent false-positives in cases like `if (() == return) {}`. + if !followed_by_block { + return false; + } + let mut innermost = inner; + loop { + innermost = match &innermost.kind { + ExprKind::Unary(_op, expr) => expr, + ExprKind::Binary(_op, _lhs, rhs) => rhs, + ExprKind::AssignOp(_op, _lhs, rhs) => rhs, + ExprKind::Assign(_lhs, rhs, _span) => rhs, + + ExprKind::Ret(_) | ExprKind::Yield(..) | ExprKind::Yeet(..) => return true, + + ExprKind::Break(_label, None) => return false, + ExprKind::Break(_label, Some(break_expr)) => { + return matches!(break_expr.kind, ExprKind::Block(..)); + } + + ExprKind::Range(_lhs, Some(rhs), _limits) => { + return matches!(rhs.kind, ExprKind::Block(..)); + } + + _ => return parser::contains_exterior_struct_lit(&inner), + } + } } fn emit_unused_delims_expr( diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 657b903e0a8..1109e308cf0 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -823,6 +823,7 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::TraitAlias | DefKind::AssocTy | DefKind::TyParam + | DefKind::ConstParam | DefKind::Fn | DefKind::Const | DefKind::Static(_) @@ -837,8 +838,7 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::Impl { .. } | DefKind::Closure | DefKind::Generator => true, - DefKind::ConstParam - | DefKind::ExternCrate + DefKind::ExternCrate | DefKind::Use | DefKind::ForeignMod | DefKind::ImplTraitPlaceholder diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index e63121475a1..c4e41e00520 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -392,10 +392,8 @@ pub type QueryOutlivesConstraint<'tcx> = (ty::OutlivesPredicate, Region<'tcx>>, ConstraintCategory<'tcx>); TrivialTypeTraversalAndLiftImpls! { - for <'tcx> { - crate::infer::canonical::Certainty, - crate::infer::canonical::CanonicalTyVarKind, - } + crate::infer::canonical::Certainty, + crate::infer::canonical::CanonicalTyVarKind, } impl<'tcx> CanonicalVarValues<'tcx> { diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index 89014f62d4d..cd1c6c330bc 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -43,34 +43,26 @@ macro_rules! span_bug { #[macro_export] macro_rules! CloneLiftImpls { - (for <$tcx:lifetime> { $($ty:ty,)+ }) => { + ($($ty:ty,)+) => { $( - impl<$tcx> $crate::ty::Lift<$tcx> for $ty { + impl<'tcx> $crate::ty::Lift<'tcx> for $ty { type Lifted = Self; - fn lift_to_tcx(self, _: $crate::ty::TyCtxt<$tcx>) -> Option { + fn lift_to_tcx(self, _: $crate::ty::TyCtxt<'tcx>) -> Option { Some(self) } } )+ }; - - ($($ty:ty,)+) => { - CloneLiftImpls! { - for <'tcx> { - $($ty,)+ - } - } - }; } /// Used for types that are `Copy` and which **do not care arena /// allocated data** (i.e., don't need to be folded). #[macro_export] macro_rules! TrivialTypeTraversalImpls { - (for <$tcx:lifetime> { $($ty:ty,)+ }) => { + ($($ty:ty,)+) => { $( - impl<$tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<$tcx>> for $ty { - fn try_fold_with>>( + impl<'tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<'tcx>> for $ty { + fn try_fold_with>>( self, _: &mut F, ) -> ::std::result::Result { @@ -78,7 +70,7 @@ macro_rules! TrivialTypeTraversalImpls { } #[inline] - fn fold_with>>( + fn fold_with>>( self, _: &mut F, ) -> Self { @@ -86,9 +78,9 @@ macro_rules! TrivialTypeTraversalImpls { } } - impl<$tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<$tcx>> for $ty { + impl<'tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<'tcx>> for $ty { #[inline] - fn visit_with>>( + fn visit_with>>( &self, _: &mut F) -> ::std::ops::ControlFlow @@ -98,14 +90,6 @@ macro_rules! TrivialTypeTraversalImpls { } )+ }; - - ($($ty:ty,)+) => { - TrivialTypeTraversalImpls! { - for<'tcx> { - $($ty,)+ - } - } - }; } #[macro_export] diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 2ea8602af12..f985aae9a22 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -714,9 +714,7 @@ pub enum BindingForm<'tcx> { } TrivialTypeTraversalAndLiftImpls! { - for<'tcx> { - BindingForm<'tcx>, - } + BindingForm<'tcx>, } mod binding_form_impl { diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 9881583214e..ace856b9f95 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -25,9 +25,7 @@ TrivialTypeTraversalAndLiftImpls! { } TrivialTypeTraversalImpls! { - for <'tcx> { - ConstValue<'tcx>, - } + ConstValue<'tcx>, } impl<'tcx> TypeFoldable> for &'tcx [InlineAsmTemplatePiece] { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 63f7cc2ee73..e5356581e6e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1329,9 +1329,12 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable // This is the impl for `&'a InternalSubsts<'a>`. nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} -CloneLiftImpls! { for<'tcx> { - Constness, traits::WellFormedLoc, ImplPolarity, crate::mir::ReturnConstraint, -} } +CloneLiftImpls! { + Constness, + traits::WellFormedLoc, + ImplPolarity, + crate::mir::ReturnConstraint, +} macro_rules! sty_debug_print { ($fmt: expr, $ctxt: expr, $($variant: ident),*) => {{ diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index bc202b027bd..5501763d66f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1963,6 +1963,16 @@ impl VariantDef { pub fn ctor_def_id(&self) -> Option { self.ctor.map(|(_, def_id)| def_id) } + + /// Returns the one field in this variant. + /// + /// `panic!`s if there are no fields or multiple fields. + #[inline] + pub fn single_field(&self) -> &FieldDef { + assert!(self.fields.len() == 1); + + &self.fields[FieldIdx::from_u32(0)] + } } impl PartialEq for VariantDef { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 619fcea8b7d..7706fdddeb8 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -276,9 +276,7 @@ TrivialTypeTraversalAndLiftImpls! { } TrivialTypeTraversalAndLiftImpls! { - for<'tcx> { - ty::ValTree<'tcx>, - } + ty::ValTree<'tcx>, } /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index e5c3fa5646a..8ee08c5be34 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -9,7 +9,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location, Operand, Terminator, TerminatorKind, RETURN_PLACE}; -use rustc_middle::ty::{self, DeducedParamAttrs, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, DeducedParamAttrs, Ty, TyCtxt}; use rustc_session::config::OptLevel; /// A visitor that determines which arguments have been mutated. We can't use the mutability field @@ -198,11 +198,12 @@ pub fn deduced_param_attrs<'tcx>( // see [1]. // // [1]: https://github.com/rust-lang/rust/pull/103172#discussion_r999139997 + let param_env = tcx.param_env_reveal_all_normalized(def_id); let mut deduced_param_attrs = tcx.arena.alloc_from_iter( body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map( |(arg_index, local_decl)| DeducedParamAttrs { read_only: !deduce_read_only.mutable_args.contains(arg_index) - && local_decl.ty.is_freeze(tcx, ParamEnv::reveal_all()), + && local_decl.ty.is_freeze(tcx, param_env), }, ), ); diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index b354dca7cc4..055682a1509 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -627,9 +627,9 @@ passes_attr_application_struct_enum_union = attribute should be applied to a struct, enum, or union .label = not a struct, enum, or union -passes_attr_application_struct_enum_function_union = - attribute should be applied to a struct, enum, function, or union - .label = not a struct, enum, function, or union +passes_attr_application_struct_enum_function_method_union = + attribute should be applied to a struct, enum, function, associated function, or union + .label = not a struct, enum, function, associated function, or union passes_transparent_incompatible = transparent {$target} cannot have other repr hints diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 80a93da2b45..085a28626ea 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1728,7 +1728,9 @@ impl CheckAttrVisitor<'_> { } } sym::align => { - if let (Target::Fn, false) = (target, self.tcx.features().fn_align) { + if let (Target::Fn | Target::Method(MethodKind::Inherent), false) = + (target, self.tcx.features().fn_align) + { feature_err( &self.tcx.sess.parse_sess, sym::fn_align, @@ -1739,10 +1741,14 @@ impl CheckAttrVisitor<'_> { } match target { - Target::Struct | Target::Union | Target::Enum | Target::Fn => continue, + Target::Struct + | Target::Union + | Target::Enum + | Target::Fn + | Target::Method(_) => continue, _ => { self.tcx.sess.emit_err( - errors::AttrApplication::StructEnumFunctionUnion { + errors::AttrApplication::StructEnumFunctionMethodUnion { hint_span: hint.span(), span, }, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 139ba8c9677..e8603b3a2f1 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1355,8 +1355,8 @@ pub enum AttrApplication { #[label] span: Span, }, - #[diag(passes_attr_application_struct_enum_function_union, code = "E0517")] - StructEnumFunctionUnion { + #[diag(passes_attr_application_struct_enum_function_method_union, code = "E0517")] + StructEnumFunctionMethodUnion { #[primary_span] hint_span: Span, #[label] diff --git a/compiler/rustc_query_system/src/dep_graph/query.rs b/compiler/rustc_query_system/src/dep_graph/query.rs index 27b3b5e1366..9dcc41e2726 100644 --- a/compiler/rustc_query_system/src/dep_graph/query.rs +++ b/compiler/rustc_query_system/src/dep_graph/query.rs @@ -24,10 +24,7 @@ impl DepGraphQuery { pub fn push(&mut self, index: DepNodeIndex, node: DepNode, edges: &[DepNodeIndex]) { let source = self.graph.add_node(node); - if index.index() >= self.dep_index_to_index.len() { - self.dep_index_to_index.resize(index.index() + 1, None); - } - self.dep_index_to_index[index] = Some(source); + self.dep_index_to_index.insert(index, source); self.indices.insert(node, source); for &target in edges.iter() { diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index ada868705c7..dfdd52720a0 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -11,12 +11,13 @@ use super::{CanonicalGoal, Certainty, EvalCtxt, Goal}; use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer}; use crate::solve::{CanonicalResponse, QueryResult, Response}; +use rustc_index::vec::IndexVec; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; use rustc_infer::infer::canonical::CanonicalVarValues; use rustc_infer::infer::canonical::{CanonicalExt, QueryRegionConstraints}; use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::solve::{ExternalConstraints, ExternalConstraintsData}; -use rustc_middle::ty::{self, GenericArgKind}; +use rustc_middle::ty::{self, BoundVar, GenericArgKind}; use rustc_span::DUMMY_SP; use std::iter; use std::ops::Deref; @@ -139,25 +140,25 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // // We therefore instantiate the existential variable in the canonical response with the // inference variable of the input right away, which is more performant. - let mut opt_values = vec![None; response.variables.len()]; + let mut opt_values = IndexVec::from_elem_n(None, response.variables.len()); for (original_value, result_value) in iter::zip(original_values, var_values.var_values) { match result_value.unpack() { GenericArgKind::Type(t) => { if let &ty::Bound(debruijn, b) = t.kind() { assert_eq!(debruijn, ty::INNERMOST); - opt_values[b.var.index()] = Some(*original_value); + opt_values[b.var] = Some(*original_value); } } GenericArgKind::Lifetime(r) => { if let ty::ReLateBound(debruijn, br) = *r { assert_eq!(debruijn, ty::INNERMOST); - opt_values[br.var.index()] = Some(*original_value); + opt_values[br.var] = Some(*original_value); } } GenericArgKind::Const(c) => { if let ty::ConstKind::Bound(debrujin, b) = c.kind() { assert_eq!(debrujin, ty::INNERMOST); - opt_values[b.index()] = Some(*original_value); + opt_values[b] = Some(*original_value); } } } @@ -180,7 +181,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { // more placeholders then they should be able to. However the inference variables have // to "come from somewhere", so by equating them with the original values of the caller // later on, we pull them down into their correct universe again. - if let Some(v) = opt_values[index] { + if let Some(v) = opt_values[BoundVar::from_usize(index)] { v } else { self.infcx.instantiate_canonical_var(DUMMY_SP, info, |_| prev_universe) diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index 6c181039730..8c3cb228322 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -33,144 +33,3 @@ macro_rules! TrivialTypeTraversalImpls { )+ }; } - -macro_rules! EnumTypeTraversalImpl { - (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path { - $($variants:tt)* - } $(where $($wc:tt)*)*) => { - impl<$($p),*> $crate::fold::TypeFoldable<$tcx> for $s - $(where $($wc)*)* - { - fn try_fold_with>( - self, - folder: &mut V, - ) -> ::std::result::Result { - EnumTypeTraversalImpl!(@FoldVariants(self, folder) input($($variants)*) output()) - } - } - }; - - (impl<$($p:tt),*> TypeVisitable<$tcx:tt> for $s:path { - $($variants:tt)* - } $(where $($wc:tt)*)*) => { - impl<$($p),*> $crate::visit::TypeVisitable<$tcx> for $s - $(where $($wc)*)* - { - fn visit_with>( - &self, - visitor: &mut V, - ) -> ::std::ops::ControlFlow { - EnumTypeTraversalImpl!(@VisitVariants(self, visitor) input($($variants)*) output()) - } - } - }; - - (@FoldVariants($this:expr, $folder:expr) input() output($($output:tt)*)) => { - Ok(match $this { - $($output)* - }) - }; - - (@FoldVariants($this:expr, $folder:expr) - input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*) - output( $($output:tt)*) ) => { - EnumTypeTraversalImpl!( - @FoldVariants($this, $folder) - input($($input)*) - output( - $variant ( $($variant_arg),* ) => { - $variant ( - $($crate::fold::TypeFoldable::try_fold_with($variant_arg, $folder)?),* - ) - } - $($output)* - ) - ) - }; - - (@FoldVariants($this:expr, $folder:expr) - input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*) - output( $($output:tt)*) ) => { - EnumTypeTraversalImpl!( - @FoldVariants($this, $folder) - input($($input)*) - output( - $variant { $($variant_arg),* } => { - $variant { - $($variant_arg: $crate::fold::TypeFoldable::fold_with( - $variant_arg, $folder - )?),* } - } - $($output)* - ) - ) - }; - - (@FoldVariants($this:expr, $folder:expr) - input( ($variant:path), $($input:tt)*) - output( $($output:tt)*) ) => { - EnumTypeTraversalImpl!( - @FoldVariants($this, $folder) - input($($input)*) - output( - $variant => { $variant } - $($output)* - ) - ) - }; - - (@VisitVariants($this:expr, $visitor:expr) input() output($($output:tt)*)) => { - match $this { - $($output)* - } - }; - - (@VisitVariants($this:expr, $visitor:expr) - input( ($variant:path) ( $($variant_arg:ident),* ) , $($input:tt)*) - output( $($output:tt)*) ) => { - EnumTypeTraversalImpl!( - @VisitVariants($this, $visitor) - input($($input)*) - output( - $variant ( $($variant_arg),* ) => { - $($crate::visit::TypeVisitable::visit_with( - $variant_arg, $visitor - )?;)* - ::std::ops::ControlFlow::Continue(()) - } - $($output)* - ) - ) - }; - - (@VisitVariants($this:expr, $visitor:expr) - input( ($variant:path) { $($variant_arg:ident),* $(,)? } , $($input:tt)*) - output( $($output:tt)*) ) => { - EnumTypeTraversalImpl!( - @VisitVariants($this, $visitor) - input($($input)*) - output( - $variant { $($variant_arg),* } => { - $($crate::visit::TypeVisitable::visit_with( - $variant_arg, $visitor - )?;)* - ::std::ops::ControlFlow::Continue(()) - } - $($output)* - ) - ) - }; - - (@VisitVariants($this:expr, $visitor:expr) - input( ($variant:path), $($input:tt)*) - output( $($output:tt)*) ) => { - EnumTypeTraversalImpl!( - @VisitVariants($this, $visitor) - input($($input)*) - output( - $variant => { ::std::ops::ControlFlow::Continue(()) } - $($output)* - ) - ) - }; -} diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index 3ebe241042f..c90c86b7690 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -70,30 +70,40 @@ impl, B: TypeVisitable, C: TypeVisitable> } } -EnumTypeTraversalImpl! { - impl TypeFoldable for Option { - (Some)(a), - (None), - } where I: Interner, T: TypeFoldable -} -EnumTypeTraversalImpl! { - impl TypeVisitable for Option { - (Some)(a), - (None), - } where I: Interner, T: TypeVisitable +impl> TypeFoldable for Option { + fn try_fold_with>(self, folder: &mut F) -> Result { + Ok(match self { + Some(v) => Some(v.try_fold_with(folder)?), + None => None, + }) + } } -EnumTypeTraversalImpl! { - impl TypeFoldable for Result { - (Ok)(a), - (Err)(a), - } where I: Interner, T: TypeFoldable, E: TypeFoldable, +impl> TypeVisitable for Option { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + match self { + Some(v) => v.visit_with(visitor), + None => ControlFlow::Continue(()), + } + } } -EnumTypeTraversalImpl! { - impl TypeVisitable for Result { - (Ok)(a), - (Err)(a), - } where I: Interner, T: TypeVisitable, E: TypeVisitable, + +impl, E: TypeFoldable> TypeFoldable for Result { + fn try_fold_with>(self, folder: &mut F) -> Result { + Ok(match self { + Ok(v) => Ok(v.try_fold_with(folder)?), + Err(e) => Err(e.try_fold_with(folder)?), + }) + } +} + +impl, E: TypeVisitable> TypeVisitable for Result { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + match self { + Ok(v) => v.visit_with(visitor), + Err(e) => e.visit_with(visitor), + } + } } impl> TypeFoldable for Rc { diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 62347f169a5..d7c6a884fc8 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -84,8 +84,8 @@ Note: The [`-g` flag][option-g-debug] is an alias for `-C debuginfo=2`. This flag controls whether or not the linker includes its default libraries. It takes one of the following values: -* `y`, `yes`, `on`, `true` or no value: include default libraries (the default). -* `n`, `no`, `off` or `false`: exclude default libraries. +* `y`, `yes`, `on`, `true`: include default libraries. +* `n`, `no`, `off` or `false` or no value: exclude default libraries (the default). For example, for gcc flavor linkers, this issues the `-nodefaultlibs` flag to the linker. diff --git a/tests/codegen/align-fn.rs b/tests/codegen/align-fn.rs index c5886cf2808..f3cf614e185 100644 --- a/tests/codegen/align-fn.rs +++ b/tests/codegen/align-fn.rs @@ -7,3 +7,43 @@ #[no_mangle] #[repr(align(16))] pub fn fn_align() {} + +pub struct A; + +impl A { + // CHECK: align 16 + #[no_mangle] + #[repr(align(16))] + pub fn method_align(self) {} + + // CHECK: align 16 + #[no_mangle] + #[repr(align(16))] + pub fn associated_fn() {} +} + +trait T: Sized { + fn trait_fn() {} + + // CHECK: align 32 + #[repr(align(32))] + fn trait_method(self) {} +} + +impl T for A { + // CHECK: align 16 + #[no_mangle] + #[repr(align(16))] + fn trait_fn() {} + + // CHECK: align 16 + #[no_mangle] + #[repr(align(16))] + fn trait_method(self) {} +} + +impl T for () {} + +pub fn foo() { + ().trait_method(); +} diff --git a/tests/codegen/thread-local.rs b/tests/codegen/thread-local.rs index aa7fab7fb17..caf0366d2c1 100644 --- a/tests/codegen/thread-local.rs +++ b/tests/codegen/thread-local.rs @@ -20,8 +20,8 @@ thread_local!(static A: Cell = const { Cell::new(1) }); // CHECK-LABEL: @get #[no_mangle] fn get() -> u32 { - // CHECK: %0 = load i32, {{.*}}[[TLS]]{{.*}} - // CHECK-NEXT: ret i32 %0 + // CHECK: [[RET_0:%.+]] = load i32, {{.*}}[[TLS]]{{.*}} + // CHECK-NEXT: ret i32 [[RET_0]] A.with(|a| a.get()) } @@ -36,8 +36,8 @@ fn set(v: u32) { // CHECK-LABEL: @get_aux #[no_mangle] fn get_aux() -> u64 { - // CHECK: %0 = load i64, {{.*}}[[TLS_AUX]] - // CHECK-NEXT: ret i64 %0 + // CHECK: [[RET_1:%.+]] = load i64, {{.*}}[[TLS_AUX]] + // CHECK-NEXT: ret i64 [[RET_1]] aux::A.with(|a| a.get()) } diff --git a/tests/ui/attributes/invalid-repr.rs b/tests/ui/attributes/invalid-repr.rs new file mode 100644 index 00000000000..10a487c127e --- /dev/null +++ b/tests/ui/attributes/invalid-repr.rs @@ -0,0 +1,5 @@ +#[repr(align(16))] +//~^ ERROR attribute should be applied to a struct, enum, function, associated function, or union +pub type Foo = i32; + +fn main() {} diff --git a/tests/ui/attributes/invalid-repr.stderr b/tests/ui/attributes/invalid-repr.stderr new file mode 100644 index 00000000000..98a6a24b3c4 --- /dev/null +++ b/tests/ui/attributes/invalid-repr.stderr @@ -0,0 +1,12 @@ +error[E0517]: attribute should be applied to a struct, enum, function, associated function, or union + --> $DIR/invalid-repr.rs:1:8 + | +LL | #[repr(align(16))] + | ^^^^^^^^^ +LL | +LL | pub type Foo = i32; + | ------------------- not a struct, enum, function, associated function, or union + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0517`. diff --git a/tests/ui/codegen/freeze-on-polymorphic-projection.rs b/tests/ui/codegen/freeze-on-polymorphic-projection.rs new file mode 100644 index 00000000000..edc79f8fd94 --- /dev/null +++ b/tests/ui/codegen/freeze-on-polymorphic-projection.rs @@ -0,0 +1,19 @@ +// build-pass +// compile-flags: -Copt-level=1 --crate-type=lib + +#![feature(specialization)] +//~^ WARN the feature `specialization` is incomplete + +pub unsafe trait Storage { + type Handle; +} + +pub unsafe trait MultipleStorage: Storage {} + +default unsafe impl Storage for S where S: MultipleStorage {} + +// Make sure that we call is_freeze on `(S::Handle,)` in the param-env of `ice`, +// instead of in an empty, reveal-all param-env. +pub fn ice(boxed: (S::Handle,)) -> (S::Handle,) { + boxed +} diff --git a/tests/ui/codegen/freeze-on-polymorphic-projection.stderr b/tests/ui/codegen/freeze-on-polymorphic-projection.stderr new file mode 100644 index 00000000000..903cb2ff6aa --- /dev/null +++ b/tests/ui/codegen/freeze-on-polymorphic-projection.stderr @@ -0,0 +1,12 @@ +warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/freeze-on-polymorphic-projection.rs:4:12 + | +LL | #![feature(specialization)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #31844 for more information + = help: consider using `min_specialization` instead, which is more stable and complete + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs b/tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs new file mode 100644 index 00000000000..85b0c6c9df8 --- /dev/null +++ b/tests/ui/consts/auxiliary/foreign-generic-mismatch-with-const-arg.rs @@ -0,0 +1 @@ +pub fn test() {} diff --git a/tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs b/tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs new file mode 100644 index 00000000000..7590abbd827 --- /dev/null +++ b/tests/ui/consts/foreign-generic-mismatch-with-const-arg.rs @@ -0,0 +1,8 @@ +// aux-build: foreign-generic-mismatch-with-const-arg.rs + +extern crate foreign_generic_mismatch_with_const_arg; + +fn main() { + foreign_generic_mismatch_with_const_arg::test::<1>(); + //~^ ERROR function takes 2 generic arguments but 1 generic argument was supplied +} diff --git a/tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr b/tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr new file mode 100644 index 00000000000..4cc03a20514 --- /dev/null +++ b/tests/ui/consts/foreign-generic-mismatch-with-const-arg.stderr @@ -0,0 +1,21 @@ +error[E0107]: function takes 2 generic arguments but 1 generic argument was supplied + --> $DIR/foreign-generic-mismatch-with-const-arg.rs:6:46 + | +LL | foreign_generic_mismatch_with_const_arg::test::<1>(); + | ^^^^ - supplied 1 generic argument + | | + | expected 2 generic arguments + | +note: function defined here, with 2 generic parameters: `N`, `T` + --> $DIR/auxiliary/foreign-generic-mismatch-with-const-arg.rs:1:8 + | +LL | pub fn test() {} + | ^^^^ -------------- - +help: add missing generic argument + | +LL | foreign_generic_mismatch_with_const_arg::test::<1, T>(); + | +++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed index 71ebaea8ed2..9c52ca5577e 100644 --- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.fixed @@ -21,17 +21,32 @@ fn lint_on_top_level() { let _ = |a: u8| 0; //~ ERROR unnecessary parentheses around pattern } -fn _no_lint_attr() { +fn no_lint_attr() { let _x = #[allow(dead_code)] (1 + 2); } -fn _no_lint_yeet() -> Result<(), ()> { +fn no_lint_yeet() -> Result<(), ()> { #[allow(unreachable_code)] if (do yeet) {} Ok(()) } +fn no_lint_ops() { + #![allow(unreachable_code, irrefutable_let_patterns)] + if ((..{}) == ..{}) {} + if (!return) {} + loop { match (() = () = () = break {}) {} } + while let () = (*&mut false |= true && return) {} +} + +fn lint_break_if_not_followed_by_block() { + #![allow(unreachable_code)] + loop { if break {} } //~ ERROR unnecessary parentheses + loop { if break ({ println!("hello") }) {} } //~ ERROR unnecessary parentheses + loop { if (break { println!("hello") }) {} } +} + // Don't lint in these cases (#64106). fn or_patterns_no_lint() { match Box::new(0) { diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs index 28b662dd024..196ecf0c1bb 100644 --- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.rs @@ -21,17 +21,32 @@ fn lint_on_top_level() { let _ = |(a): u8| 0; //~ ERROR unnecessary parentheses around pattern } -fn _no_lint_attr() { +fn no_lint_attr() { let _x = #[allow(dead_code)] (1 + 2); } -fn _no_lint_yeet() -> Result<(), ()> { +fn no_lint_yeet() -> Result<(), ()> { #[allow(unreachable_code)] if (do yeet) {} Ok(()) } +fn no_lint_ops() { + #![allow(unreachable_code, irrefutable_let_patterns)] + if ((..{}) == ..{}) {} + if (!return) {} + loop { match (() = () = () = break {}) {} } + while let () = (*&mut false |= true && return) {} +} + +fn lint_break_if_not_followed_by_block() { + #![allow(unreachable_code)] + loop { if (break) {} } //~ ERROR unnecessary parentheses + loop { if (break ({ println!("hello") })) {} } //~ ERROR unnecessary parentheses + loop { if (break { println!("hello") }) {} } +} + // Don't lint in these cases (#64106). fn or_patterns_no_lint() { match Box::new(0) { diff --git a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr index a5e69e6d938..f916bba8194 100644 --- a/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr +++ b/tests/ui/lint/unused/issue-54538-unused-parens-lint.stderr @@ -75,8 +75,32 @@ LL - let _ = |(a): u8| 0; LL + let _ = |a: u8| 0; | +error: unnecessary parentheses around `if` condition + --> $DIR/issue-54538-unused-parens-lint.rs:45:15 + | +LL | loop { if (break) {} } + | ^ ^ + | +help: remove these parentheses + | +LL - loop { if (break) {} } +LL + loop { if break {} } + | + +error: unnecessary parentheses around `if` condition + --> $DIR/issue-54538-unused-parens-lint.rs:46:15 + | +LL | loop { if (break ({ println!("hello") })) {} } + | ^ ^ + | +help: remove these parentheses + | +LL - loop { if (break ({ println!("hello") })) {} } +LL + loop { if break ({ println!("hello") }) {} } + | + error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:56:12 + --> $DIR/issue-54538-unused-parens-lint.rs:71:12 | LL | if let (0 | 1) = 0 {} | ^ ^ @@ -88,7 +112,7 @@ LL + if let 0 | 1 = 0 {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:57:13 + --> $DIR/issue-54538-unused-parens-lint.rs:72:13 | LL | if let ((0 | 1),) = (0,) {} | ^ ^ @@ -100,7 +124,7 @@ LL + if let (0 | 1,) = (0,) {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:58:13 + --> $DIR/issue-54538-unused-parens-lint.rs:73:13 | LL | if let [(0 | 1)] = [0] {} | ^ ^ @@ -112,7 +136,7 @@ LL + if let [0 | 1] = [0] {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:59:16 + --> $DIR/issue-54538-unused-parens-lint.rs:74:16 | LL | if let 0 | (1 | 2) = 0 {} | ^ ^ @@ -124,7 +148,7 @@ LL + if let 0 | 1 | 2 = 0 {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:61:15 + --> $DIR/issue-54538-unused-parens-lint.rs:76:15 | LL | if let TS((0 | 1)) = TS(0) {} | ^ ^ @@ -136,7 +160,7 @@ LL + if let TS(0 | 1) = TS(0) {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:63:20 + --> $DIR/issue-54538-unused-parens-lint.rs:78:20 | LL | if let NS { f: (0 | 1) } = (NS { f: 0 }) {} | ^ ^ @@ -148,7 +172,7 @@ LL + if let NS { f: 0 | 1 } = (NS { f: 0 }) {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:73:9 + --> $DIR/issue-54538-unused-parens-lint.rs:88:9 | LL | (_) => {} | ^ ^ @@ -160,7 +184,7 @@ LL + _ => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:74:9 + --> $DIR/issue-54538-unused-parens-lint.rs:89:9 | LL | (y) => {} | ^ ^ @@ -172,7 +196,7 @@ LL + y => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:75:9 + --> $DIR/issue-54538-unused-parens-lint.rs:90:9 | LL | (ref r) => {} | ^ ^ @@ -184,7 +208,7 @@ LL + ref r => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:76:9 + --> $DIR/issue-54538-unused-parens-lint.rs:91:9 | LL | (e @ 1...2) => {} | ^ ^ @@ -196,7 +220,7 @@ LL + e @ 1...2 => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:82:9 + --> $DIR/issue-54538-unused-parens-lint.rs:97:9 | LL | (e @ &(1...2)) => {} | ^ ^ @@ -208,7 +232,7 @@ LL + e @ &(1...2) => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:83:10 + --> $DIR/issue-54538-unused-parens-lint.rs:98:10 | LL | &(_) => {} | ^ ^ @@ -220,7 +244,7 @@ LL + &_ => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:94:9 + --> $DIR/issue-54538-unused-parens-lint.rs:109:9 | LL | (_) => {} | ^ ^ @@ -232,7 +256,7 @@ LL + _ => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:95:9 + --> $DIR/issue-54538-unused-parens-lint.rs:110:9 | LL | (y) => {} | ^ ^ @@ -244,7 +268,7 @@ LL + y => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:96:9 + --> $DIR/issue-54538-unused-parens-lint.rs:111:9 | LL | (ref r) => {} | ^ ^ @@ -256,7 +280,7 @@ LL + ref r => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:97:9 + --> $DIR/issue-54538-unused-parens-lint.rs:112:9 | LL | (e @ 1..=2) => {} | ^ ^ @@ -268,7 +292,7 @@ LL + e @ 1..=2 => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:103:9 + --> $DIR/issue-54538-unused-parens-lint.rs:118:9 | LL | (e @ &(1..=2)) => {} | ^ ^ @@ -280,7 +304,7 @@ LL + e @ &(1..=2) => {} | error: unnecessary parentheses around pattern - --> $DIR/issue-54538-unused-parens-lint.rs:104:10 + --> $DIR/issue-54538-unused-parens-lint.rs:119:10 | LL | &(_) => {} | ^ ^ @@ -291,5 +315,5 @@ LL - &(_) => {} LL + &_ => {} | -error: aborting due to 24 previous errors +error: aborting due to 26 previous errors