Skip to content

Commit c30ca41

Browse files
authored
Rollup merge of rust-lang#72740 - estebank:recursive-indirection, r=matthewjasper
On recursive ADT, provide indirection structured suggestion
2 parents 7c78a5f + 03552ec commit c30ca41

28 files changed

+202
-67
lines changed

src/librustc_errors/diagnostic.rs

+23
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,29 @@ impl Diagnostic {
296296
self
297297
}
298298

299+
pub fn multipart_suggestions(
300+
&mut self,
301+
msg: &str,
302+
suggestions: Vec<Vec<(Span, String)>>,
303+
applicability: Applicability,
304+
) -> &mut Self {
305+
self.suggestions.push(CodeSuggestion {
306+
substitutions: suggestions
307+
.into_iter()
308+
.map(|suggestion| Substitution {
309+
parts: suggestion
310+
.into_iter()
311+
.map(|(span, snippet)| SubstitutionPart { snippet, span })
312+
.collect(),
313+
})
314+
.collect(),
315+
msg: msg.to_owned(),
316+
style: SuggestionStyle::ShowCode,
317+
applicability,
318+
});
319+
self
320+
}
321+
299322
/// Prints out a message with for a multipart suggestion without showing the suggested code.
300323
///
301324
/// This is intended to be used for suggestions that are obvious in what the changes need to

src/librustc_errors/diagnostic_builder.rs

+13
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,19 @@ impl<'a> DiagnosticBuilder<'a> {
260260
self
261261
}
262262

263+
pub fn multipart_suggestions(
264+
&mut self,
265+
msg: &str,
266+
suggestions: Vec<Vec<(Span, String)>>,
267+
applicability: Applicability,
268+
) -> &mut Self {
269+
if !self.0.allow_suggestions {
270+
return self;
271+
}
272+
self.0.diagnostic.multipart_suggestions(msg, suggestions, applicability);
273+
self
274+
}
275+
263276
pub fn tool_only_multipart_suggestion(
264277
&mut self,
265278
msg: &str,

src/librustc_middle/ty/util.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,15 @@ impl<'tcx> ty::TyS<'tcx> {
827827
// Find non representable fields with their spans
828828
fold_repr(def.all_fields().map(|field| {
829829
let ty = field.ty(tcx, substs);
830-
let span = tcx.hir().span_if_local(field.did).unwrap_or(sp);
830+
let span = match field
831+
.did
832+
.as_local()
833+
.map(|id| tcx.hir().as_local_hir_id(id))
834+
.and_then(|id| tcx.hir().find(id))
835+
{
836+
Some(hir::Node::Field(field)) => field.ty.span,
837+
_ => sp,
838+
};
831839
match is_type_structurally_recursive(
832840
tcx,
833841
span,

src/librustc_trait_selection/traits/error_reporting/mod.rs

+31-14
Original file line numberDiff line numberDiff line change
@@ -1747,24 +1747,41 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
17471747
pub fn recursive_type_with_infinite_size_error(
17481748
tcx: TyCtxt<'tcx>,
17491749
type_def_id: DefId,
1750-
) -> DiagnosticBuilder<'tcx> {
1750+
spans: Vec<Span>,
1751+
) {
17511752
assert!(type_def_id.is_local());
17521753
let span = tcx.hir().span_if_local(type_def_id).unwrap();
17531754
let span = tcx.sess.source_map().guess_head_span(span);
1754-
let mut err = struct_span_err!(
1755-
tcx.sess,
1756-
span,
1757-
E0072,
1758-
"recursive type `{}` has infinite size",
1759-
tcx.def_path_str(type_def_id)
1760-
);
1755+
let path = tcx.def_path_str(type_def_id);
1756+
let mut err =
1757+
struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size", path);
17611758
err.span_label(span, "recursive type has infinite size");
1762-
err.help(&format!(
1763-
"insert indirection (e.g., a `Box`, `Rc`, or `&`) \
1764-
at some point to make `{}` representable",
1765-
tcx.def_path_str(type_def_id)
1766-
));
1767-
err
1759+
for &span in &spans {
1760+
err.span_label(span, "recursive without indirection");
1761+
}
1762+
let msg = format!(
1763+
"insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `{}` representable",
1764+
path,
1765+
);
1766+
if spans.len() <= 4 {
1767+
err.multipart_suggestion(
1768+
&msg,
1769+
spans
1770+
.iter()
1771+
.flat_map(|&span| {
1772+
vec![
1773+
(span.shrink_to_lo(), "Box<".to_string()),
1774+
(span.shrink_to_hi(), ">".to_string()),
1775+
]
1776+
.into_iter()
1777+
})
1778+
.collect(),
1779+
Applicability::HasPlaceholders,
1780+
);
1781+
} else {
1782+
err.help(&msg);
1783+
}
1784+
err.emit();
17681785
}
17691786

17701787
/// Summarizes information

src/librustc_typeck/check/mod.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -2390,11 +2390,7 @@ fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalDefId) -> bo
23902390
// caught by case 1.
23912391
match rty.is_representable(tcx, sp) {
23922392
Representability::SelfRecursive(spans) => {
2393-
let mut err = recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id());
2394-
for span in spans {
2395-
err.span_label(span, "recursive without indirection");
2396-
}
2397-
err.emit();
2393+
recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans);
23982394
return false;
23992395
}
24002396
Representability::Representable | Representability::ContainsRecursive => (),

src/test/ui/infinite/infinite-tag-type-recursion.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ LL | enum MList { Cons(isize, MList), Nil }
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `MList` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `MList` representable
10+
|
11+
LL | enum MList { Cons(isize, Box<MList>), Nil }
12+
| ^^^^ ^
1013

1114
error[E0391]: cycle detected when computing drop-check constraints for `MList`
1215
--> $DIR/infinite-tag-type-recursion.rs:1:1

src/test/ui/issues/issue-17431-1.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
22
--> $DIR/issue-17431-1.rs:1:1
33
|
44
LL | struct Foo { foo: Option<Option<Foo>> }
5-
| ^^^^^^^^^^ ------------------------ recursive without indirection
5+
| ^^^^^^^^^^ ------------------- recursive without indirection
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
10+
|
11+
LL | struct Foo { foo: Box<Option<Option<Foo>>> }
12+
| ^^^^ ^
1013

1114
error: aborting due to previous error
1215

src/test/ui/issues/issue-17431-2.stderr

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,27 @@ error[E0072]: recursive type `Baz` has infinite size
22
--> $DIR/issue-17431-2.rs:1:1
33
|
44
LL | struct Baz { q: Option<Foo> }
5-
| ^^^^^^^^^^ -------------- recursive without indirection
5+
| ^^^^^^^^^^ ----------- recursive without indirection
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
10+
|
11+
LL | struct Baz { q: Box<Option<Foo>> }
12+
| ^^^^ ^
1013

1114
error[E0072]: recursive type `Foo` has infinite size
1215
--> $DIR/issue-17431-2.rs:4:1
1316
|
1417
LL | struct Foo { q: Option<Baz> }
15-
| ^^^^^^^^^^ -------------- recursive without indirection
18+
| ^^^^^^^^^^ ----------- recursive without indirection
1619
| |
1720
| recursive type has infinite size
1821
|
19-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
22+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
23+
|
24+
LL | struct Foo { q: Box<Option<Baz>> }
25+
| ^^^^ ^
2026

2127
error: aborting due to 2 previous errors
2228

src/test/ui/issues/issue-17431-3.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
22
--> $DIR/issue-17431-3.rs:3:1
33
|
44
LL | struct Foo { foo: Mutex<Option<Foo>> }
5-
| ^^^^^^^^^^ ----------------------- recursive without indirection
5+
| ^^^^^^^^^^ ------------------ recursive without indirection
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
10+
|
11+
LL | struct Foo { foo: Box<Mutex<Option<Foo>>> }
12+
| ^^^^ ^
1013

1114
error: aborting due to previous error
1215

src/test/ui/issues/issue-17431-4.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
22
--> $DIR/issue-17431-4.rs:3:1
33
|
44
LL | struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T> }
5-
| ^^^^^^^^^^^^^ --------------------------- recursive without indirection
5+
| ^^^^^^^^^^^^^ ---------------------- recursive without indirection
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
10+
|
11+
LL | struct Foo<T> { foo: Box<Option<Option<Foo<T>>>>, marker: marker::PhantomData<T> }
12+
| ^^^^ ^
1013

1114
error: aborting due to previous error
1215

src/test/ui/issues/issue-17431-5.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Bar` has infinite size
22
--> $DIR/issue-17431-5.rs:5:1
33
|
44
LL | struct Bar<T> { x: Bar<Foo> , marker: marker::PhantomData<T> }
5-
| ^^^^^^^^^^^^^ ----------- recursive without indirection
5+
| ^^^^^^^^^^^^^ -------- recursive without indirection
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
10+
|
11+
LL | struct Bar<T> { x: Box<Bar<Foo>> , marker: marker::PhantomData<T> }
12+
| ^^^^ ^
1013

1114
error: aborting due to previous error
1215

src/test/ui/issues/issue-17431-6.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ LL | enum Foo { X(Mutex<Option<Foo>>) }
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
10+
|
11+
LL | enum Foo { X(Box<Mutex<Option<Foo>>>) }
12+
| ^^^^ ^
1013

1114
error: aborting due to previous error
1215

src/test/ui/issues/issue-17431-7.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ LL | enum Foo { Voo(Option<Option<Foo>>) }
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
10+
|
11+
LL | enum Foo { Voo(Box<Option<Option<Foo>>>) }
12+
| ^^^^ ^
1013

1114
error: aborting due to previous error
1215

src/test/ui/issues/issue-2718-a.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ LL | pub struct Pong(SendPacket<Ping>);
77
| | recursive without indirection
88
| recursive type has infinite size
99
|
10-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `pingpong::Pong` representable
10+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `pingpong::Pong` representable
11+
|
12+
LL | pub struct Pong(Box<SendPacket<Ping>>);
13+
| ^^^^ ^
1114

1215
error: aborting due to previous error
1316

src/test/ui/issues/issue-3008-1.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ LL | enum Bar {
77
LL | BarSome(Bar)
88
| --- recursive without indirection
99
|
10-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
10+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
11+
|
12+
LL | BarSome(Box<Bar>)
13+
| ^^^^ ^
1114

1215
error: aborting due to previous error
1316

src/test/ui/issues/issue-3008-2.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Bar` has infinite size
22
--> $DIR/issue-3008-2.rs:2:1
33
|
44
LL | struct Bar { x: Bar }
5-
| ^^^^^^^^^^ ------ recursive without indirection
5+
| ^^^^^^^^^^ --- recursive without indirection
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
10+
|
11+
LL | struct Bar { x: Box<Bar> }
12+
| ^^^^ ^
1013

1114
error: aborting due to previous error
1215

src/test/ui/issues/issue-3008-3.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ LL | enum E2<T> { V2(E2<E1>, marker::PhantomData<T>), }
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `E2` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E2` representable
10+
|
11+
LL | enum E2<T> { V2(Box<E2<E1>>, marker::PhantomData<T>), }
12+
| ^^^^ ^
1013

1114
error: aborting due to previous error
1215

src/test/ui/issues/issue-32326.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ LL | Plus(Expr, Expr),
88
| |
99
| recursive without indirection
1010
|
11-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Expr` representable
11+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Expr` representable
12+
|
13+
LL | Plus(Box<Expr>, Box<Expr>),
14+
| ^^^^ ^ ^^^^ ^
1215

1316
error: aborting due to previous error
1417

src/test/ui/issues/issue-3779.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ LL | struct S {
55
| ^^^^^^^^ recursive type has infinite size
66
LL |
77
LL | element: Option<S>
8-
| ------------------ recursive without indirection
8+
| --------- recursive without indirection
99
|
10-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `S` representable
10+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `S` representable
11+
|
12+
LL | element: Box<Option<S>>
13+
| ^^^^ ^
1114

1215
error: aborting due to previous error
1316

src/test/ui/issues/issue-57271.stderr

+8-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ LL | Class(ClassTypeSignature),
77
LL | Array(TypeSignature),
88
| ------------- recursive without indirection
99
|
10-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ObjectType` representable
10+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ObjectType` representable
11+
|
12+
LL | Array(Box<TypeSignature>),
13+
| ^^^^ ^
1114

1215
error[E0072]: recursive type `TypeSignature` has infinite size
1316
--> $DIR/issue-57271.rs:19:1
@@ -18,7 +21,10 @@ LL | Base(BaseType),
1821
LL | Object(ObjectType),
1922
| ---------- recursive without indirection
2023
|
21-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `TypeSignature` representable
24+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `TypeSignature` representable
25+
|
26+
LL | Object(Box<ObjectType>),
27+
| ^^^^ ^
2228

2329
error: aborting due to 2 previous errors
2430

src/test/ui/issues/issue-72554.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ LL | pub enum ElemDerived {
66
LL | A(ElemDerived)
77
| ----------- recursive without indirection
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ElemDerived` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ElemDerived` representable
10+
|
11+
LL | A(Box<ElemDerived>)
12+
| ^^^^ ^
1013

1114
error: aborting due to previous error
1215

src/test/ui/recursion/recursive-enum.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ LL | enum List<T> { Cons(T, List<T>), Nil }
66
| |
77
| recursive type has infinite size
88
|
9-
= help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
9+
help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `List` representable
10+
|
11+
LL | enum List<T> { Cons(T, Box<List<T>>), Nil }
12+
| ^^^^ ^
1013

1114
error: aborting due to previous error
1215

0 commit comments

Comments
 (0)