Skip to content

Commit

Permalink
Rollup merge of rust-lang#72740 - estebank:recursive-indirection, r=m…
Browse files Browse the repository at this point in the history
…atthewjasper

On recursive ADT, provide indirection structured suggestion
  • Loading branch information
RalfJung committed Jun 6, 2020
2 parents 3c39683 + c209040 commit d4a4f16
Show file tree
Hide file tree
Showing 27 changed files with 198 additions and 66 deletions.
23 changes: 23 additions & 0 deletions src/librustc_errors/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,29 @@ impl Diagnostic {
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
Expand Down
13 changes: 13 additions & 0 deletions src/librustc_errors/diagnostic_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,19 @@ impl<'a> DiagnosticBuilder<'a> {
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,
Expand Down
10 changes: 9 additions & 1 deletion src/librustc_middle/ty/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,15 @@ impl<'tcx> ty::TyS<'tcx> {
// 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,
Expand Down
45 changes: 31 additions & 14 deletions src/librustc_trait_selection/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1737,24 +1737,41 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
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 msg = format!(
"insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `{}` representable",
path,
);
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,
);
} else {
err.help(&msg);
}
err.emit();
}

/// Summarizes information
Expand Down
6 changes: 1 addition & 5 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2393,11 +2393,7 @@ fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalDefId) -> bo
// 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 => (),
Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/infinite/infinite-tag-type-recursion.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ LL | enum MList { Cons(isize, MList), Nil }
| |
| 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 (e.g., a `Box`, `Rc`, or `&`) to make `MList` representable
|
LL | enum MList { Cons(isize, Box<MList>), Nil }
| ^^^^ ^

error[E0391]: cycle detected when computing drop-check constraints for `MList`
--> $DIR/infinite-tag-type-recursion.rs:1:1
Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/issues/issue-17431-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
--> $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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | struct Foo { foo: Box<Option<Option<Foo>>> }
| ^^^^ ^

error: aborting due to previous error

Expand Down
14 changes: 10 additions & 4 deletions src/test/ui/issues/issue-17431-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,27 @@ error[E0072]: recursive type `Baz` has infinite size
--> $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 (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
|
LL | struct Baz { q: Box<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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | struct Foo { q: Box<Option<Baz>> }
| ^^^^ ^

error: aborting due to 2 previous errors

Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/issues/issue-17431-3.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
--> $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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | struct Foo { foo: Box<Mutex<Option<Foo>>> }
| ^^^^ ^

error: aborting due to previous error

Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/issues/issue-17431-4.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
--> $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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | struct Foo<T> { foo: Box<Option<Option<Foo<T>>>>, marker: marker::PhantomData<T> }
| ^^^^ ^

error: aborting due to previous error

Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/issues/issue-17431-5.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ error[E0072]: recursive type `Bar` has infinite size
--> $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 (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
|
LL | struct Bar<T> { x: Box<Bar<Foo>> , marker: marker::PhantomData<T> }
| ^^^^ ^

error: aborting due to previous error

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-17431-6.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ LL | enum Foo { X(Mutex<Option<Foo>>) }
| |
| 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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | enum Foo { X(Box<Mutex<Option<Foo>>>) }
| ^^^^ ^

error: aborting due to previous error

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-17431-7.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ LL | enum Foo { Voo(Option<Option<Foo>>) }
| |
| 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 (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
|
LL | enum Foo { Voo(Box<Option<Option<Foo>>>) }
| ^^^^ ^

error: aborting due to previous error

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-2718-a.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ LL | pub struct Pong(SendPacket<Ping>);
| | 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 (e.g., a `Box`, `Rc`, or `&`) to make `pingpong::Pong` representable
|
LL | pub struct Pong(Box<SendPacket<Ping>>);
| ^^^^ ^

error: aborting due to previous error

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-3008-1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ LL | enum Bar {
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 (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
|
LL | BarSome(Box<Bar>)
| ^^^^ ^

error: aborting due to previous error

Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/issues/issue-3008-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ error[E0072]: recursive type `Bar` has infinite size
--> $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 (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
|
LL | struct Bar { x: Box<Bar> }
| ^^^^ ^

error: aborting due to previous error

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-3008-3.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ LL | enum E2<T> { V2(E2<E1>, marker::PhantomData<T>), }
| |
| 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 (e.g., a `Box`, `Rc`, or `&`) to make `E2` representable
|
LL | enum E2<T> { V2(Box<E2<E1>>, marker::PhantomData<T>), }
| ^^^^ ^

error: aborting due to previous error

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-32326.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ LL | Plus(Expr, Expr),
| |
| 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

Expand Down
7 changes: 5 additions & 2 deletions src/test/ui/issues/issue-3779.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ LL | struct S {
| ^^^^^^^^ 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 (e.g., a `Box`, `Rc`, or `&`) to make `S` representable
|
LL | element: Box<Option<S>>
| ^^^^ ^

error: aborting due to previous error

Expand Down
10 changes: 8 additions & 2 deletions src/test/ui/issues/issue-57271.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ LL | Class(ClassTypeSignature),
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 (e.g., a `Box`, `Rc`, or `&`) to make `ObjectType` representable
|
LL | Array(Box<TypeSignature>),
| ^^^^ ^

error[E0072]: recursive type `TypeSignature` has infinite size
--> $DIR/issue-57271.rs:19:1
Expand All @@ -18,7 +21,10 @@ LL | Base(BaseType),
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 (e.g., a `Box`, `Rc`, or `&`) to make `TypeSignature` representable
|
LL | Object(Box<ObjectType>),
| ^^^^ ^

error: aborting due to 2 previous errors

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/recursion/recursive-enum.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ LL | enum List<T> { Cons(T, List<T>), Nil }
| |
| 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 (e.g., a `Box`, `Rc`, or `&`) to make `List` representable
|
LL | enum List<T> { Cons(T, Box<List<T>>), Nil }
| ^^^^ ^

error: aborting due to previous error

Expand Down
Loading

0 comments on commit d4a4f16

Please sign in to comment.