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

Suggest using slice when encountering let x = ""[..]; #46249

Merged
merged 4 commits into from
Nov 28, 2017
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
23 changes: 23 additions & 0 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
trait_ref.self_ty()));
}

self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);

// Try to report a help message
if !trait_ref.has_infer_types() &&
self.predicate_can_apply(obligation.param_env, trait_ref) {
Expand Down Expand Up @@ -821,6 +823,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
err.emit();
}

/// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why just for assignments and not all the cases in the test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other cases in the test go through type check instead. I'll see if I can expand #46256 to also suggest in these cases. I included all the cases originally mentioned in order to make sure we don't regress in any of the cases (without noticing).

/// suggestion to borrow the initializer in order to use have a slice instead.
fn suggest_borrow_on_unsized_slice(&self,
code: &ObligationCauseCode<'tcx>,
err: &mut DiagnosticBuilder<'tcx>) {
if let &ObligationCauseCode::VariableType(node_id) = code {
let parent_node = self.tcx.hir.get_parent_node(node_id);
if let Some(hir::map::NodeLocal(ref local)) = self.tcx.hir.find(parent_node) {
if let Some(ref expr) = local.init {
if let hir::ExprIndex(_, _) = expr.node {
if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(expr.span) {
err.span_suggestion(expr.span,
"consider borrowing here",
format!("&{}", snippet));
}
}
}
}
}
}

fn report_arg_count_mismatch(
&self,
span: Span,
Expand Down
32 changes: 32 additions & 0 deletions src/test/ui/suggestions/str-array-assignment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn main() { //~ NOTE expected `()` because of default return type
let s = "abc";
let t = if true { s[..2] } else { s };
//~^ ERROR if and else have incompatible types
//~| NOTE expected str, found &str
//~| NOTE expected type
let u: &str = if true { s[..2] } else { s };
//~^ ERROR mismatched types
//~| NOTE expected &str, found str
//~| NOTE expected type
let v = s[..2];
//~^ ERROR the trait bound `str: std::marker::Sized` is not satisfied
//~| HELP consider borrowing here
//~| NOTE `str` does not have a constant size known at compile-time
//~| HELP the trait `std::marker::Sized` is not implemented for `str`
//~| NOTE all local variables must have a statically known size
let w: &str = s[..2];
//~^ ERROR mismatched types
//~| NOTE expected &str, found str
//~| NOTE expected type
//~| HELP try with `&s[..2]`
}
44 changes: 44 additions & 0 deletions src/test/ui/suggestions/str-array-assignment.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
error[E0308]: if and else have incompatible types
--> $DIR/str-array-assignment.rs:13:11
|
13 | let t = if true { s[..2] } else { s };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected str, found &str
|
= note: expected type `str`
found type `&str`

error[E0308]: mismatched types
--> $DIR/str-array-assignment.rs:17:27
|
11 | fn main() { //~ NOTE expected `()` because of default return type
| - expected `()` because of default return type
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks dubious. Could you look into this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I noticed that too. Still digging.

Copy link
Contributor

@arielb1 arielb1 Nov 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's also already the case on nightly. Feel free to ignore this and open an issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...
17 | let u: &str = if true { s[..2] } else { s };
| ^^^^^^ expected &str, found str
|
= note: expected type `&str`
found type `str`

error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> $DIR/str-array-assignment.rs:21:7
|
21 | let v = s[..2];
| ^ ------ help: consider borrowing here: `&s[..2]`
| |
| `str` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: all local variables must have a statically known size

error[E0308]: mismatched types
--> $DIR/str-array-assignment.rs:27:17
|
27 | let w: &str = s[..2];
| ^^^^^^ expected &str, found str
|
= note: expected type `&str`
found type `str`
= help: try with `&s[..2]`

error: aborting due to 4 previous errors