Skip to content

Commit 61edf25

Browse files
committed
Tweak suggest_constraining_type_param
Some of the bound restriction structured suggestions were incorrect while others had subpar output.
1 parent 131772c commit 61edf25

File tree

66 files changed

+408
-570
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+408
-570
lines changed

src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs

-2
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
222222
&mut err,
223223
&param.name.as_str(),
224224
"Copy",
225-
tcx.sess.source_map(),
226-
span,
227225
None,
228226
);
229227
}

src/librustc_trait_selection/traits/error_reporting/mod.rs

+46-73
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}
2525
use rustc_hir as hir;
2626
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
2727
use rustc_hir::{Node, QPath, TyKind, WhereBoundPredicate, WherePredicate};
28-
use rustc_span::source_map::SourceMap;
29-
use rustc_span::{ExpnKind, Span, DUMMY_SP};
28+
use rustc_span::{BytePos, ExpnKind, Span, DUMMY_SP};
3029
use std::fmt;
3130

3231
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
@@ -1680,14 +1679,8 @@ pub fn suggest_constraining_type_param(
16801679
err: &mut DiagnosticBuilder<'_>,
16811680
param_name: &str,
16821681
constraint: &str,
1683-
source_map: &SourceMap,
1684-
span: Span,
16851682
def_id: Option<DefId>,
16861683
) -> bool {
1687-
const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound with";
1688-
const MSG_RESTRICT_TYPE: &str = "consider restricting this type parameter with";
1689-
const MSG_RESTRICT_TYPE_FURTHER: &str = "consider further restricting this type parameter with";
1690-
16911684
let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
16921685

16931686
let param = if let Some(param) = param {
@@ -1696,6 +1689,11 @@ pub fn suggest_constraining_type_param(
16961689
return false;
16971690
};
16981691

1692+
const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound";
1693+
let msg_restrict_type = format!("consider restricting type parameter `{}`", param_name);
1694+
let msg_restrict_type_further =
1695+
format!("consider further restricting type parameter `{}`", param_name);
1696+
16991697
if def_id == tcx.lang_items().sized_trait() {
17001698
// Type parameters are already `Sized` by default.
17011699
err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint));
@@ -1718,19 +1716,21 @@ pub fn suggest_constraining_type_param(
17181716
// |
17191717
// replace with: `impl Foo + Bar`
17201718

1721-
err.span_help(param.span, &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint));
1722-
1723-
err.tool_only_span_suggestion(
1724-
param.span,
1719+
err.span_suggestion_verbose(
1720+
param.span.shrink_to_hi(),
17251721
MSG_RESTRICT_BOUND_FURTHER,
1726-
format!("{} + {}", param_name, constraint),
1722+
format!(" + {}", constraint),
17271723
Applicability::MachineApplicable,
17281724
);
17291725

17301726
return true;
17311727
}
17321728

1733-
if generics.where_clause.predicates.is_empty() {
1729+
if generics.where_clause.predicates.is_empty()
1730+
// Given `trait Base<T = String>: Super<T>` where `T: Copy`, suggest restricting in the
1731+
// `where` clause in stead of `trait Base<T: Copy = String>: Super<T>`.
1732+
&& !matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
1733+
{
17341734
if let Some(bounds_span) = param.bounds_span() {
17351735
// If user has provided some bounds, suggest restricting them:
17361736
//
@@ -1746,37 +1746,21 @@ pub fn suggest_constraining_type_param(
17461746
// |
17471747
// replace with: `T: Bar +`
17481748

1749-
err.span_help(
1750-
bounds_span,
1751-
&format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
1749+
err.span_suggestion_verbose(
1750+
bounds_span.shrink_to_hi(),
1751+
MSG_RESTRICT_BOUND_FURTHER,
1752+
format!(" + {}", constraint),
1753+
Applicability::MachineApplicable,
17521754
);
1753-
1754-
let span_hi = param.span.with_hi(span.hi());
1755-
let span_with_colon = source_map.span_through_char(span_hi, ':');
1756-
1757-
if span_hi != param.span && span_with_colon != span_hi {
1758-
err.tool_only_span_suggestion(
1759-
span_with_colon,
1760-
MSG_RESTRICT_BOUND_FURTHER,
1761-
format!("{}: {} + ", param_name, constraint),
1762-
Applicability::MachineApplicable,
1763-
);
1764-
}
17651755
} else {
17661756
// If user hasn't provided any bounds, suggest adding a new one:
17671757
//
17681758
// fn foo<T>(t: T) { ... }
17691759
// - help: consider restricting this type parameter with `T: Foo`
1770-
1771-
err.span_help(
1772-
param.span,
1773-
&format!("{} `{}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
1774-
);
1775-
1776-
err.tool_only_span_suggestion(
1777-
param.span,
1778-
MSG_RESTRICT_TYPE,
1779-
format!("{}: {}", param_name, constraint),
1760+
err.span_suggestion_verbose(
1761+
param.span.shrink_to_hi(),
1762+
&msg_restrict_type,
1763+
format!(": {}", constraint),
17801764
Applicability::MachineApplicable,
17811765
);
17821766
}
@@ -1840,55 +1824,44 @@ pub fn suggest_constraining_type_param(
18401824
}
18411825
}
18421826

1843-
let where_clause_span =
1844-
generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi();
1827+
let where_clause_span = generics.where_clause.span_for_predicates_or_empty_place();
1828+
// Account for `fn foo<T>(t: T) where T: Foo,` so we don't suggest two trailing commas.
1829+
let mut trailing_comma = false;
1830+
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(where_clause_span) {
1831+
if snippet.ends_with(",") {
1832+
trailing_comma = true;
1833+
}
1834+
}
1835+
let where_clause_span = if trailing_comma {
1836+
let hi = where_clause_span.hi();
1837+
Span::new(hi - BytePos(1), hi, where_clause_span.ctxt())
1838+
} else {
1839+
where_clause_span.shrink_to_hi()
1840+
};
18451841

18461842
match &param_spans[..] {
18471843
&[] => {
1848-
err.span_help(
1849-
param.span,
1850-
&format!("{} `where {}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
1851-
);
1852-
1853-
err.tool_only_span_suggestion(
1844+
err.span_suggestion_verbose(
18541845
where_clause_span,
1855-
MSG_RESTRICT_TYPE,
1846+
&msg_restrict_type_further,
18561847
format!(", {}: {}", param_name, constraint),
18571848
Applicability::MachineApplicable,
18581849
);
18591850
}
18601851

18611852
&[&param_span] => {
1862-
err.span_help(
1863-
param_span,
1864-
&format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
1853+
err.span_suggestion_verbose(
1854+
param_span.shrink_to_hi(),
1855+
MSG_RESTRICT_BOUND_FURTHER,
1856+
format!(" + {}", constraint),
1857+
Applicability::MachineApplicable,
18651858
);
1866-
1867-
let span_hi = param_span.with_hi(span.hi());
1868-
let span_with_colon = source_map.span_through_char(span_hi, ':');
1869-
1870-
if span_hi != param_span && span_with_colon != span_hi {
1871-
err.tool_only_span_suggestion(
1872-
span_with_colon,
1873-
MSG_RESTRICT_BOUND_FURTHER,
1874-
format!("{}: {} +", param_name, constraint),
1875-
Applicability::MachineApplicable,
1876-
);
1877-
}
18781859
}
18791860

18801861
_ => {
1881-
err.span_help(
1882-
param.span,
1883-
&format!(
1884-
"{} `where {}: {}`",
1885-
MSG_RESTRICT_TYPE_FURTHER, param_name, constraint,
1886-
),
1887-
);
1888-
1889-
err.tool_only_span_suggestion(
1862+
err.span_suggestion_verbose(
18901863
where_clause_span,
1891-
MSG_RESTRICT_BOUND_FURTHER,
1864+
&msg_restrict_type_further,
18921865
format!(", {}: {}", param_name, constraint),
18931866
Applicability::MachineApplicable,
18941867
);

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

+9-33
Original file line numberDiff line numberDiff line change
@@ -218,51 +218,29 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
218218
return;
219219
}
220220

221-
hir::Node::Item(hir::Item {
222-
kind: hir::ItemKind::Struct(_, generics),
223-
span,
224-
..
225-
})
226-
| hir::Node::Item(hir::Item {
227-
kind: hir::ItemKind::Enum(_, generics), span, ..
228-
})
229-
| hir::Node::Item(hir::Item {
230-
kind: hir::ItemKind::Union(_, generics),
231-
span,
232-
..
233-
})
221+
hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), .. })
222+
| hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), .. })
223+
| hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), .. })
234224
| hir::Node::Item(hir::Item {
235225
kind: hir::ItemKind::Trait(_, _, generics, ..),
236-
span,
237-
..
238-
})
239-
| hir::Node::Item(hir::Item {
240-
kind: hir::ItemKind::Impl { generics, .. },
241-
span,
242226
..
243227
})
244228
| hir::Node::Item(hir::Item {
245-
kind: hir::ItemKind::Fn(_, generics, _),
246-
span,
247-
..
229+
kind: hir::ItemKind::Impl { generics, .. }, ..
248230
})
231+
| hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
249232
| hir::Node::Item(hir::Item {
250-
kind: hir::ItemKind::TyAlias(_, generics),
251-
span,
252-
..
233+
kind: hir::ItemKind::TyAlias(_, generics), ..
253234
})
254235
| hir::Node::Item(hir::Item {
255-
kind: hir::ItemKind::TraitAlias(generics, _),
256-
span,
257-
..
236+
kind: hir::ItemKind::TraitAlias(generics, _), ..
258237
})
259238
| hir::Node::Item(hir::Item {
260239
kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
261-
span,
262240
..
263241
})
264-
| hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
265-
| hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
242+
| hir::Node::TraitItem(hir::TraitItem { generics, .. })
243+
| hir::Node::ImplItem(hir::ImplItem { generics, .. })
266244
if param_ty =>
267245
{
268246
// Missing generic type parameter bound.
@@ -274,8 +252,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
274252
&mut err,
275253
&param_name,
276254
&constraint,
277-
self.tcx.sess.source_map(),
278-
*span,
279255
Some(trait_ref.def_id()),
280256
) {
281257
return;

src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr

+3-4
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ LL | const Y: usize;
77
LL | let _array = [4; <A as Foo>::Y];
88
| ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
99
|
10-
help: consider further restricting this bound with `+ Foo`
11-
--> $DIR/associated-const-type-parameter-arrays-2.rs:15:16
10+
help: consider further restricting this bound
1211
|
13-
LL | pub fn test<A: Foo, B: Foo>() {
14-
| ^^^
12+
LL | pub fn test<A: Foo + Foo, B: Foo>() {
13+
| ^^^^^
1514

1615
error: aborting due to previous error
1716

src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr

+3-4
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@ LL | const Y: usize;
77
LL | let _array: [u32; <A as Foo>::Y];
88
| ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A`
99
|
10-
help: consider further restricting this bound with `+ Foo`
11-
--> $DIR/associated-const-type-parameter-arrays.rs:15:16
10+
help: consider further restricting this bound
1211
|
13-
LL | pub fn test<A: Foo, B: Foo>() {
14-
| ^^^
12+
LL | pub fn test<A: Foo + Foo, B: Foo>() {
13+
| ^^^^^
1514

1615
error: aborting due to previous error
1716

src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ error[E0277]: the trait bound `T: Foo<usize>` is not satisfied
44
LL | let u: <T as Foo<usize>>::Bar = t.get_bar();
55
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo<usize>` is not implemented for `T`
66
|
7-
help: consider further restricting this bound with `+ Foo<usize>`
8-
--> $DIR/associated-types-invalid-trait-ref-issue-18865.rs:9:8
7+
help: consider further restricting this bound
98
|
10-
LL | fn f<T:Foo<isize>>(t: &T) {
11-
| ^^^^^^^^^^
9+
LL | fn f<T:Foo<isize> + Foo<usize>>(t: &T) {
10+
| ^^^^^^^^^^^^
1211

1312
error: aborting due to previous error
1413

src/test/ui/associated-types/associated-types-no-suitable-bound.stderr

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ error[E0277]: the trait bound `T: Get` is not satisfied
44
LL | fn uhoh<T>(foo: <T as Get>::Value) {}
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
66
|
7-
help: consider restricting this type parameter with `T: Get`
8-
--> $DIR/associated-types-no-suitable-bound.rs:11:13
7+
help: consider restricting type parameter `T`
98
|
10-
LL | fn uhoh<T>(foo: <T as Get>::Value) {}
11-
| ^
9+
LL | fn uhoh<T: Get>(foo: <T as Get>::Value) {}
10+
| ^^^^^
1211

1312
error: aborting due to previous error
1413

src/test/ui/associated-types/defaults-suitability.stderr

+7-9
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@ LL | trait Foo<T> {
2323
LL | type Bar: Clone = Vec<T>;
2424
| ^^^^^ the trait `std::clone::Clone` is not implemented for `T`
2525
|
26-
help: consider restricting this type parameter with `T: std::clone::Clone`
27-
--> $DIR/defaults-suitability.rs:32:11
28-
|
29-
LL | trait Foo<T> {
30-
| ^
3126
= note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<T>`
27+
help: consider restricting type parameter `T`
28+
|
29+
LL | trait Foo<T: std::clone::Clone> {
30+
| ^^^^^^^^^^^^^^^^^^^
3231

3332
error[E0277]: the trait bound `(): Foo<Self>` is not satisfied
3433
--> $DIR/defaults-suitability.rs:39:17
@@ -119,11 +118,10 @@ LL | | type Baz = T;
119118
LL | | }
120119
| |_- required by `Foo3`
121120
|
122-
help: consider restricting this type parameter with `where T: std::clone::Clone`
123-
--> $DIR/defaults-suitability.rs:88:12
121+
help: consider further restricting type parameter `T`
124122
|
125-
LL | trait Foo3<T> where
126-
| ^
123+
LL | Self::Baz: Clone, T: std::clone::Clone
124+
| ^^^^^^^^^^^^^^^^^^^^^^
127125

128126
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
129127
--> $DIR/defaults-suitability.rs:27:5

0 commit comments

Comments
 (0)