Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

detect () to avoid redundant <> suggestion for type #104497

Merged
merged 1 commit into from
Nov 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1926,12 +1926,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::Str
| ty::Projection(_)
| ty::Param(_) => format!("{deref_ty}"),
// we need to test something like <&[_]>::len
// we need to test something like <&[_]>::len or <(&[u32])>::len
// and Vec::function();
// <&[_]>::len doesn't need an extra "<>" between
// <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
// but for Adt type like Vec::function()
// we would suggest <[_]>::function();
_ if self.tcx.sess.source_map().span_wrapped_by_angle_bracket(ty.span) => format!("{deref_ty}"),
_ if self.tcx.sess.source_map().span_wrapped_by_angle_or_parentheses(ty.span) => format!("{deref_ty}"),
_ => format!("<{deref_ty}>"),
};
err.span_suggestion_verbose(
Expand Down
25 changes: 21 additions & 4 deletions compiler/rustc_span/src/source_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -753,22 +753,29 @@ impl SourceMap {
}
}

/// Given a 'Span', tries to tell if the next character is '>'
/// and the previous charactoer is '<' after skipping white space
/// return true if wrapped by '<>'
pub fn span_wrapped_by_angle_bracket(&self, span: Span) -> bool {
/// Given a 'Span', tries to tell if it's wrapped by "<>" or "()"
/// the algorithm searches if the next character is '>' or ')' after skipping white space
/// then searches the previous charactoer to match '<' or '(' after skipping white space
/// return true if wrapped by '<>' or '()'
pub fn span_wrapped_by_angle_or_parentheses(&self, span: Span) -> bool {
self.span_to_source(span, |src, start_index, end_index| {
if src.get(start_index..end_index).is_none() {
return Ok(false);
}
// test the right side to match '>' after skipping white space
let end_src = &src[end_index..];
let mut i = 0;
let mut found_right_parentheses = false;
let mut found_right_angle = false;
while let Some(cc) = end_src.chars().nth(i) {
if cc == ' ' {
i = i + 1;
} else if cc == '>' {
// found > in the right;
found_right_angle = true;
break;
} else if cc == ')' {
found_right_parentheses = true;
break;
} else {
// failed to find '>' return false immediately
Expand All @@ -786,6 +793,16 @@ impl SourceMap {
i = i - 1;
} else if cc == '<' {
// found < in the left
if !found_right_angle {
// skip something like "(< )>"
return Ok(false);
}
break;
} else if cc == '(' {
if !found_right_parentheses {
// skip something like "<(>)"
return Ok(false);
}
break;
} else {
// failed to find '<' return false immediately
Expand Down
8 changes: 8 additions & 0 deletions src/test/ui/type/issue-103271.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,12 @@ fn main() {
let x: &u32 = item;
assert_eq!(x, &1);
}
let iter_fun2 = <(&[u32])>::iter;
//~^ no function or associated item named `iter` found for reference `&[u32]` in the current scope [E0599]
//~| function or associated item not found in `&[u32]`
//~| HELP the function `iter` is implemented on `[u32]`
for item2 in iter_fun2(&[1,1]) {
let x: &u32 = item2;
assert_eq!(x, &1);
}
}
13 changes: 12 additions & 1 deletion src/test/ui/type/issue-103271.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@ help: the function `iter` is implemented on `[u32]`
LL | let iter_fun = <[u32]>::iter;
| ~~~~~

error: aborting due to previous error
error[E0599]: no function or associated item named `iter` found for reference `&[u32]` in the current scope
--> $DIR/issue-103271.rs:10:33
|
LL | let iter_fun2 = <(&[u32])>::iter;
| ^^^^ function or associated item not found in `&[u32]`
|
help: the function `iter` is implemented on `[u32]`
|
LL | let iter_fun2 = <([u32])>::iter;
| ~~~~~

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0599`.