Skip to content

Commit

Permalink
Auto merge of rust-lang#126581 - GuillaumeGomez:rollup-dx4fadn, r=Gui…
Browse files Browse the repository at this point in the history
…llaumeGomez

Rollup of 3 pull requests

Successful merges:

 - rust-lang#126226 (Make suggestion to change `Fn` to `FnMut` work with methods as well)
 - rust-lang#126570 (Convert a `span_bug` to a `span_delayed_bug`.)
 - rust-lang#126580 (Add `run-make/const_fn_mir` missing test annotation)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jun 17, 2024
2 parents e23ae72 + 9092ffb commit 3baa20b
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 57 deletions.
113 changes: 69 additions & 44 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -937,56 +937,81 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let node = self.infcx.tcx.hir_node(fn_call_id);
let def_id = hir.enclosing_body_owner(fn_call_id);
let mut look_at_return = true;
// If we can detect the expression to be an `fn` call where the closure was an argument,
// we point at the `fn` definition argument...
if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Call(func, args), .. }) = node {
let arg_pos = args

// If the HIR node is a function or method call gets the def ID
// of the called function or method and the span and args of the call expr
let get_call_details = || {
let hir::Node::Expr(hir::Expr { hir_id, kind, .. }) = node else {
return None;
};

let typeck_results = self.infcx.tcx.typeck(def_id);

match kind {
hir::ExprKind::Call(expr, args) => {
if let Some(ty::FnDef(def_id, _)) =
typeck_results.node_type_opt(expr.hir_id).as_ref().map(|ty| ty.kind())
{
Some((*def_id, expr.span, *args))
} else {
None
}
}
hir::ExprKind::MethodCall(_, _, args, span) => {
if let Some(def_id) = typeck_results.type_dependent_def_id(*hir_id) {
Some((def_id, *span, *args))
} else {
None
}
}
_ => None,
}
};

// If we can detect the expression to be an function or method call where the closure was an argument,
// we point at the function or method definition argument...
if let Some((callee_def_id, call_span, call_args)) = get_call_details() {
let arg_pos = call_args
.iter()
.enumerate()
.filter(|(_, arg)| arg.hir_id == closure_id)
.map(|(pos, _)| pos)
.next();
let tables = self.infcx.tcx.typeck(def_id);
if let Some(ty::FnDef(def_id, _)) =
tables.node_type_opt(func.hir_id).as_ref().map(|ty| ty.kind())
{
let arg = match hir.get_if_local(*def_id) {
Some(
hir::Node::Item(hir::Item {
ident, kind: hir::ItemKind::Fn(sig, ..), ..
})
| hir::Node::TraitItem(hir::TraitItem {
ident,
kind: hir::TraitItemKind::Fn(sig, _),
..

let arg = match hir.get_if_local(callee_def_id) {
Some(
hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. })
| hir::Node::TraitItem(hir::TraitItem {
ident,
kind: hir::TraitItemKind::Fn(sig, _),
..
})
| hir::Node::ImplItem(hir::ImplItem {
ident,
kind: hir::ImplItemKind::Fn(sig, _),
..
}),
) => Some(
arg_pos
.and_then(|pos| {
sig.decl.inputs.get(
pos + if sig.decl.implicit_self.has_implicit_self() {
1
} else {
0
},
)
})
| hir::Node::ImplItem(hir::ImplItem {
ident,
kind: hir::ImplItemKind::Fn(sig, _),
..
}),
) => Some(
arg_pos
.and_then(|pos| {
sig.decl.inputs.get(
pos + if sig.decl.implicit_self.has_implicit_self() {
1
} else {
0
},
)
})
.map(|arg| arg.span)
.unwrap_or(ident.span),
),
_ => None,
};
if let Some(span) = arg {
err.span_label(span, "change this to accept `FnMut` instead of `Fn`");
err.span_label(func.span, "expects `Fn` instead of `FnMut`");
err.span_label(closure_span, "in this closure");
look_at_return = false;
}
.map(|arg| arg.span)
.unwrap_or(ident.span),
),
_ => None,
};
if let Some(span) = arg {
err.span_label(span, "change this to accept `FnMut` instead of `Fn`");
err.span_label(call_span, "expects `Fn` instead of `FnMut`");
err.span_label(closure_span, "in this closure");
look_at_return = false;
}
}

Expand Down
4 changes: 1 addition & 3 deletions compiler/rustc_borrowck/src/diagnostics/region_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -628,9 +628,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
| GenericArgKind::Const(_),
_,
) => {
// This was previously a `span_delayed_bug` and could be
// reached by the test for #82126, but no longer.
self.dcx().span_bug(
self.dcx().span_delayed_bug(
hir_arg.span(),
format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"),
);
Expand Down
10 changes: 0 additions & 10 deletions tests/crashes/126385.rs

This file was deleted.

2 changes: 2 additions & 0 deletions tests/run-make/const_fn_mir/rmake.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// The `needs-unwind -Cpanic=abort` gives a different MIR output.

//@ needs-unwind

use run_make_support::{cwd, diff, rustc};

fn main() {
Expand Down
14 changes: 14 additions & 0 deletions tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// This test was triggering a `span_bug` crash, which was then fixed by
// downgrading it to a `span_delayed_bug`.

pub struct MyStruct<'field> {
field: &'field [u32],
}

impl MyStruct<'_> {
pub fn f(field: &[u32]) -> Self<u32> { //~ ERROR type arguments are not allowed on self type
Self { field } //~ ERROR lifetime may not live long enough
}
}

fn main() {}
34 changes: 34 additions & 0 deletions tests/ui/borrowck/unmatched-arg-and-hir-arg-issue-126385.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
error[E0109]: type arguments are not allowed on self type
--> $DIR/unmatched-arg-and-hir-arg-issue-126385.rs:9:37
|
LL | pub fn f(field: &[u32]) -> Self<u32> {
| ---- ^^^ type argument not allowed
| |
| not allowed on self type
|
note: `Self` is of type `MyStruct<'_>`
--> $DIR/unmatched-arg-and-hir-arg-issue-126385.rs:4:12
|
LL | pub struct MyStruct<'field> {
| ^^^^^^^^ `Self` corresponds to this type
...
LL | impl MyStruct<'_> {
| ----------------- `Self` is on type `MyStruct` in this `impl`
help: the `Self` type doesn't accept type parameters, use the concrete type's name `MyStruct` instead if you want to specify its type parameters
|
LL | pub fn f(field: &[u32]) -> MyStruct<u32> {
| ~~~~~~~~

error: lifetime may not live long enough
--> $DIR/unmatched-arg-and-hir-arg-issue-126385.rs:10:9
|
LL | pub fn f(field: &[u32]) -> Self<u32> {
| - --------- return type is MyStruct<'2>
| |
| let's call the lifetime of this reference `'1`
LL | Self { field }
| ^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0109`.
29 changes: 29 additions & 0 deletions tests/ui/closures/wrong-closure-arg-suggestion-125325.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Regression test for #125325

// Tests that we suggest changing an `impl Fn` param
// to `impl FnMut` when the provided closure arg
// is trying to mutate the closure env.
// Ensures that it works that way for both
// functions and methods

struct S;

impl S {
fn assoc_func(&self, _f: impl Fn()) -> usize {
0
}
}

fn func(_f: impl Fn()) -> usize {
0
}

fn test_func(s: &S) -> usize {
let mut x = ();
s.assoc_func(|| x = ());
//~^ cannot assign to `x`, as it is a captured variable in a `Fn` closure
func(|| x = ())
//~^ cannot assign to `x`, as it is a captured variable in a `Fn` closure
}

fn main() {}
28 changes: 28 additions & 0 deletions tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
--> $DIR/wrong-closure-arg-suggestion-125325.rs:23:21
|
LL | fn assoc_func(&self, _f: impl Fn()) -> usize {
| --------- change this to accept `FnMut` instead of `Fn`
...
LL | s.assoc_func(|| x = ());
| --------------^^^^^^-
| | | |
| | | cannot assign
| | in this closure
| expects `Fn` instead of `FnMut`

error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure
--> $DIR/wrong-closure-arg-suggestion-125325.rs:25:13
|
LL | fn func(_f: impl Fn()) -> usize {
| --------- change this to accept `FnMut` instead of `Fn`
...
LL | func(|| x = ())
| ---- -- ^^^^^^ cannot assign
| | |
| | in this closure
| expects `Fn` instead of `FnMut`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0594`.

0 comments on commit 3baa20b

Please sign in to comment.