]> git.lizzy.rs Git - rust.git/commitdiff
Suggest borrowing in more unsized fn param cases
authorEsteban Küber <esteban@kuber.com.ar>
Sat, 11 Jul 2020 01:11:40 +0000 (18:11 -0700)
committerEsteban Küber <esteban@kuber.com.ar>
Tue, 14 Jul 2020 17:50:24 +0000 (10:50 -0700)
15 files changed:
src/librustc_ast_lowering/expr.rs
src/librustc_ast_lowering/item.rs
src/librustc_hir/hir.rs
src/librustc_trait_selection/traits/error_reporting/mod.rs
src/librustc_trait_selection/traits/error_reporting/suggestions.rs
src/test/ui/async-await/issue-72590-type-error-sized.stderr
src/test/ui/error-codes/E0277.stderr
src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
src/test/ui/issues/issue-27078.stderr
src/test/ui/issues/issue-5883.stderr
src/test/ui/resolve/issue-5035-2.stderr
src/test/ui/str/str-array-assignment.stderr
src/test/ui/suggestions/path-by-value.stderr
src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
src/test/ui/unsized6.stderr

index 90a3a5ec64e0e56ba973720bc30932a8e9ffd267..201972fcf264bd505b6e5f61b187f1e4e0be9541 100644 (file)
@@ -526,7 +526,7 @@ pub(super) fn make_async_expr(
             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| {
index 00665c4cafb6b4d24d23c180cddeecaa52cd0414..dd5e658102facacbe5688df07b9427c7961a5c03 100644 (file)
@@ -972,6 +972,7 @@ fn lower_param(&mut self, param: &Param) -> hir::Param<'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 @@ fn lower_maybe_async_body(
                     attrs: parameter.attrs,
                     hir_id: parameter.hir_id,
                     pat: new_parameter_pat,
+                    ty_span: parameter.ty_span,
                     span: parameter.span,
                 };
 
index f3dfec7ca72150386063bb74dacc5dd9df1508a1..07b489a75626708528388cab5e92774867506e48 100644 (file)
@@ -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,
 }
 
index ad6e81ed3e8893610295f83885fcb680308f4312..6fb07f5e1954c6ea4c76c8a72d0cd715631dd471 100644 (file)
@@ -403,7 +403,6 @@ fn report_selection_error(
                         }
 
                         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);
index 3daa5b3b1abdc93d901b904bae95deea2f24fe43..9bcc2a885fe12243be40f692812146bd51efd26e 100644 (file)
@@ -43,12 +43,6 @@ fn suggest_restricting_param_bound(
         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 @@ fn suggest_dereferences(
         }
     }
 
-    /// 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 @@ fn note_obligation_cause_code<T>(
                     }
                 }
             }
-            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");
                 }
index 95ed9513f357b2da7f86137ab9c9ac3be9af7279..762afa6450a955c7395e0fadba680db714b54dc7 100644 (file)
@@ -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
 
index 8789bb9609bd4753c3a83cbabcfab630e2245af3..203fc18915647fcbacbddbf9fa101a1e0b396dc9 100644 (file)
@@ -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
index 0775431a9d350269da9fa573b6d772d1d935afb0..0195cc1481e74ce1adc170620a7d909bb8c3b9ce 100644 (file)
@@ -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
 
index 313c294e8a1a56687ce12bc9287c693cefc34c30..4b031d26ad53b9dff6bb835143cbec140c45fed4 100644 (file)
@@ -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
 
index 149d882af78ffd8632488454fc4cff4fc30e4653..897984d0ae410eb483502ad901f698e0d9e55336 100644 (file)
@@ -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
index ec2882d6c6d7366fef76173819cdc24a8ff055b3..4ed93ad3279adec5bb4ea680e90ed9ab29b84d6b 100644 (file)
@@ -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
 
index 0b1832d70ff860b7dbc4c21debdd2fee94ee3a22..52d3aefe125c03b6bd374a543283c33eae17eabc 100644 (file)
@@ -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
index 5bd50fea1cb6c19957b5da94e0e4152811d0a508..2b7c29e20cd31092e670f09108329e26518b5394 100644 (file)
@@ -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
 
index 082d787fb0b7bcb2ec7d1e61243b9408f4f5a876..daca91abff8433fc9573cf8b44951a1ac0896e1c 100644 (file)
@@ -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
 
index d566399e5ba0044b25c5b814bde4e9e17bc27cc5..82f1e87008d30bfa30e76aafcedae9d0aa5559c3 100644 (file)
@@ -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