about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2020-07-10 18:11:40 -0700
committerEsteban Küber <esteban@kuber.com.ar>2020-07-14 10:50:24 -0700
commitd989796b478764e1a535951b56d150ab42f1d891 (patch)
tree796c95bb1b84ca652695f3320d0e20fa82bea385
parentb7db6bb5af8187ccb9be1076dd99d3cbb7fd8fa5 (diff)
downloadrust-d989796b478764e1a535951b56d150ab42f1d891.tar.gz
rust-d989796b478764e1a535951b56d150ab42f1d891.zip
Suggest borrowing in more unsized fn param cases
-rw-r--r--src/librustc_ast_lowering/expr.rs2
-rw-r--r--src/librustc_ast_lowering/item.rs2
-rw-r--r--src/librustc_hir/hir.rs1
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/mod.rs1
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/suggestions.rs65
-rw-r--r--src/test/ui/async-await/issue-72590-type-error-sized.stderr5
-rw-r--r--src/test/ui/error-codes/E0277.stderr5
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_locals.stderr5
-rw-r--r--src/test/ui/issues/issue-27078.stderr5
-rw-r--r--src/test/ui/issues/issue-5883.stderr5
-rw-r--r--src/test/ui/resolve/issue-5035-2.stderr5
-rw-r--r--src/test/ui/str/str-array-assignment.stderr8
-rw-r--r--src/test/ui/suggestions/path-by-value.stderr5
-rw-r--r--src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr5
-rw-r--r--src/test/ui/unsized6.stderr10
15 files changed, 80 insertions, 49 deletions
diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs
index 90a3a5ec64e..201972fcf26 100644
--- a/src/librustc_ast_lowering/expr.rs
+++ b/src/librustc_ast_lowering/expr.rs
@@ -526,7 +526,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             Ident::with_dummy_span(sym::_task_context),
             hir::BindingAnnotation::Mutable,
         );
-        let param = hir::Param { attrs: &[], hir_id: self.next_id(), pat, span };
+        let param = hir::Param { attrs: &[], hir_id: self.next_id(), pat, ty_span: span, span };
         let params = arena_vec![self; param];
 
         let body_id = self.lower_body(move |this| {
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index 00665c4cafb..dd5e658102f 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -972,6 +972,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             attrs: self.lower_attrs(&param.attrs),
             hir_id: self.lower_node_id(param.id),
             pat: self.lower_pat(&param.pat),
+            ty_span: param.ty.span,
             span: param.span,
         }
     }
@@ -1098,6 +1099,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     attrs: parameter.attrs,
                     hir_id: parameter.hir_id,
                     pat: new_parameter_pat,
+                    ty_span: parameter.ty_span,
                     span: parameter.span,
                 };
 
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index f3dfec7ca72..07b489a7562 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -2148,6 +2148,7 @@ pub struct Param<'hir> {
     pub attrs: &'hir [Attribute],
     pub hir_id: HirId,
     pub pat: &'hir Pat<'hir>,
+    pub ty_span: Span,
     pub span: Span,
 }
 
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index ad6e81ed3e8..6fb07f5e195 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -403,7 +403,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         }
 
                         self.suggest_dereferences(&obligation, &mut err, &trait_ref, points_at_arg);
-                        self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
                         self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
                         self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
                         self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index 3daa5b3b1ab..9bcc2a885fe 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -43,12 +43,6 @@ pub trait InferCtxtExt<'tcx> {
         body_id: hir::HirId,
     );
 
-    fn suggest_borrow_on_unsized_slice(
-        &self,
-        code: &ObligationCauseCode<'tcx>,
-        err: &mut DiagnosticBuilder<'_>,
-    );
-
     fn suggest_dereferences(
         &self,
         obligation: &PredicateObligation<'tcx>,
@@ -515,32 +509,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         }
     }
 
-    /// 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<'_>,
-    ) {
-        if let &ObligationCauseCode::VariableType(hir_id) = code {
-            let parent_node = self.tcx.hir().get_parent_node(hir_id);
-            if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
-                if let Some(ref expr) = local.init {
-                    if let hir::ExprKind::Index(_, _) = expr.kind {
-                        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
-                            err.span_suggestion(
-                                expr.span,
-                                "consider borrowing here",
-                                format!("&{}", snippet),
-                                Applicability::MachineApplicable,
-                            );
-                        }
-                    }
-                }
-            }
-        }
-    }
-
     /// Given a closure's `DefId`, return the given name of the closure.
     ///
     /// This doesn't account for reassignments, but it's only used for suggestions.
@@ -1817,8 +1785,37 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     }
                 }
             }
-            ObligationCauseCode::VariableType(_) => {
-                err.note("all local variables must have a statically known size");
+            ObligationCauseCode::VariableType(hir_id) => {
+                let parent_node = self.tcx.hir().get_parent_node(hir_id);
+                match self.tcx.hir().find(parent_node) {
+                    Some(Node::Local(hir::Local {
+                        init: Some(hir::Expr { kind: hir::ExprKind::Index(_, _), span, .. }),
+                        ..
+                    })) => {
+                        // 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.
+                        err.span_suggestion_verbose(
+                            span.shrink_to_lo(),
+                            "consider borrowing here",
+                            "&".to_owned(),
+                            Applicability::MachineApplicable,
+                        );
+                        err.note("all local variables must have a statically known size");
+                    }
+                    Some(Node::Param(param)) => {
+                        err.span_suggestion_verbose(
+                            param.ty_span.shrink_to_lo(),
+                            "function arguments must have a statically known size, borrowed types \
+                            always have a known size",
+                            "&".to_owned(),
+                            Applicability::MachineApplicable,
+                        );
+                    }
+                    _ => {
+                        err.note("all local variables must have a statically known size");
+                    }
+                }
                 if !self.tcx.features().unsized_locals {
                     err.help("unsized locals are gated as an unstable feature");
                 }
diff --git a/src/test/ui/async-await/issue-72590-type-error-sized.stderr b/src/test/ui/async-await/issue-72590-type-error-sized.stderr
index 95ed9513f35..762afa6450a 100644
--- a/src/test/ui/async-await/issue-72590-type-error-sized.stderr
+++ b/src/test/ui/async-await/issue-72590-type-error-sized.stderr
@@ -18,8 +18,11 @@ LL |     async fn frob(self) {}
    |
    = help: within `Foo`, the trait `std::marker::Sized` is not implemented for `str`
    = note: required because it appears within the type `Foo`
-   = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL |     async fn frob(&self) {}
+   |                   ^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/error-codes/E0277.stderr b/src/test/ui/error-codes/E0277.stderr
index 8789bb9609b..203fc189156 100644
--- a/src/test/ui/error-codes/E0277.stderr
+++ b/src/test/ui/error-codes/E0277.stderr
@@ -6,8 +6,11 @@ LL | fn f(p: Path) { }
    |
    = help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `std::path::Path`
-   = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn f(p: &Path) { }
+   |         ^
 
 error[E0277]: the trait bound `i32: Foo` is not satisfied
   --> $DIR/E0277.rs:17:15
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
index 0775431a9d3..0195cc1481e 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
@@ -5,8 +5,11 @@ LL | fn f(f: dyn FnOnce()) {}
    |      ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn std::ops::FnOnce() + 'static)`
-   = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn f(f: &dyn FnOnce()) {}
+   |         ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-27078.stderr b/src/test/ui/issues/issue-27078.stderr
index 313c294e8a1..4b031d26ad5 100644
--- a/src/test/ui/issues/issue-27078.stderr
+++ b/src/test/ui/issues/issue-27078.stderr
@@ -5,12 +5,15 @@ LL |     fn foo(self) -> &'static i32 {
    |            ^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `Self`
-   = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
 help: consider further restricting `Self`
    |
 LL |     fn foo(self) -> &'static i32 where Self: std::marker::Sized {
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL |     fn foo(&self) -> &'static i32 {
+   |            ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-5883.stderr b/src/test/ui/issues/issue-5883.stderr
index 149d882af78..897984d0ae4 100644
--- a/src/test/ui/issues/issue-5883.stderr
+++ b/src/test/ui/issues/issue-5883.stderr
@@ -5,8 +5,11 @@ LL | fn new_struct(r: dyn A + 'static)
    |               ^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn A + 'static)`
-   = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn new_struct(r: &dyn A + 'static)
+   |                  ^
 
 error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time
   --> $DIR/issue-5883.rs:8:8
diff --git a/src/test/ui/resolve/issue-5035-2.stderr b/src/test/ui/resolve/issue-5035-2.stderr
index ec2882d6c6d..4ed93ad3279 100644
--- a/src/test/ui/resolve/issue-5035-2.stderr
+++ b/src/test/ui/resolve/issue-5035-2.stderr
@@ -5,8 +5,11 @@ LL | fn foo(_x: K) {}
    |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn I + 'static)`
-   = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn foo(_x: &K) {}
+   |            ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/str/str-array-assignment.stderr b/src/test/ui/str/str-array-assignment.stderr
index 0b1832d70ff..52d3aefe125 100644
--- a/src/test/ui/str/str-array-assignment.stderr
+++ b/src/test/ui/str/str-array-assignment.stderr
@@ -19,13 +19,15 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   --> $DIR/str-array-assignment.rs:7:7
    |
 LL |   let v = s[..2];
-   |       ^   ------ help: consider borrowing here: `&s[..2]`
-   |       |
-   |       doesn't have a size known at compile-time
+   |       ^ doesn't have a 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
    = help: unsized locals are gated as an unstable feature
+help: consider borrowing here
+   |
+LL |   let v = &s[..2];
+   |           ^
 
 error[E0308]: mismatched types
   --> $DIR/str-array-assignment.rs:9:17
diff --git a/src/test/ui/suggestions/path-by-value.stderr b/src/test/ui/suggestions/path-by-value.stderr
index 5bd50fea1cb..2b7c29e20cd 100644
--- a/src/test/ui/suggestions/path-by-value.stderr
+++ b/src/test/ui/suggestions/path-by-value.stderr
@@ -6,8 +6,11 @@ LL | fn f(p: Path) { }
    |
    = help: within `std::path::Path`, the trait `std::marker::Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `std::path::Path`
-   = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn f(p: &Path) { }
+   |         ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr b/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
index 082d787fb0b..daca91abff8 100644
--- a/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
+++ b/src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
@@ -13,8 +13,11 @@ LL | fn foo(_x: Foo + Send) {
    |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `(dyn Foo + std::marker::Send + 'static)`
-   = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn foo(_x: &Foo + Send) {
+   |            ^
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/unsized6.stderr b/src/test/ui/unsized6.stderr
index d566399e5ba..82f1e87008d 100644
--- a/src/test/ui/unsized6.stderr
+++ b/src/test/ui/unsized6.stderr
@@ -144,8 +144,11 @@ LL | fn g1<X: ?Sized>(x: X) {}
    |       this type parameter needs to be `std::marker::Sized`
    |
    = help: the trait `std::marker::Sized` is not implemented for `X`
-   = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn g1<X: ?Sized>(x: &X) {}
+   |                     ^
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
   --> $DIR/unsized6.rs:40:22
@@ -156,8 +159,11 @@ LL | fn g2<X: ?Sized + T>(x: X) {}
    |       this type parameter needs to be `std::marker::Sized`
    |
    = help: the trait `std::marker::Sized` is not implemented for `X`
-   = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
+help: function arguments must have a statically known size, borrowed types always have a known size
+   |
+LL | fn g2<X: ?Sized + T>(x: &X) {}
+   |                         ^
 
 error: aborting due to 13 previous errors