mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-21 17:52:12 +03:00
Suggest returning a reference for unsized place from a closure
This commit is contained in:
@@ -2746,6 +2746,11 @@ pub fn note_obligation_cause(
|
||||
obligation.param_env,
|
||||
obligation.cause.code(),
|
||||
);
|
||||
self.suggest_borrow_for_unsized_closure_return(
|
||||
obligation.cause.body_id,
|
||||
err,
|
||||
obligation.predicate,
|
||||
);
|
||||
self.suggest_unsized_bound_if_applicable(err, obligation);
|
||||
if let Some(span) = err.span.primary_span()
|
||||
&& let Some(mut diag) =
|
||||
|
||||
@@ -2193,6 +2193,60 @@ pub(super) fn suggest_semicolon_removal(
|
||||
false
|
||||
}
|
||||
|
||||
pub(super) fn suggest_borrow_for_unsized_closure_return<G: EmissionGuarantee>(
|
||||
&self,
|
||||
body_id: LocalDefId,
|
||||
err: &mut Diag<'_, G>,
|
||||
predicate: ty::Predicate<'tcx>,
|
||||
) {
|
||||
let Some(pred) = predicate.as_trait_clause() else {
|
||||
return;
|
||||
};
|
||||
if !self.tcx.is_lang_item(pred.def_id(), LangItem::Sized) {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(span) = err.span.primary_span() else {
|
||||
return;
|
||||
};
|
||||
let Some(node_body_id) = self.tcx.hir_node_by_def_id(body_id).body_id() else {
|
||||
return;
|
||||
};
|
||||
let body = self.tcx.hir_body(node_body_id);
|
||||
let mut expr_finder = FindExprBySpan::new(span, self.tcx);
|
||||
expr_finder.visit_expr(body.value);
|
||||
let Some(expr) = expr_finder.result else {
|
||||
return;
|
||||
};
|
||||
|
||||
let closure = match expr.kind {
|
||||
hir::ExprKind::Call(_, args) => args.iter().find_map(|arg| match arg.kind {
|
||||
hir::ExprKind::Closure(closure) => Some(closure),
|
||||
_ => None,
|
||||
}),
|
||||
hir::ExprKind::MethodCall(_, _, args, _) => {
|
||||
args.iter().find_map(|arg| match arg.kind {
|
||||
hir::ExprKind::Closure(closure) => Some(closure),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
let Some(closure) = closure else {
|
||||
return;
|
||||
};
|
||||
if !matches!(closure.fn_decl.output, hir::FnRetTy::DefaultReturn(_)) {
|
||||
return;
|
||||
}
|
||||
|
||||
err.span_suggestion_verbose(
|
||||
self.tcx.hir_body(closure.body).value.span.shrink_to_lo(),
|
||||
"consider borrowing the value",
|
||||
"&",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
|
||||
pub(super) fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span> {
|
||||
let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn { sig, .. }, .. }) =
|
||||
self.tcx.hir_node_by_def_id(obligation.cause.body_id)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#![allow(unused_variables, for_loops_over_fallibles)]
|
||||
//@ run-rustfix
|
||||
|
||||
fn main() {
|
||||
// Basic case from the issue: str slice
|
||||
let o = Some("Hello, world!");
|
||||
for s in o.map(|s| &s[3..8]) {}
|
||||
//~^ ERROR the size for values of type `str` cannot be known at compilation time
|
||||
//~| ERROR the size for values of type `str` cannot be known at compilation time
|
||||
//~| ERROR the size for values of type `str` cannot be known at compilation time
|
||||
//~| ERROR `Option<str>` is not an iterator
|
||||
|
||||
// Byte slice case
|
||||
let arr = Some(b"Hello, world!");
|
||||
for s in arr.map(|s| &s[3..8]) {}
|
||||
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
//~| ERROR `Option<[u8]>` is not an iterator
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#![allow(unused_variables, for_loops_over_fallibles)]
|
||||
//@ run-rustfix
|
||||
|
||||
fn main() {
|
||||
// Basic case from the issue: str slice
|
||||
let o = Some("Hello, world!");
|
||||
for s in o.map(|s| s[3..8]) {}
|
||||
//~^ ERROR the size for values of type `str` cannot be known at compilation time
|
||||
//~| ERROR the size for values of type `str` cannot be known at compilation time
|
||||
//~| ERROR the size for values of type `str` cannot be known at compilation time
|
||||
//~| ERROR `Option<str>` is not an iterator
|
||||
|
||||
// Byte slice case
|
||||
let arr = Some(b"Hello, world!");
|
||||
for s in arr.map(|s| s[3..8]) {}
|
||||
//~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
|
||||
//~| ERROR `Option<[u8]>` is not an iterator
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
--> $DIR/unsized-return-suggest-ref-issue-152064.rs:7:16
|
||||
|
|
||||
LL | for s in o.map(|s| s[3..8]) {}
|
||||
| ^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `str`
|
||||
note: required by an implicit `Sized` bound in `Option::<T>::map`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
||||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
--> $DIR/unsized-return-suggest-ref-issue-152064.rs:7:24
|
||||
|
|
||||
LL | for s in o.map(|s| s[3..8]) {}
|
||||
| ^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `str`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0277]: the size for values of type `str` cannot be known at compilation time
|
||||
--> $DIR/unsized-return-suggest-ref-issue-152064.rs:7:14
|
||||
|
|
||||
LL | for s in o.map(|s| s[3..8]) {}
|
||||
| ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `str`
|
||||
note: required by an implicit `Sized` bound in `Option`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
help: consider borrowing the value
|
||||
|
|
||||
LL | for s in o.map(|s| &s[3..8]) {}
|
||||
| +
|
||||
|
||||
error[E0277]: `Option<str>` is not an iterator
|
||||
--> $DIR/unsized-return-suggest-ref-issue-152064.rs:7:14
|
||||
|
|
||||
LL | for s in o.map(|s| s[3..8]) {}
|
||||
| ^^^^^^^^^^^^^^^^^^ `Option<str>` is not an iterator
|
||||
|
|
||||
= help: the trait `IntoIterator` is not implemented for `Option<str>`
|
||||
help: the following other types implement trait `IntoIterator`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
= note: `Option<T>`
|
||||
::: $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
= note: `&Option<T>`
|
||||
::: $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
= note: `&mut Option<T>`
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/unsized-return-suggest-ref-issue-152064.rs:15:18
|
||||
|
|
||||
LL | for s in arr.map(|s| s[3..8]) {}
|
||||
| ^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `[u8]`
|
||||
note: required by an implicit `Sized` bound in `Option::<T>::map`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/unsized-return-suggest-ref-issue-152064.rs:15:26
|
||||
|
|
||||
LL | for s in arr.map(|s| s[3..8]) {}
|
||||
| ^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `[u8]`
|
||||
= note: the return type of a function must have a statically known size
|
||||
|
||||
error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
|
||||
--> $DIR/unsized-return-suggest-ref-issue-152064.rs:15:14
|
||||
|
|
||||
LL | for s in arr.map(|s| s[3..8]) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `[u8]`
|
||||
note: required by an implicit `Sized` bound in `Option`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
help: consider borrowing the value
|
||||
|
|
||||
LL | for s in arr.map(|s| &s[3..8]) {}
|
||||
| +
|
||||
|
||||
error[E0277]: `Option<[u8]>` is not an iterator
|
||||
--> $DIR/unsized-return-suggest-ref-issue-152064.rs:15:14
|
||||
|
|
||||
LL | for s in arr.map(|s| s[3..8]) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^ `Option<[u8]>` is not an iterator
|
||||
|
|
||||
= help: the trait `IntoIterator` is not implemented for `Option<[u8]>`
|
||||
help: the following other types implement trait `IntoIterator`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
= note: `Option<T>`
|
||||
::: $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
= note: `&Option<T>`
|
||||
::: $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
= note: `&mut Option<T>`
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Reference in New Issue
Block a user