self
}
+ pub fn multipart_suggestions(
+ &mut self,
+ msg: &str,
+ suggestions: Vec<Vec<(Span, String)>>,
+ applicability: Applicability,
+ ) -> &mut Self {
+ self.suggestions.push(CodeSuggestion {
+ substitutions: suggestions
+ .into_iter()
+ .map(|suggestion| Substitution {
+ parts: suggestion
+ .into_iter()
+ .map(|(span, snippet)| SubstitutionPart { snippet, span })
+ .collect(),
+ })
+ .collect(),
+ msg: msg.to_owned(),
+ style: SuggestionStyle::ShowCode,
+ applicability,
+ });
+ self
+ }
+
/// Prints out a message with for a multipart suggestion without showing the suggested code.
///
/// This is intended to be used for suggestions that are obvious in what the changes need to
self
}
+ pub fn multipart_suggestions(
+ &mut self,
+ msg: &str,
+ suggestions: Vec<Vec<(Span, String)>>,
+ applicability: Applicability,
+ ) -> &mut Self {
+ if !self.0.allow_suggestions {
+ return self;
+ }
+ self.0.diagnostic.multipart_suggestions(msg, suggestions, applicability);
+ self
+ }
+
pub fn tool_only_multipart_suggestion(
&mut self,
msg: &str,
// Find non representable fields with their spans
fold_repr(def.all_fields().map(|field| {
let ty = field.ty(tcx, substs);
- let span = tcx.hir().span_if_local(field.did).unwrap_or(sp);
+ let span = match field
+ .did
+ .as_local()
+ .map(|id| tcx.hir().as_local_hir_id(id))
+ .and_then(|id| tcx.hir().find(id))
+ {
+ Some(hir::Node::Field(field)) => field.ty.span,
+ _ => sp,
+ };
match is_type_structurally_recursive(
tcx,
span,
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
// caught by case 1.
match rty.is_representable(tcx, sp) {
Representability::SelfRecursive(spans) => {
- let mut err = recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id());
- for span in spans {
- err.span_label(span, "recursive without indirection");
- }
- err.emit();
+ recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans);
return false;
}
Representability::Representable | Representability::ContainsRecursive => (),
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `MList` representable
+help: insert some indirection to make `MList` representable
+ |
+LL | enum MList { Cons(isize, Box<MList>), Nil }
+ | ^^^^ ^
+LL | enum MList { Cons(isize, Rc<MList>), Nil }
+ | ^^^ ^
+LL | enum MList { Cons(isize, &MList), Nil }
+ | ^
error[E0391]: cycle detected when computing drop-check constraints for `MList`
--> $DIR/infinite-tag-type-recursion.rs:1:1
--> $DIR/issue-17431-1.rs:1:1
|
LL | struct Foo { foo: Option<Option<Foo>> }
- | ^^^^^^^^^^ ------------------------ recursive without indirection
+ | ^^^^^^^^^^ ------------------- recursive without indirection
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection to make `Foo` representable
+ |
+LL | struct Foo { foo: Box<Option<Option<Foo>>> }
+ | ^^^^ ^
+LL | struct Foo { foo: Rc<Option<Option<Foo>>> }
+ | ^^^ ^
+LL | struct Foo { foo: &Option<Option<Foo>> }
+ | ^
error: aborting due to previous error
--> $DIR/issue-17431-2.rs:1:1
|
LL | struct Baz { q: Option<Foo> }
- | ^^^^^^^^^^ -------------- recursive without indirection
+ | ^^^^^^^^^^ ----------- recursive without indirection
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
+help: insert some indirection to make `Baz` representable
+ |
+LL | struct Baz { q: Box<Option<Foo>> }
+ | ^^^^ ^
+LL | struct Baz { q: Rc<Option<Foo>> }
+ | ^^^ ^
+LL | struct Baz { q: &Option<Foo> }
+ | ^
error[E0072]: recursive type `Foo` has infinite size
--> $DIR/issue-17431-2.rs:4:1
|
LL | struct Foo { q: Option<Baz> }
- | ^^^^^^^^^^ -------------- recursive without indirection
+ | ^^^^^^^^^^ ----------- recursive without indirection
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection to make `Foo` representable
+ |
+LL | struct Foo { q: Box<Option<Baz>> }
+ | ^^^^ ^
+LL | struct Foo { q: Rc<Option<Baz>> }
+ | ^^^ ^
+LL | struct Foo { q: &Option<Baz> }
+ | ^
error: aborting due to 2 previous errors
--> $DIR/issue-17431-3.rs:3:1
|
LL | struct Foo { foo: Mutex<Option<Foo>> }
- | ^^^^^^^^^^ ----------------------- recursive without indirection
+ | ^^^^^^^^^^ ------------------ recursive without indirection
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection to make `Foo` representable
+ |
+LL | struct Foo { foo: Box<Mutex<Option<Foo>>> }
+ | ^^^^ ^
+LL | struct Foo { foo: Rc<Mutex<Option<Foo>>> }
+ | ^^^ ^
+LL | struct Foo { foo: &Mutex<Option<Foo>> }
+ | ^
error: aborting due to previous error
--> $DIR/issue-17431-4.rs:3:1
|
LL | struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T> }
- | ^^^^^^^^^^^^^ --------------------------- recursive without indirection
+ | ^^^^^^^^^^^^^ ---------------------- recursive without indirection
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection to make `Foo` representable
+ |
+LL | struct Foo<T> { foo: Box<Option<Option<Foo<T>>>>, marker: marker::PhantomData<T> }
+ | ^^^^ ^
+LL | struct Foo<T> { foo: Rc<Option<Option<Foo<T>>>>, marker: marker::PhantomData<T> }
+ | ^^^ ^
+LL | struct Foo<T> { foo: &Option<Option<Foo<T>>>, marker: marker::PhantomData<T> }
+ | ^
error: aborting due to previous error
--> $DIR/issue-17431-5.rs:5:1
|
LL | struct Bar<T> { x: Bar<Foo> , marker: marker::PhantomData<T> }
- | ^^^^^^^^^^^^^ ----------- recursive without indirection
+ | ^^^^^^^^^^^^^ -------- recursive without indirection
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+help: insert some indirection to make `Bar` representable
+ |
+LL | struct Bar<T> { x: Box<Bar<Foo>> , marker: marker::PhantomData<T> }
+ | ^^^^ ^
+LL | struct Bar<T> { x: Rc<Bar<Foo>> , marker: marker::PhantomData<T> }
+ | ^^^ ^
+LL | struct Bar<T> { x: &Bar<Foo> , marker: marker::PhantomData<T> }
+ | ^
error: aborting due to previous error
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection to make `Foo` representable
+ |
+LL | enum Foo { X(Box<Mutex<Option<Foo>>>) }
+ | ^^^^ ^
+LL | enum Foo { X(Rc<Mutex<Option<Foo>>>) }
+ | ^^^ ^
+LL | enum Foo { X(&Mutex<Option<Foo>>) }
+ | ^
error: aborting due to previous error
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection to make `Foo` representable
+ |
+LL | enum Foo { Voo(Box<Option<Option<Foo>>>) }
+ | ^^^^ ^
+LL | enum Foo { Voo(Rc<Option<Option<Foo>>>) }
+ | ^^^ ^
+LL | enum Foo { Voo(&Option<Option<Foo>>) }
+ | ^
error: aborting due to previous error
| | recursive without indirection
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `pingpong::Pong` representable
+help: insert some indirection to make `pingpong::Pong` representable
+ |
+LL | pub struct Pong(Box<SendPacket<Ping>>);
+ | ^^^^ ^
+LL | pub struct Pong(Rc<SendPacket<Ping>>);
+ | ^^^ ^
+LL | pub struct Pong(&SendPacket<Ping>);
+ | ^
error: aborting due to previous error
LL | BarSome(Bar)
| --- recursive without indirection
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+help: insert some indirection to make `Bar` representable
+ |
+LL | BarSome(Box<Bar>)
+ | ^^^^ ^
+LL | BarSome(Rc<Bar>)
+ | ^^^ ^
+LL | BarSome(&Bar)
+ | ^
error: aborting due to previous error
--> $DIR/issue-3008-2.rs:2:1
|
LL | struct Bar { x: Bar }
- | ^^^^^^^^^^ ------ recursive without indirection
+ | ^^^^^^^^^^ --- recursive without indirection
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+help: insert some indirection to make `Bar` representable
+ |
+LL | struct Bar { x: Box<Bar> }
+ | ^^^^ ^
+LL | struct Bar { x: Rc<Bar> }
+ | ^^^ ^
+LL | struct Bar { x: &Bar }
+ | ^
error: aborting due to previous error
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `E2` representable
+help: insert some indirection to make `E2` representable
+ |
+LL | enum E2<T> { V2(Box<E2<E1>>, marker::PhantomData<T>), }
+ | ^^^^ ^
+LL | enum E2<T> { V2(Rc<E2<E1>>, marker::PhantomData<T>), }
+ | ^^^ ^
+LL | enum E2<T> { V2(&E2<E1>, marker::PhantomData<T>), }
+ | ^
error: aborting due to previous error
| |
| recursive without indirection
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Expr` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Expr` representable
+ |
+LL | Plus(Box<Expr>, Box<Expr>),
+ | ^^^^ ^ ^^^^ ^
error: aborting due to previous error
| ^^^^^^^^ recursive type has infinite size
LL |
LL | element: Option<S>
- | ------------------ recursive without indirection
+ | --------- recursive without indirection
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `S` representable
+help: insert some indirection to make `S` representable
+ |
+LL | element: Box<Option<S>>
+ | ^^^^ ^
+LL | element: Rc<Option<S>>
+ | ^^^ ^
+LL | element: &Option<S>
+ | ^
error: aborting due to previous error
LL | Array(TypeSignature),
| ------------- recursive without indirection
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ObjectType` representable
+help: insert some indirection to make `ObjectType` representable
+ |
+LL | Array(Box<TypeSignature>),
+ | ^^^^ ^
+LL | Array(Rc<TypeSignature>),
+ | ^^^ ^
+LL | Array(&TypeSignature),
+ | ^
error[E0072]: recursive type `TypeSignature` has infinite size
--> $DIR/issue-57271.rs:19:1
LL | Object(ObjectType),
| ---------- recursive without indirection
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `TypeSignature` representable
+help: insert some indirection to make `TypeSignature` representable
+ |
+LL | Object(Box<ObjectType>),
+ | ^^^^ ^
+LL | Object(Rc<ObjectType>),
+ | ^^^ ^
+LL | Object(&ObjectType),
+ | ^
error: aborting due to 2 previous errors
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
+help: insert some indirection to make `List` representable
+ |
+LL | enum List<T> { Cons(T, Box<List<T>>), Nil }
+ | ^^^^ ^
+LL | enum List<T> { Cons(T, Rc<List<T>>), Nil }
+ | ^^^ ^
+LL | enum List<T> { Cons(T, &List<T>), Nil }
+ | ^
error: aborting due to previous error
--> $DIR/sized-cycle-note.rs:9:1
|
LL | struct Baz { q: Option<Foo> }
- | ^^^^^^^^^^ -------------- recursive without indirection
+ | ^^^^^^^^^^ ----------- recursive without indirection
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
+help: insert some indirection to make `Baz` representable
+ |
+LL | struct Baz { q: Box<Option<Foo>> }
+ | ^^^^ ^
+LL | struct Baz { q: Rc<Option<Foo>> }
+ | ^^^ ^
+LL | struct Baz { q: &Option<Foo> }
+ | ^
error[E0072]: recursive type `Foo` has infinite size
--> $DIR/sized-cycle-note.rs:11:1
|
LL | struct Foo { q: Option<Baz> }
- | ^^^^^^^^^^ -------------- recursive without indirection
+ | ^^^^^^^^^^ ----------- recursive without indirection
| |
| recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection to make `Foo` representable
+ |
+LL | struct Foo { q: Box<Option<Baz>> }
+ | ^^^^ ^
+LL | struct Foo { q: Rc<Option<Baz>> }
+ | ^^^ ^
+LL | struct Foo { q: &Option<Baz> }
+ | ^
error: aborting due to 2 previous errors
| ^^^^^^^^^^^^^^^ recursive type has infinite size
LL | head: u8,
LL | tail: Option<ListNode>,
- | ---------------------- recursive without indirection
+ | ---------------- recursive without indirection
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
+help: insert some indirection to make `ListNode` representable
+ |
+LL | tail: Box<Option<ListNode>>,
+ | ^^^^ ^
+LL | tail: Rc<Option<ListNode>>,
+ | ^^^ ^
+LL | tail: &Option<ListNode>,
+ | ^
error: aborting due to previous error
LL | | {
LL | | head: u8,
LL | | tail: Option<ListNode>,
- | | ---------------------- recursive without indirection
+ | | ---------------- recursive without indirection
LL | | }
| |_^ recursive type has infinite size
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
+help: insert some indirection to make `ListNode` representable
+ |
+LL | tail: Box<Option<ListNode>>,
+ | ^^^^ ^
+LL | tail: Rc<Option<ListNode>>,
+ | ^^^ ^
+LL | tail: &Option<ListNode>,
+ | ^
error: aborting due to previous error
LL | struct Foo<'a> {
| ^^^^^^^^^^^^^^ recursive type has infinite size
LL | bar: Bar<'a>,
- | ------------ recursive without indirection
+ | ------- recursive without indirection
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection to make `Foo` representable
+ |
+LL | bar: Box<Bar<'a>>,
+ | ^^^^ ^
+LL | bar: Rc<Bar<'a>>,
+ | ^^^ ^
+LL | bar: &Bar<'a>,
+ | ^
error[E0072]: recursive type `Bar` has infinite size
--> $DIR/recursive-type-field.rs:8:1
LL | struct Bar<'a> {
| ^^^^^^^^^^^^^^ recursive type has infinite size
LL | y: (Foo<'a>, Foo<'a>),
- | --------------------- recursive without indirection
+ | ------------------ recursive without indirection
LL | z: Option<Bar<'a>>,
- | ------------------ recursive without indirection
+ | --------------- recursive without indirection
...
LL | d: [Bar<'a>; 1],
- | --------------- recursive without indirection
+ | ------------ recursive without indirection
LL | e: Foo<'a>,
- | ---------- recursive without indirection
+ | ------- recursive without indirection
LL | x: Bar<'a>,
- | ---------- recursive without indirection
+ | ------- recursive without indirection
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+ = help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
error: aborting due to 2 previous errors
| ^^^^^^^^^ recursive type has infinite size
LL | foo: isize,
LL | foolish: T1
- | ----------- recursive without indirection
+ | -- recursive without indirection
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `T1` representable
+help: insert some indirection to make `T1` representable
+ |
+LL | foolish: Box<T1>
+ | ^^^^ ^
+LL | foolish: Rc<T1>
+ | ^^^ ^
+LL | foolish: &T1
+ | ^
error: aborting due to previous error
| ^^^^^^^ recursive type has infinite size
LL | a: u8,
LL | b: U,
- | ---- recursive without indirection
+ | - recursive without indirection
|
- = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `U` representable
+help: insert some indirection to make `U` representable
+ |
+LL | b: Box<U>,
+ | ^^^^ ^
+LL | b: Rc<U>,
+ | ^^^ ^
+LL | b: &U,
+ | ^
error: aborting due to previous error