about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2017-11-28 03:16:46 +0800
committerGitHub <noreply@github.com>2017-11-28 03:16:46 +0800
commita60ffa06aebeb87acfd6c3226a91ed508b124e21 (patch)
tree629a74176b58c1acf0800857cf6596f3221cbe0e
parent840e6c12ba0b6ab500040b65c10b611ef201f8af (diff)
parentfa44927d2c017359a7d4b14a31e96ee35472b406 (diff)
downloadrust-a60ffa06aebeb87acfd6c3226a91ed508b124e21.tar.gz
rust-a60ffa06aebeb87acfd6c3226a91ed508b124e21.zip
Rollup merge of #46249 - estebank:suggest-slice, r=arielb1
Suggest using slice when encountering `let x = ""[..];`

Fix #26319.
-rw-r--r--src/librustc/traits/error_reporting.rs23
-rw-r--r--src/test/ui/suggestions/str-array-assignment.rs32
-rw-r--r--src/test/ui/suggestions/str-array-assignment.stderr44
3 files changed, 99 insertions, 0 deletions
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 46ec2be4a1f..5703c5c870e 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -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) {
@@ -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
+    /// 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,
diff --git a/src/test/ui/suggestions/str-array-assignment.rs b/src/test/ui/suggestions/str-array-assignment.rs
new file mode 100644
index 00000000000..6c7f4852a4a
--- /dev/null
+++ b/src/test/ui/suggestions/str-array-assignment.rs
@@ -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]`
+}
diff --git a/src/test/ui/suggestions/str-array-assignment.stderr b/src/test/ui/suggestions/str-array-assignment.stderr
new file mode 100644
index 00000000000..14b744c2e46
--- /dev/null
+++ b/src/test/ui/suggestions/str-array-assignment.stderr
@@ -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
+...
+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
+