Skip to content

Commit

Permalink
Suggest borrowing in more unsized fn param cases
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Jul 14, 2020
1 parent b7db6bb commit d989796
Show file tree
Hide file tree
Showing 15 changed files with 80 additions and 49 deletions.
2 changes: 1 addition & 1 deletion src/librustc_ast_lowering/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_ast_lowering/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand Down Expand Up @@ -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,
};

Expand Down
1 change: 1 addition & 0 deletions src/librustc_hir/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down
1 change: 0 additions & 1 deletion src/librustc_trait_selection/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
65 changes: 31 additions & 34 deletions src/librustc_trait_selection/traits/error_reporting/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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");
}
Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/async-await/issue-72590-type-error-sized.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/error-codes/E0277.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/feature-gates/feature-gate-unsized_locals.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-27078.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/issues/issue-5883.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/resolve/issue-5035-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 5 additions & 3 deletions src/test/ui/str/str-array-assignment.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/suggestions/path-by-value.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 4 additions & 1 deletion src/test/ui/traits/trait-bounds-not-on-bare-trait.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 8 additions & 2 deletions src/test/ui/unsized6.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down

0 comments on commit d989796

Please sign in to comment.