mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-22 11:53:44 +00:00
Suggest Box::new
when appropriate
When encountering a boxed value as expected and a stack allocated value that could be boxed to fulfill the expectation, like in the following snippet, suggest `Box::new` wrapping.
This commit is contained in:
parent
1e6f753762
commit
fb2511c3c5
@ -650,11 +650,31 @@ impl<'hir> Map<'hir> {
|
||||
}
|
||||
|
||||
pub fn is_const_scope(&self, hir_id: HirId) -> bool {
|
||||
self.walk_parent_nodes(hir_id, |node| match *node {
|
||||
Node::Item(Item { node: ItemKind::Const(_, _), .. }) => true,
|
||||
Node::Item(Item { node: ItemKind::Fn(_, header, _, _), .. }) => header.is_const(),
|
||||
let parent_id = self.get_parent_item(hir_id);
|
||||
match self.get(parent_id) {
|
||||
Node::Item(&Item {
|
||||
node: ItemKind::Const(..),
|
||||
..
|
||||
})
|
||||
| Node::TraitItem(&TraitItem {
|
||||
node: TraitItemKind::Const(..),
|
||||
..
|
||||
})
|
||||
| Node::ImplItem(&ImplItem {
|
||||
node: ImplItemKind::Const(..),
|
||||
..
|
||||
})
|
||||
| Node::AnonConst(_)
|
||||
| Node::Item(&Item {
|
||||
node: ItemKind::Static(..),
|
||||
..
|
||||
}) => true,
|
||||
Node::Item(&Item {
|
||||
node: ItemKind::Fn(_, header, ..),
|
||||
..
|
||||
}) => header.constness == Constness::Const,
|
||||
_ => false,
|
||||
}, |_| false).map(|id| id != CRATE_HIR_ID).unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// If there is some error when walking the parents (e.g., a node does not
|
||||
|
@ -127,6 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
self.suggest_compatible_variants(&mut err, expr, expected, expr_ty);
|
||||
self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
|
||||
self.suggest_boxing_when_appropriate(&mut err, expr, expected, expr_ty);
|
||||
self.suggest_missing_await(&mut err, expr, expected, expr_ty);
|
||||
|
||||
(expected, Some(err))
|
||||
|
@ -3820,6 +3820,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
err, &fn_decl, expected, found, can_suggest);
|
||||
}
|
||||
self.suggest_ref_or_into(err, expression, expected, found);
|
||||
self.suggest_boxing_when_appropriate(err, expression, expected, found);
|
||||
pointing_at_return_type
|
||||
}
|
||||
|
||||
@ -3980,6 +3981,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// When encountering the expected boxed value allocated in the stack, suggest allocating it
|
||||
/// in the heap by calling `Box::new()`.
|
||||
fn suggest_boxing_when_appropriate(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'tcx>,
|
||||
expr: &hir::Expr,
|
||||
expected: Ty<'tcx>,
|
||||
found: Ty<'tcx>,
|
||||
) {
|
||||
if self.tcx.hir().is_const_scope(expr.hir_id) {
|
||||
// Do not suggest `Box::new` in const context.
|
||||
return;
|
||||
}
|
||||
if expected.is_box() && !found.is_box() {
|
||||
let boxed_found = self.tcx.mk_box(found);
|
||||
if let (true, Ok(snippet)) = (
|
||||
self.can_coerce(boxed_found, expected),
|
||||
self.sess().source_map().span_to_snippet(expr.span),
|
||||
) {
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
"you can store this in the heap calling `Box::new`",
|
||||
format!("Box::new({})", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.note("for more information about the distinction between the stack and the \
|
||||
heap, read https://doc.rust-lang.org/book/ch15-01-box.html, \
|
||||
https://doc.rust-lang.org/rust-by-example/std/box.html and \
|
||||
https://doc.rust-lang.org/std/boxed/index.html");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A common error is to forget to add a semicolon at the end of a block, e.g.,
|
||||
///
|
||||
/// ```
|
||||
|
8
src/test/ui/suggestions/suggest-box.fixed
Normal file
8
src/test/ui/suggestions/suggest-box.fixed
Normal file
@ -0,0 +1,8 @@
|
||||
// run-rustfix
|
||||
|
||||
fn main() {
|
||||
let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| { //~ ERROR mismatched types
|
||||
Err(())?;
|
||||
Ok(())
|
||||
});
|
||||
}
|
8
src/test/ui/suggestions/suggest-box.rs
Normal file
8
src/test/ui/suggestions/suggest-box.rs
Normal file
@ -0,0 +1,8 @@
|
||||
// run-rustfix
|
||||
|
||||
fn main() {
|
||||
let _x: Box<dyn Fn() -> Result<(), ()>> = || { //~ ERROR mismatched types
|
||||
Err(())?;
|
||||
Ok(())
|
||||
};
|
||||
}
|
24
src/test/ui/suggestions/suggest-box.stderr
Normal file
24
src/test/ui/suggestions/suggest-box.stderr
Normal file
@ -0,0 +1,24 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/suggest-box.rs:4:47
|
||||
|
|
||||
LL | let _x: Box<dyn Fn() -> Result<(), ()>> = || {
|
||||
| _______________________________________________^
|
||||
LL | | Err(())?;
|
||||
LL | | Ok(())
|
||||
LL | | };
|
||||
| |_____^ expected struct `std::boxed::Box`, found closure
|
||||
|
|
||||
= note: expected type `std::boxed::Box<dyn std::ops::Fn() -> std::result::Result<(), ()>>`
|
||||
found type `[closure@$DIR/suggest-box.rs:4:47: 7:6]`
|
||||
= note: for more information about the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html and https://doc.rust-lang.org/std/boxed/index.html
|
||||
help: you can store this in the heap calling `Box::new`
|
||||
|
|
||||
LL | let _x: Box<dyn Fn() -> Result<(), ()>> = Box::new(|| {
|
||||
LL | Err(())?;
|
||||
LL | Ok(())
|
||||
LL | });
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user