]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_typeck/src/check/upvar.rs
New upstream version 1.62.1+dfsg1
[rustc.git] / compiler / rustc_typeck / src / check / upvar.rs
index 0b343a5f905c467bbef1c2366bc097a307aac262..fee2efd5804f0f0538ab733b339728e424cf8408 100644 (file)
@@ -5,9 +5,9 @@
 //! immutable "borrow kind" (see `ty::BorrowKind` for details) and then
 //! "escalating" the kind as needed. The borrow kind proceeds according to
 //! the following lattice:
-//!
-//!     ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow
-//!
+//! ```ignore (not-rust)
+//! ty::ImmBorrow -> ty::UniqueImmBorrow -> ty::MutBorrow
+//! ```
 //! So, for example, if we see an assignment `x = 5` to an upvar `x`, we
 //! will promote its borrow kind to mutable borrow. If we see an `&mut x`
 //! we'll do the same. Naturally, this applies not just to the upvar, but
@@ -33,7 +33,7 @@
 use super::FnCtxt;
 
 use crate::expr_use_visitor as euv;
-use rustc_errors::Applicability;
+use rustc_errors::{Applicability, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::def_id::LocalDefId;
@@ -46,7 +46,7 @@ use rustc_middle::ty::{
 };
 use rustc_session::lint;
 use rustc_span::sym;
-use rustc_span::{BytePos, MultiSpan, Pos, Span, Symbol};
+use rustc_span::{BytePos, Pos, Span, Symbol};
 use rustc_trait_selection::infer::InferCtxtExt;
 
 use rustc_data_structures::stable_map::FxHashMap;
@@ -447,16 +447,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///       the existing min_capture map that is stored in TypeckResults.
     ///
     /// Eg:
-    /// ```rust,no_run
+    /// ```
+    /// #[derive(Debug)]
     /// struct Point { x: i32, y: i32 }
     ///
-    /// let s: String;  // hir_id_s
-    /// let mut p: Point; // his_id_p
+    /// let s = String::from("s");  // hir_id_s
+    /// let mut p = Point { x: 2, y: -2 }; // his_id_p
     /// let c = || {
-    ///        println!("{s}");  // L1
+    ///        println!("{s:?}");  // L1
     ///        p.x += 10;  // L2
     ///        println!("{}" , p.y); // L3
-    ///        println!("{p}"); // L4
+    ///        println!("{p:?}"); // L4
     ///        drop(s);   // L5
     /// };
     /// ```
@@ -465,7 +466,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///
     /// InferBorrowKind results in a structure like this:
     ///
-    /// ```text
+    /// ```ignore (illustrative)
     /// {
     ///       Place(base: hir_id_s, projections: [], ....) -> {
     ///                                                            capture_kind_expr: hir_id_L5,
@@ -487,10 +488,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///                                                          path_expr_id: hir_id_L4,
     ///                                                          capture_kind: ByValue
     ///                                                      },
+    /// }
     /// ```
     ///
     /// After the min capture analysis, we get:
-    /// ```text
+    /// ```ignore (illustrative)
     /// {
     ///       hir_id_s -> [
     ///            Place(base: hir_id_s, projections: [], ....) -> {
@@ -506,6 +508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///                                                               capture_kind: ByValue
     ///                                                           },
     ///       ],
+    /// }
     /// ```
     fn compute_min_captures(
         &self,
@@ -862,7 +865,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             diagnostics_builder.span_suggestion(
                                 closure_body_span.with_lo(closure_body_span.lo() + BytePos::from_usize(line1.len())).shrink_to_lo(),
                                 &diagnostic_msg,
-                                format!("\n{}{};", indent, migration_string),
+                                format!("\n{indent}{migration_string};"),
                                 Applicability::MachineApplicable,
                             );
                         } else if line1.starts_with('{') {
@@ -873,7 +876,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             diagnostics_builder.span_suggestion(
                                 closure_body_span.with_lo(closure_body_span.lo() + BytePos(1)).shrink_to_lo(),
                                 &diagnostic_msg,
-                                format!(" {};", migration_string),
+                                format!(" {migration_string};"),
                                 Applicability::MachineApplicable,
                             );
                         } else {
@@ -882,7 +885,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             diagnostics_builder.multipart_suggestion(
                                 &diagnostic_msg,
                                 vec![
-                                    (closure_body_span.shrink_to_lo(), format!("{{ {}; ", migration_string)),
+                                    (closure_body_span.shrink_to_lo(), format!("{{ {migration_string}; ")),
                                     (closure_body_span.shrink_to_hi(), " }".to_string()),
                                 ],
                                 Applicability::MachineApplicable
@@ -914,6 +917,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         reasons.auto_traits.extend(auto_trait_reasons);
         reasons.drop_order = drop_order;
 
+        // `auto_trait_reasons` are in hashset order, so sort them to put the
+        // diagnostics we emit later in a cross-platform-consistent order.
+        reasons.auto_traits.sort_unstable();
+
         reasons
     }
 
@@ -1281,27 +1288,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// - Ty(place): Type of place
     /// - `(a, b)`: Represents the function parameters `base_path_ty` and `captured_by_move_projs`
     /// respectively.
-    /// ```
+    /// ```ignore (illustrative)
     ///                  (Ty(w), [ &[p, x], &[c] ])
-    ///                                 |
-    ///                    ----------------------------
-    ///                    |                          |
-    ///                    v                          v
+    /// //                              |
+    /// //                 ----------------------------
+    /// //                 |                          |
+    /// //                 v                          v
     ///        (Ty(w.p), [ &[x] ])          (Ty(w.c), [ &[] ]) // I(1)
-    ///                    |                          |
-    ///                    v                          v
+    /// //                 |                          |
+    /// //                 v                          v
     ///        (Ty(w.p), [ &[x] ])                 false
-    ///                    |
-    ///                    |
-    ///          -------------------------------
-    ///          |                             |
-    ///          v                             v
+    /// //                 |
+    /// //                 |
+    /// //       -------------------------------
+    /// //       |                             |
+    /// //       v                             v
     ///     (Ty((w.p).x), [ &[] ])     (Ty((w.p).y), []) // IMP 2
-    ///          |                             |
-    ///          v                             v
+    /// //       |                             |
+    /// //       v                             v
     ///        false              NeedsSignificantDrop(Ty(w.p.y))
-    ///                                        |
-    ///                                        v
+    /// //                                     |
+    /// //                                     v
     ///                                      true
     /// ```
     ///
@@ -1319,7 +1326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ///
     /// Consider another example:
     ///
-    /// ```rust
+    /// ```ignore (pseudo-rust)
     /// struct X;
     /// impl Drop for X {}
     ///
@@ -1527,7 +1534,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.tcx.sess.struct_span_err(closure_span, "First Pass analysis includes:");
             for (place, capture_info) in capture_information {
                 let capture_str = construct_capture_info_string(self.tcx, place, capture_info);
-                let output_str = format!("Capturing {}", capture_str);
+                let output_str = format!("Capturing {capture_str}");
 
                 let span =
                     capture_info.path_expr_id.map_or(closure_span, |e| self.tcx.hir().span(e));
@@ -1552,7 +1559,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                         let capture_str =
                             construct_capture_info_string(self.tcx, place, capture_info);
-                        let output_str = format!("Min Capture {}", capture_str);
+                        let output_str = format!("Min Capture {capture_str}");
 
                         if capture.info.path_expr_id != capture.info.capture_kind_expr_id {
                             let path_span = capture_info
@@ -1724,14 +1731,14 @@ struct InferBorrowKind<'a, 'tcx> {
     /// s.str2 via a MutableBorrow
     ///
     /// ```rust,no_run
-    /// struct SomeStruct { str1: String, str2: String }
+    /// struct SomeStruct { str1: String, str2: String };
     ///
     /// // Assume that the HirId for the variable definition is `V1`
-    /// let mut s = SomeStruct { str1: format!("s1"), str2: format!("s2") }
+    /// let mut s = SomeStruct { str1: format!("s1"), str2: format!("s2") };
     ///
     /// let fix_s = |new_s2| {
     ///     // Assume that the HirId for the expression `s.str1` is `E1`
-    ///     println!("Updating SomeStruct with str1=", s.str1);
+    ///     println!("Updating SomeStruct with str1={0}", s.str1);
     ///     // Assume that the HirId for the expression `*s.str2` is `E2`
     ///     s.str2 = new_s2;
     /// };
@@ -1739,7 +1746,7 @@ struct InferBorrowKind<'a, 'tcx> {
     ///
     /// For closure `fix_s`, (at a high level) the map contains
     ///
-    /// ```
+    /// ```ignore (illustrative)
     /// Place { V1, [ProjectionKind::Field(Index=0, Variant=0)] } : CaptureKind { E1, ImmutableBorrow }
     /// Place { V1, [ProjectionKind::Field(Index=1, Variant=0)] } : CaptureKind { E2, MutableBorrow }
     /// ```
@@ -1969,7 +1976,7 @@ fn construct_place_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String
         projections_str.push_str(proj.as_str());
     }
 
-    format!("{}[{}]", variable_name, projections_str)
+    format!("{variable_name}[{projections_str}]")
 }
 
 fn construct_capture_kind_reason_string<'tcx>(
@@ -1984,13 +1991,13 @@ fn construct_capture_kind_reason_string<'tcx>(
         ty::UpvarCapture::ByRef(kind) => format!("{:?}", kind),
     };
 
-    format!("{} captured as {} here", place_str, capture_kind_str)
+    format!("{place_str} captured as {capture_kind_str} here")
 }
 
 fn construct_path_string<'tcx>(tcx: TyCtxt<'_>, place: &Place<'tcx>) -> String {
     let place_str = construct_place_string(tcx, place);
 
-    format!("{} used here", place_str)
+    format!("{place_str} used here")
 }
 
 fn construct_capture_info_string<'tcx>(
@@ -2004,7 +2011,7 @@ fn construct_capture_info_string<'tcx>(
         ty::UpvarCapture::ByValue => "ByValue".into(),
         ty::UpvarCapture::ByRef(kind) => format!("{:?}", kind),
     };
-    format!("{} -> {}", place_str, capture_kind_str)
+    format!("{place_str} -> {capture_kind_str}")
 }
 
 fn var_name(tcx: TyCtxt<'_>, var_hir_id: hir::HirId) -> Symbol {
@@ -2035,16 +2042,16 @@ fn migration_suggestion_for_2229(
         .collect::<Vec<_>>();
 
     let migration_ref_concat =
-        need_migrations_variables.iter().map(|v| format!("&{}", v)).collect::<Vec<_>>().join(", ");
+        need_migrations_variables.iter().map(|v| format!("&{v}")).collect::<Vec<_>>().join(", ");
 
     let migration_string = if 1 == need_migrations.len() {
-        format!("let _ = {}", migration_ref_concat)
+        format!("let _ = {migration_ref_concat}")
     } else {
-        format!("let _ = ({})", migration_ref_concat)
+        format!("let _ = ({migration_ref_concat})")
     };
 
     let migrated_variables_concat =
-        need_migrations_variables.iter().map(|v| format!("`{}`", v)).collect::<Vec<_>>().join(", ");
+        need_migrations_variables.iter().map(|v| format!("`{v}`")).collect::<Vec<_>>().join(", ");
 
     (migration_string, migrated_variables_concat)
 }
@@ -2067,7 +2074,7 @@ fn migration_suggestion_for_2229(
 /// Consider the following example
 /// ```rust,no_run
 /// struct Point { x: i32, y: i32 }
-/// let mut p: Point { x: 10, y: 10 };
+/// let mut p = Point { x: 10, y: 10 };
 ///
 /// let c = || {
 ///     p.x     += 10;
@@ -2213,7 +2220,10 @@ fn determine_place_ancestry_relation<'tcx>(
 ///
 /// Reason we only drop the last deref is because of the following edge case:
 ///
-/// ```rust
+/// ```
+/// # struct A { field_of_a: Box<i32> }
+/// # struct B {}
+/// # struct C<'a>(&'a i32);
 /// struct MyStruct<'a> {
 ///    a: &'static A,
 ///    b: B,
@@ -2221,7 +2231,7 @@ fn determine_place_ancestry_relation<'tcx>(
 /// }
 ///
 /// fn foo<'a, 'b>(m: &'a MyStruct<'b>) -> impl FnMut() + 'static {
-///     let c = || drop(&*m.a.field_of_a);
+///     || drop(&*m.a.field_of_a)
 ///     // Here we really do want to capture `*m.a` because that outlives `'static`
 ///
 ///     // If we capture `m`, then the closure no longer outlives `'static'