Skip to content

Commit 7995a08

Browse files
committed
Increase verbosity when suggesting subtle code changes
1 parent 1581278 commit 7995a08

32 files changed

+361
-240
lines changed

src/librustc_infer/infer/error_reporting/need_type_info.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::infer::InferCtxt;
33
use rustc::hir::map::Map;
44
use rustc::ty::print::Print;
55
use rustc::ty::{self, DefIdTree, Infer, Ty, TyVar};
6-
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
6+
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
77
use rustc_hir as hir;
88
use rustc_hir::def::{DefKind, Namespace};
99
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
@@ -462,24 +462,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
462462
e: &Expr<'_>,
463463
err: &mut DiagnosticBuilder<'_>,
464464
) {
465-
if let (Ok(snippet), Some(tables), None) = (
466-
self.tcx.sess.source_map().span_to_snippet(segment.ident.span),
467-
self.in_progress_tables,
468-
&segment.args,
469-
) {
465+
if let (Some(tables), None) = (self.in_progress_tables, &segment.args) {
470466
let borrow = tables.borrow();
471467
if let Some((DefKind::Method, did)) = borrow.type_dependent_def(e.hir_id) {
472468
let generics = self.tcx.generics_of(did);
473469
if !generics.params.is_empty() {
474-
err.span_suggestion(
475-
segment.ident.span,
470+
err.span_suggestion_verbose(
471+
segment.ident.span.shrink_to_hi(),
476472
&format!(
477473
"consider specifying the type argument{} in the method call",
478-
if generics.params.len() > 1 { "s" } else { "" },
474+
pluralize!(generics.params.len()),
479475
),
480476
format!(
481-
"{}::<{}>",
482-
snippet,
477+
"::<{}>",
483478
generics
484479
.params
485480
.iter()

src/librustc_infer/traits/error_reporting/mod.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use rustc::ty::{
2323
};
2424
use rustc_ast::ast;
2525
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
26-
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder};
26+
use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
2727
use rustc_hir as hir;
2828
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
2929
use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate};
@@ -1186,15 +1186,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
11861186
// |
11871187
// = note: cannot resolve `_: Tt`
11881188

1189-
err.span_suggestion(
1190-
span,
1189+
err.span_suggestion_verbose(
1190+
span.shrink_to_hi(),
11911191
&format!(
11921192
"consider specifying the type argument{} in the function call",
1193-
if generics.params.len() > 1 { "s" } else { "" },
1193+
pluralize!(generics.params.len()),
11941194
),
11951195
format!(
1196-
"{}::<{}>",
1197-
snippet,
1196+
"::<{}>",
11981197
generics
11991198
.params
12001199
.iter()
@@ -1356,7 +1355,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
13561355
[] => (span.shrink_to_hi(), ":"),
13571356
[.., bound] => (bound.span().shrink_to_hi(), " + "),
13581357
};
1359-
err.span_suggestion(
1358+
err.span_suggestion_verbose(
13601359
span,
13611360
"consider relaxing the implicit `Sized` restriction",
13621361
format!("{} ?Sized", separator),

src/librustc_infer/traits/error_reporting/suggestions.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
265265
}
266266
let hir = self.tcx.hir();
267267
// Get the name of the callable and the arguments to be used in the suggestion.
268-
let snippet = match hir.get_if_local(def_id) {
268+
let (snippet, sugg) = match hir.get_if_local(def_id) {
269269
Some(hir::Node::Expr(hir::Expr {
270270
kind: hir::ExprKind::Closure(_, decl, _, span, ..),
271271
..
@@ -276,7 +276,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
276276
None => return,
277277
};
278278
let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
279-
format!("{}({})", name, args)
279+
let sugg = format!("({})", args);
280+
(format!("{}{}", name, sugg), sugg)
280281
}
281282
Some(hir::Node::Item(hir::Item {
282283
ident,
@@ -297,7 +298,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
297298
})
298299
.collect::<Vec<_>>()
299300
.join(", ");
300-
format!("{}({})", ident, args)
301+
let sugg = format!("({})", args);
302+
(format!("{}{}", ident, sugg), sugg)
301303
}
302304
_ => return,
303305
};
@@ -306,10 +308,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
306308
// an argument, the `obligation.cause.span` points at the expression
307309
// of the argument, so we can provide a suggestion. This is signaled
308310
// by `points_at_arg`. Otherwise, we give a more general note.
309-
err.span_suggestion(
310-
obligation.cause.span,
311+
err.span_suggestion_verbose(
312+
obligation.cause.span.shrink_to_hi(),
311313
&msg,
312-
snippet,
314+
sugg,
313315
Applicability::HasPlaceholders,
314316
);
315317
} else {
@@ -494,7 +496,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
494496
.source_map()
495497
.span_take_while(span, |c| c.is_whitespace() || *c == '&');
496498
if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
497-
err.span_suggestion(
499+
err.span_suggestion_verbose(
498500
sp,
499501
"consider changing this borrow's mutability",
500502
"&mut ".to_string(),
@@ -898,11 +900,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
898900
// For example, if `expected_args_length` is 2, suggest `|_, _|`.
899901
if found_args.is_empty() && is_closure {
900902
let underscores = vec!["_"; expected_args.len()].join(", ");
901-
err.span_suggestion(
903+
err.span_suggestion_verbose(
902904
pipe_span,
903905
&format!(
904906
"consider changing the closure to take and ignore the expected argument{}",
905-
if expected_args.len() < 2 { "" } else { "s" }
907+
pluralize!(expected_args.len())
906908
),
907909
format!("|{}|", underscores),
908910
Applicability::MachineApplicable,
@@ -916,7 +918,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
916918
.map(|(name, _)| name.to_owned())
917919
.collect::<Vec<String>>()
918920
.join(", ");
919-
err.span_suggestion(
921+
err.span_suggestion_verbose(
920922
found_span,
921923
"change the closure to take multiple arguments instead of a single tuple",
922924
format!("|{}|", sugg),
@@ -953,7 +955,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
953955
String::new()
954956
},
955957
);
956-
err.span_suggestion(
958+
err.span_suggestion_verbose(
957959
found_span,
958960
"change the closure to accept a tuple instead of individual arguments",
959961
sugg,

src/librustc_typeck/check/method/mod.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
136136
self_ty: Ty<'tcx>,
137137
call_expr: &hir::Expr<'_>,
138138
) {
139-
let has_params = self
139+
let params = self
140140
.probe_for_name(
141141
method_name.span,
142142
probe::Mode::MethodCall,
@@ -146,26 +146,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
146146
call_expr.hir_id,
147147
ProbeScope::TraitsInScope,
148148
)
149-
.and_then(|pick| {
149+
.map(|pick| {
150150
let sig = self.tcx.fn_sig(pick.item.def_id);
151-
Ok(sig.inputs().skip_binder().len() > 1)
152-
});
151+
sig.inputs().skip_binder().len().saturating_sub(1)
152+
})
153+
.unwrap_or(0);
153154

154155
// Account for `foo.bar<T>`;
155-
let sugg_span = method_name.span.with_hi(call_expr.span.hi());
156-
let snippet = self
157-
.tcx
158-
.sess
159-
.source_map()
160-
.span_to_snippet(sugg_span)
161-
.unwrap_or_else(|_| method_name.to_string());
162-
let (suggestion, applicability) = if has_params.unwrap_or_default() {
163-
(format!("{}(...)", snippet), Applicability::HasPlaceholders)
164-
} else {
165-
(format!("{}()", snippet), Applicability::MaybeIncorrect)
166-
};
156+
let sugg_span = call_expr.span.shrink_to_hi();
157+
let (suggestion, applicability) = (
158+
format!("({})", (0..params).map(|_| "_").collect::<Vec<_>>().join(", ")),
159+
if params > 0 { Applicability::HasPlaceholders } else { Applicability::MaybeIncorrect },
160+
);
167161

168-
err.span_suggestion(sugg_span, msg, suggestion, applicability);
162+
err.span_suggestion_verbose(sugg_span, msg, suggestion, applicability);
169163
}
170164

171165
/// Performs method lookup. If lookup is successful, it will return the callee

src/librustc_typeck/check/mod.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4951,15 +4951,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
49514951
}
49524952
_ => {}
49534953
}
4954-
if let Ok(code) = self.sess().source_map().span_to_snippet(expr.span) {
4955-
err.span_suggestion(
4956-
expr.span,
4957-
&format!("use parentheses to {}", msg),
4958-
format!("{}({})", code, sugg_call),
4959-
applicability,
4960-
);
4961-
return true;
4962-
}
4954+
err.span_suggestion_verbose(
4955+
expr.span.shrink_to_hi(),
4956+
&format!("use parentheses to {}", msg),
4957+
format!("({})", sugg_call),
4958+
applicability,
4959+
);
4960+
return true;
49634961
}
49644962
false
49654963
}

src/librustc_typeck/check/pat.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -752,17 +752,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
752752
res.descr(),
753753
),
754754
);
755-
let (msg, sugg) = match parent_pat {
756-
Some(Pat { kind: hir::PatKind::Struct(..), .. }) => (
757-
"bind the struct field to a different name instead",
758-
format!("{}: other_{}", ident, ident.as_str().to_lowercase()),
759-
),
760-
_ => (
761-
"introduce a new binding instead",
762-
format!("other_{}", ident.as_str().to_lowercase()),
763-
),
755+
match parent_pat {
756+
Some(Pat { kind: hir::PatKind::Struct(..), .. }) => {
757+
e.span_suggestion_verbose(
758+
ident.span.shrink_to_hi(),
759+
"bind the struct field to a different name instead",
760+
format!(": other_{}", ident.as_str().to_lowercase()),
761+
Applicability::HasPlaceholders,
762+
);
763+
}
764+
_ => {
765+
let msg = "introduce a new binding instead";
766+
let sugg = format!("other_{}", ident.as_str().to_lowercase());
767+
e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders);
768+
}
764769
};
765-
e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders);
766770
}
767771
}
768772
e.emit();

src/test/ui/error-codes/E0615.stderr

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ error[E0615]: attempted to take value of method `method` on type `Foo`
22
--> $DIR/E0615.rs:11:7
33
|
44
LL | f.method;
5-
| ^^^^^^ help: use parentheses to call the method: `method()`
5+
| ^^^^^^
6+
|
7+
help: use parentheses to call the method
8+
|
9+
LL | f.method();
10+
| ^^
611

712
error: aborting due to previous error
813

src/test/ui/extern/extern-types-unsized.stderr

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim
22
--> $DIR/extern-types-unsized.rs:22:20
33
|
44
LL | fn assert_sized<T>() { }
5-
| ------------ -- help: consider relaxing the implicit `Sized` restriction: `: ?Sized`
6-
| |
7-
| required by this bound in `assert_sized`
5+
| ------------ - required by this bound in `assert_sized`
86
...
97
LL | assert_sized::<A>();
108
| ^ doesn't have a size known at compile-time
119
|
1210
= help: the trait `std::marker::Sized` is not implemented for `A`
1311
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
12+
help: consider relaxing the implicit `Sized` restriction
13+
|
14+
LL | fn assert_sized<T: ?Sized>() { }
15+
| ^^^^^^^^
1416

1517
error[E0277]: the size for values of type `A` cannot be known at compilation time
1618
--> $DIR/extern-types-unsized.rs:25:5

src/test/ui/implicit-method-bind.stderr

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ error[E0615]: attempted to take value of method `abs` on type `i32`
22
--> $DIR/implicit-method-bind.rs:2:20
33
|
44
LL | let _f = 10i32.abs;
5-
| ^^^ help: use parentheses to call the method: `abs()`
5+
| ^^^
6+
|
7+
help: use parentheses to call the method
8+
|
9+
LL | let _f = 10i32.abs();
10+
| ^^
611

712
error: aborting due to previous error
813

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ error[E0615]: attempted to take value of method `get` on type `std::boxed::Box<(
22
--> $DIR/issue-13853-2.rs:5:43
33
|
44
LL | fn foo(res : Box<dyn ResponseHook>) { res.get }
5-
| ^^^ help: use parentheses to call the method: `get()`
5+
| ^^^
6+
|
7+
help: use parentheses to call the method
8+
|
9+
LL | fn foo(res : Box<dyn ResponseHook>) { res.get() }
10+
| ^^
611

712
error: aborting due to previous error
813

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ error[E0616]: field `len` of struct `sub::S` is private
22
--> $DIR/issue-26472.rs:11:13
33
|
44
LL | let v = s.len;
5-
| ^^---
6-
| |
7-
| help: a method `len` also exists, call it with parentheses: `len()`
5+
| ^^^^^
6+
|
7+
help: a method `len` also exists, call it with parentheses
8+
|
9+
LL | let v = s.len();
10+
| ^^
811

912
error[E0616]: field `len` of struct `sub::S` is private
1013
--> $DIR/issue-26472.rs:12:5

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ LL | struct Foo(u32);
55
| ---------------- fn(u32) -> Foo {Foo} defined here
66
LL |
77
LL | fn test() -> Foo { Foo }
8-
| --- ^^^
9-
| | |
10-
| | expected struct `Foo`, found fn item
11-
| | help: use parentheses to instantiate this tuple struct: `Foo(_)`
8+
| --- ^^^ expected struct `Foo`, found fn item
9+
| |
1210
| expected `Foo` because of return type
1311
|
1412
= note: expected struct `Foo`
1513
found fn item `fn(u32) -> Foo {Foo}`
14+
help: use parentheses to instantiate this tuple struct
15+
|
16+
LL | fn test() -> Foo { Foo(_) }
17+
| ^^^
1618

1719
error: aborting due to previous error
1820

src/test/ui/methods/method-missing-call.stderr

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,23 @@ error[E0615]: attempted to take value of method `get_x` on type `Point`
22
--> $DIR/method-missing-call.rs:22:26
33
|
44
LL | .get_x;
5-
| ^^^^^ help: use parentheses to call the method: `get_x()`
5+
| ^^^^^
6+
|
7+
help: use parentheses to call the method
8+
|
9+
LL | .get_x();
10+
| ^^
611

712
error[E0615]: attempted to take value of method `filter_map` on type `std::iter::Filter<std::iter::Map<std::slice::Iter<'_, {integer}>, [closure@$DIR/method-missing-call.rs:27:20: 27:25]>, [closure@$DIR/method-missing-call.rs:28:23: 28:35]>`
813
--> $DIR/method-missing-call.rs:29:16
914
|
1015
LL | .filter_map;
11-
| ^^^^^^^^^^ help: use parentheses to call the method: `filter_map(...)`
16+
| ^^^^^^^^^^
17+
|
18+
help: use parentheses to call the method
19+
|
20+
LL | .filter_map(_);
21+
| ^^^
1222

1323
error: aborting due to 2 previous errors
1424

0 commit comments

Comments
 (0)