From d989796b478764e1a535951b56d150ab42f1d891 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Esteban=20K=C3=BCber?= Date: Fri, 10 Jul 2020 18:11:40 -0700 Subject: [PATCH] Suggest borrowing in more unsized fn param cases --- src/librustc_ast_lowering/expr.rs | 2 +- src/librustc_ast_lowering/item.rs | 2 + src/librustc_hir/hir.rs | 1 + .../traits/error_reporting/mod.rs | 1 - .../traits/error_reporting/suggestions.rs | 65 +++++++++---------- .../issue-72590-type-error-sized.stderr | 5 +- src/test/ui/error-codes/E0277.stderr | 5 +- .../feature-gate-unsized_locals.stderr | 5 +- src/test/ui/issues/issue-27078.stderr | 5 +- src/test/ui/issues/issue-5883.stderr | 5 +- src/test/ui/resolve/issue-5035-2.stderr | 5 +- src/test/ui/str/str-array-assignment.stderr | 8 ++- src/test/ui/suggestions/path-by-value.stderr | 5 +- .../trait-bounds-not-on-bare-trait.stderr | 5 +- src/test/ui/unsized6.stderr | 10 ++- 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 @@ 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| { 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 @@ fn lower_param(&mut self, param: &Param) -> hir::Param<'hir> { attrs: self.lower_attrs(¶m.attrs), hir_id: self.lower_node_id(param.id), pat: self.lower_pat(¶m.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, }; 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 @@ 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); 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 @@ 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( } } } - 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: 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: &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: 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: &X) {} + | ^ error: aborting due to 13 previous errors -- 2.44.0