Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4796,7 +4796,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let hir::Node::Expr(rcvr) = self.tcx.hir_node(hir_id) else {
return false;
};
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, rcvr_ty.into_iter());
// The trait may have generic parameters beyond `Self` (e.g. `Borrow<Borrowed>`), and
// `rcvr_ty` may even be unknown. We only ever know the receiver type (the `Self` arg),
// so fill `Self` from `rcvr_ty` when available and the remaining parameters with fresh
// inference variables; building a `TraitRef` with a partial arg list would otherwise trip
// `debug_assert_args_compatible` and ICE. See #157189.
let trait_ref = ty::TraitRef::new_from_args(
self.tcx,
trait_def_id,
ty::GenericArgs::for_item(self.tcx, trait_def_id, |param, _| {
if param.index == 0
&& let Some(rcvr_ty) = rcvr_ty
{
rcvr_ty.into()
} else {
self.var_for_def(rcvr.span, param)
}
}),
);
let trait_pred = ty::Binder::dummy(ty::TraitPredicate {
trait_ref,
polarity: ty::PredicatePolarity::Positive,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//! Regression test for #157189.
//!
//! When a method call fails to resolve, the "trait which provides `<method>` is
//! implemented but not in scope" diagnostic probes all traits for a method of the
//! same name. Here `.borrow()` matches `std::borrow::Borrow::borrow`, and `Borrow`
//! has a generic parameter (`Borrowed`) besides `Self`. Building the trait
//! reference for the diagnostic used to pass only the receiver type as the single
//! argument, which mismatched the trait's generics and ICEd in
//! `debug_assert_args_compatible`. It should just report the error.

trait Foo {
extern "C" fn borrow(&self);
}

struct Bar;

fn main() {
let foo: Box<dyn Fn(bool) -> usize> = Box::new(Bar);
//~^ ERROR expected a `Fn(bool)` closure, found `Bar`
foo.borrow();
//~^ ERROR no method named `borrow` found
foo.take()
//~^ ERROR `Box<dyn Fn(bool) -> usize>` is not an iterator
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
error[E0599]: no method named `borrow` found for struct `Box<dyn Fn(bool) -> usize>` in the current scope
--> $DIR/method-suggestion-trait-with-extra-generics-no-ice.rs:20:9
|
LL | foo.borrow();
| ^^^^^^
|
--> $SRC_DIR/core/src/borrow.rs:LL:COL
|
= note: the method is available for `Box<dyn Fn(bool) -> usize>` here
|
= help: items from traits can only be used if the trait is in scope
help: use parentheses to call this trait object
|
LL | foo(/* bool */).borrow();
| ++++++++++++
help: trait `Borrow` which provides `borrow` is implemented but not in scope; perhaps you want to import it
|
LL + use std::borrow::Borrow;
|
help: there is a method `borrow_mut` with a similar name
|
LL | foo.borrow_mut();
| ++++

error[E0277]: expected a `Fn(bool)` closure, found `Bar`
--> $DIR/method-suggestion-trait-with-extra-generics-no-ice.rs:18:43
|
LL | let foo: Box<dyn Fn(bool) -> usize> = Box::new(Bar);
| ^^^^^^^^^^^^^ expected an `Fn(bool)` closure, found `Bar`
|
help: the trait `Fn(bool)` is not implemented for `Bar`
--> $DIR/method-suggestion-trait-with-extra-generics-no-ice.rs:15:1
|
LL | struct Bar;
| ^^^^^^^^^^
= note: required for the cast from `Box<Bar>` to `Box<dyn Fn(bool) -> usize>`

error[E0599]: `Box<dyn Fn(bool) -> usize>` is not an iterator
--> $DIR/method-suggestion-trait-with-extra-generics-no-ice.rs:22:9
|
LL | foo.take()
| ^^^^
| |
| this is an associated function, not a method
| `Box<dyn Fn(bool) -> usize>` is not an iterator
|
= note: found the following associated functions; to be used as methods, functions must have a `self` parameter
= note: the candidate is defined in an impl for the type `Box<T, A>`
= note: the following trait bounds were not satisfied:
`dyn Fn(bool) -> usize: Iterator`
which is required by `Box<dyn Fn(bool) -> usize>: Iterator`
`Box<dyn Fn(bool) -> usize>: Iterator`
which is required by `&mut Box<dyn Fn(bool) -> usize>: Iterator`
`dyn Fn(bool) -> usize: Iterator`
which is required by `&mut dyn Fn(bool) -> usize: Iterator`
help: use associated function syntax instead
|
LL - foo.take()
LL + Box::<dyn Fn(bool) -> usize>::take(foo)
|

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0277, E0599.
For more information about an error, try `rustc --explain E0277`.
Loading