]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_trait_selection/traits/error_reporting/mod.rs
On recursive ADT, provide indirection structured suggestion
[rust.git] / src / librustc_trait_selection / traits / error_reporting / mod.rs
index 1b72a4bf84f191b363915745594c3bdc550b3b7e..3457f7b4580c5ec8360a0cadd76221b36212c4b7 100644 (file)
@@ -1747,24 +1747,62 @@ fn is_recursive_obligation(
 pub fn recursive_type_with_infinite_size_error(
     tcx: TyCtxt<'tcx>,
     type_def_id: DefId,
-) -> DiagnosticBuilder<'tcx> {
+    spans: Vec<Span>,
+) {
     assert!(type_def_id.is_local());
     let span = tcx.hir().span_if_local(type_def_id).unwrap();
     let span = tcx.sess.source_map().guess_head_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0072,
-        "recursive type `{}` has infinite size",
-        tcx.def_path_str(type_def_id)
-    );
+    let path = tcx.def_path_str(type_def_id);
+    let mut err =
+        struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size", path);
     err.span_label(span, "recursive type has infinite size");
-    err.help(&format!(
-        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
-                           at some point to make `{}` representable",
-        tcx.def_path_str(type_def_id)
-    ));
-    err
+    for &span in &spans {
+        err.span_label(span, "recursive without indirection");
+    }
+    let short_msg = format!("insert some indirection to make `{}` representable", path);
+    let msg = format!(
+        "insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `{}` representable",
+        path,
+    );
+    match &spans[..] {
+        [span] => {
+            err.multipart_suggestions(
+                &short_msg,
+                vec![
+                    vec![
+                        (span.shrink_to_lo(), "Box<".to_string()),
+                        (span.shrink_to_hi(), ">".to_string()),
+                    ],
+                    vec![
+                        (span.shrink_to_lo(), "Rc<".to_string()),
+                        (span.shrink_to_hi(), ">".to_string()),
+                    ],
+                    vec![(span.shrink_to_lo(), "&".to_string())],
+                ],
+                Applicability::HasPlaceholders,
+            );
+        }
+        _ if spans.len() <= 4 => {
+            err.multipart_suggestion(
+                &msg,
+                spans
+                    .iter()
+                    .flat_map(|&span| {
+                        vec![
+                            (span.shrink_to_lo(), "Box<".to_string()),
+                            (span.shrink_to_hi(), ">".to_string()),
+                        ]
+                        .into_iter()
+                    })
+                    .collect(),
+                Applicability::HasPlaceholders,
+            );
+        }
+        _ => {
+            err.help(&msg);
+        }
+    }
+    err.emit();
 }
 
 /// Summarizes information