Suggest borrowing in more unsized fn param cases

This commit is contained in:
Esteban Küber 2020-07-10 18:11:40 -07:00
parent b7db6bb5af
commit d989796b47
15 changed files with 80 additions and 49 deletions

View File

@ -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| {

View File

@ -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,
};

View 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,
}

View File

@ -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);

View File

@ -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");
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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