diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 46ec2be4a1f9b..5703c5c870e88 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 0000000000000..6c7f4852a4ae5 --- /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 or the MIT license +// , 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 0000000000000..14b744c2e469c --- /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 +