Skip to content

Commit

Permalink
Use root obligation on E0277 for some cases
Browse files Browse the repository at this point in the history
When encountering trait bound errors that satisfy some heuristics that
tell us that the relevant trait for the user comes from the root
obligation and not the current obligation, we use the root predicate for
the main message.

This allows to talk about "X doesn't implement Pattern<'_>" over the
most specific case that just happened to fail, like  "char doesn't
implement Fn(&mut char)" in
`tests/ui/traits/suggest-dereferences/root-obligation.rs`

The heuristics are:

 - the type of the leaf predicate is (roughly) the same as the type
   from the root predicate, as a proxy for "we care about the root"
 - the leaf trait and the root trait are different, so as to avoid
   talking about `&mut T: Trait` and instead remain talking about
   `T: Trait` instead
 - the root trait is not `Unsize`, as to avoid talking about it in
   `tests/ui/coercion/coerce-issue-49593-box-never.rs`.

```
error[E0277]: the trait bound `&char: Pattern<'_>` is not satisfied
  --> $DIR/root-obligation.rs:6:38
   |
LL |         .filter(|c| "aeiou".contains(c))
   |                             -------- ^ the trait `Fn<(char,)>` is not implemented for `&char`, which is required by `&char: Pattern<'_>`
   |                             |
   |                             required by a bound introduced by this call
   |
   = note: required for `&char` to implement `FnOnce<(char,)>`
   = note: required for `&char` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::contains`
  --> $SRC_DIR/core/src/str/mod.rs:LL:COL
help: consider dereferencing here
   |
LL |         .filter(|c| "aeiou".contains(*c))
   |                                      +
```

Fix rust-lang#79359, fix rust-lang#119983, fix rust-lang#118779, cc rust-lang#118415 (the suggestion needs
to change).
  • Loading branch information
estebank committed Mar 1, 2024
1 parent c475e23 commit 596b391
Show file tree
Hide file tree
Showing 38 changed files with 156 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -409,9 +409,44 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_predicate)) => {
let trait_predicate = bound_predicate.rebind(trait_predicate);
let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
let trait_ref = trait_predicate.to_poly_trait_ref();
let (main_trait_predicate, o) = if let ty::PredicateKind::Clause(
ty::ClauseKind::Trait(root_pred)
) = root_obligation.predicate.kind().skip_binder()
&& trait_predicate.self_ty().skip_binder()
== root_pred.self_ty().peel_refs()
&& trait_predicate.def_id() != root_pred.def_id()
&& Some(root_pred.def_id()) != self.tcx.lang_items().unsize_trait()
{
// Let's use the root obligation as the main message, as we care about
// the most general case ("X doesn't implement Pattern<'_>") over the
// most specific case that happened to fail ("char doesn't implement
// Fn(&mut char)").
//
// We rely on a few heuristics to identify cases where this root
// obligation is more important than the leaf obligation:
//
// - the type of the leaf predicate is (roughly) the same as the type
// from the root predicate, as a proxy for "we care about the root"
// - the leaf trait and the root trait are different, so as to avoid
// talking about `&mut T: Trait` and instead remain talking about
// `T: Trait` instead
// - the root trait is not `Unsize`, as to avoid talking about it in
// `tests/ui/coercion/coerce-issue-49593-box-never.rs`.
(
self.resolve_vars_if_possible(
root_obligation.predicate.kind().rebind(root_pred),
),
root_obligation,
)
} else {
(trait_predicate, &obligation)
};
let trait_ref = main_trait_predicate.to_poly_trait_ref();

if let Some(guar) = self.emit_specialized_closure_kind_error(&obligation, trait_ref) {
if let Some(guar) = self.emit_specialized_closure_kind_error(
&obligation,
trait_ref,
) {
return guar;
}

Expand Down Expand Up @@ -450,7 +485,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
notes,
parent_label,
append_const_msg,
} = self.on_unimplemented_note(trait_ref, &obligation);
} = self.on_unimplemented_note(trait_ref, o);
let have_alt_message = message.is_some() || label.is_some();
let is_try_conversion = self.is_try_conversion(span, trait_ref.def_id());
let is_unsize =
Expand All @@ -473,7 +508,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
};

let err_msg = self.get_standard_error_message(
&trait_predicate,
&main_trait_predicate,
message,
predicate_is_const,
append_const_msg,
Expand Down
5 changes: 5 additions & 0 deletions library/core/src/future/into_future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ use crate::future::Future;
/// ```
#[stable(feature = "into_future", since = "1.64.0")]
#[rustc_diagnostic_item = "IntoFuture"]
#[diagnostic::on_unimplemented(
label = "`{Self}` is not a future",
message = "`{Self}` is not a future",
note = "{Self} must be a future or must implement `IntoFuture` to be awaited"
)]
pub trait IntoFuture {
/// The output that the future will produce on completion.
#[stable(feature = "into_future", since = "1.64.0")]
Expand Down
43 changes: 43 additions & 0 deletions library/core/src/iter/traits/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,49 @@ pub trait FromIterator<A>: Sized {
/// ```
#[rustc_diagnostic_item = "IntoIterator"]
#[rustc_skip_array_during_method_dispatch]
#[rustc_on_unimplemented(
on(
_Self = "core::ops::range::RangeTo<Idx>",
label = "if you meant to iterate until a value, add a starting value",
note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
bounded `Range`: `0..end`"
),
on(
_Self = "core::ops::range::RangeToInclusive<Idx>",
label = "if you meant to iterate until a value (including it), add a starting value",
note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
to have a bounded `RangeInclusive`: `0..=end`"
),
on(
_Self = "[]",
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
),
on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
on(
_Self = "alloc::vec::Vec<T, A>",
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
),
on(
_Self = "&str",
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
on(
_Self = "alloc::string::String",
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
on(
_Self = "{integral}",
note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
syntax `start..end` or the inclusive range syntax `start..=end`"
),
on(
_Self = "{float}",
note = "if you want to iterate between `start` until a value `end`, use the exclusive range \
syntax `start..end` or the inclusive range syntax `start..=end`"
),
label = "`{Self}` is not an iterator",
message = "`{Self}` is not an iterator"
)]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait IntoIterator {
/// The type of the elements being iterated over.
Expand Down
5 changes: 2 additions & 3 deletions tests/ui/associated-types/substs-ppaux.normal.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,12 @@ help: use parentheses to call this function
LL | let x: () = foo::<'static>();
| ++

error[E0277]: the size for values of type `str` cannot be known at compilation time
error[E0277]: the trait bound `str: Foo<'_, '_, u8>` is not satisfied
--> $DIR/substs-ppaux.rs:49:6
|
LL | <str as Foo<u8>>::bar;
| ^^^ doesn't have a size known at compile-time
| ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>`
|
= help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'_, '_, u8>`
note: required for `str` to implement `Foo<'_, '_, u8>`
--> $DIR/substs-ppaux.rs:11:17
|
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-types/substs-ppaux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,6 @@ fn foo<'z>() where &'z (): Sized {
//[normal]~| found fn item `fn() {foo::<'static>}`

<str as Foo<u8>>::bar;
//[verbose]~^ ERROR the size for values of type
//[normal]~^^ ERROR the size for values of type
//[verbose]~^ ERROR the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied
//[normal]~^^ ERROR the trait bound `str: Foo<'_, '_, u8>` is not satisfied
}
5 changes: 2 additions & 3 deletions tests/ui/associated-types/substs-ppaux.verbose.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,12 @@ help: use parentheses to call this function
LL | let x: () = foo::<'static>();
| ++

error[E0277]: the size for values of type `str` cannot be known at compilation time
error[E0277]: the trait bound `str: Foo<'?0, '?1, u8>` is not satisfied
--> $DIR/substs-ppaux.rs:49:6
|
LL | <str as Foo<u8>>::bar;
| ^^^ doesn't have a size known at compile-time
| ^^^ the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>`
|
= help: the trait `Sized` is not implemented for `str`, which is required by `str: Foo<'?0, '?1, u8>`
note: required for `str` to implement `Foo<'?0, '?1, u8>`
--> $DIR/substs-ppaux.rs:11:17
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ impl Signed for i32 { }
fn main() {
is_defaulted::<&'static i32>();
is_defaulted::<&'static u32>();
//~^ ERROR `u32: Signed` is not satisfied
//~^ ERROR the trait bound `&'static u32: Defaulted` is not satisfied
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `u32: Signed` is not satisfied
error[E0277]: the trait bound `&'static u32: Defaulted` is not satisfied
--> $DIR/typeck-default-trait-impl-precedence.rs:19:20
|
LL | is_defaulted::<&'static u32>();
| ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`, which is required by `&'static u32: Defaulted`
| ^^^^^^^^^^^^ the trait `Signed` is not implemented for `&'static u32`, which is required by `&'static u32: Defaulted`
|
note: required for `&'static u32` to implement `Defaulted`
--> $DIR/typeck-default-trait-impl-precedence.rs:10:19
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/for/issue-20605.current.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0277]: the size for values of type `dyn Iterator<Item = &'a mut u8>` cannot be known at compilation time
error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
--> $DIR/issue-20605.rs:5:17
|
LL | for item in *things { *item = 0 }
Expand Down
6 changes: 4 additions & 2 deletions tests/ui/for/issue-20605.next.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
error[E0277]: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
--> $DIR/issue-20605.rs:5:17
|
LL | for item in *things { *item = 0 }
| ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
| ^^^^^^^ `dyn Iterator<Item = &'a mut u8>` is not an iterator
|
= help: the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`

error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
--> $DIR/issue-20605.rs:5:17
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/for/issue-20605.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
for item in *things { *item = 0 }
//[current]~^ ERROR the size for values of type
//[next]~^^ ERROR the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
//[current]~^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
//[next]~^^ ERROR `dyn Iterator<Item = &'a mut u8>` is not an iterator
//[next]~| ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
//[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
//[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/kindck/kindck-impl-type-params-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ fn take_param<T:Foo>(foo: &T) { }
fn main() {
let x: Box<_> = Box::new(3);
take_param(&x);
//~^ ERROR the trait bound `Box<{integer}>: Copy` is not satisfied
//~^ ERROR the trait bound `Box<{integer}>: Foo` is not satisfied
}
2 changes: 1 addition & 1 deletion tests/ui/kindck/kindck-impl-type-params-2.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
--> $DIR/kindck-impl-type-params-2.rs:13:16
|
LL | take_param(&x);
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/kindck/kindck-inherited-copy-bound.curr.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
--> $DIR/kindck-inherited-copy-bound.rs:21:16
|
LL | take_param(&x);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
--> $DIR/kindck-inherited-copy-bound.rs:21:16
|
LL | take_param(&x);
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/kindck/kindck-send-object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ trait Message : Send { }

fn object_ref_with_static_bound_not_ok() {
assert_send::<&'static (dyn Dummy + 'static)>();
//~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
//~^ ERROR `&'static (dyn Dummy + 'static)` cannot be sent between threads safely [E0277]
}

fn box_object_with_no_bound_not_ok<'a>() {
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/kindck/kindck-send-object.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
--> $DIR/kindck-send-object.rs:12:19
|
LL | assert_send::<&'static (dyn Dummy + 'static)>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
|
= help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
= help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
= note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
note: required by a bound in `assert_send`
--> $DIR/kindck-send-object.rs:5:18
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/kindck/kindck-send-object1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ trait Dummy { }
// careful with object types, who knows what they close over...
fn test51<'a>() {
assert_send::<&'a dyn Dummy>();
//~^ ERROR `(dyn Dummy + 'a)` cannot be shared between threads safely [E0277]
//~^ ERROR `&'a (dyn Dummy + 'a)` cannot be sent between threads safely [E0277]
}
fn test52<'a>() {
assert_send::<&'a (dyn Dummy + Sync)>();
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/kindck/kindck-send-object1.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely
error[E0277]: `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
--> $DIR/kindck-send-object1.rs:10:19
|
LL | assert_send::<&'a dyn Dummy>();
| ^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
| ^^^^^^^^^^^^^ `&'a (dyn Dummy + 'a)` cannot be sent between threads safely
|
= help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
= help: the trait `Sync` is not implemented for `&'a (dyn Dummy + 'a)`, which is required by `&'a (dyn Dummy + 'a): Send`
= note: required for `&'a (dyn Dummy + 'a)` to implement `Send`
note: required by a bound in `assert_send`
--> $DIR/kindck-send-object1.rs:5:18
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/kindck/kindck-send-object2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ trait Dummy { }

fn test50() {
assert_send::<&'static dyn Dummy>();
//~^ ERROR `(dyn Dummy + 'static)` cannot be shared between threads safely [E0277]
//~^ ERROR `&'static (dyn Dummy + 'static)` cannot be sent between threads safely [E0277]
}

fn test53() {
Expand Down
6 changes: 3 additions & 3 deletions tests/ui/kindck/kindck-send-object2.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
error[E0277]: `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
--> $DIR/kindck-send-object2.rs:7:19
|
LL | assert_send::<&'static dyn Dummy>();
| ^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
| ^^^^^^^^^^^^^^^^^^ `&'static (dyn Dummy + 'static)` cannot be sent between threads safely
|
= help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
= help: the trait `Sync` is not implemented for `&'static (dyn Dummy + 'static)`, which is required by `&'static (dyn Dummy + 'static): Send`
= note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
note: required by a bound in `assert_send`
--> $DIR/kindck-send-object2.rs:3:18
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ fn stuff<T: Bar>(_: T) {}

fn main() {
stuff(1u8);
//~^ the trait bound `u8: Foo` is not satisfied
//~^ the trait bound `u8: Bar` is not satisfied
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0277]: the trait bound `u8: Foo` is not satisfied
error[E0277]: the trait bound `u8: Bar` is not satisfied
--> $DIR/feature-gate-do_not_recommend.rs:19:11
|
LL | stuff(1u8);
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/suggestions/issue-104961.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

fn foo(x: &str) -> bool {
x.starts_with(&("hi".to_string() + " you"))
//~^ ERROR expected a `FnMut(char)` closure, found `String`
//~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
}

fn foo2(x: &str) -> bool {
x.starts_with(&"hi".to_string())
//~^ ERROR expected a `FnMut(char)` closure, found `String`
//~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
}

fn main() {
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/suggestions/issue-104961.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

fn foo(x: &str) -> bool {
x.starts_with("hi".to_string() + " you")
//~^ ERROR expected a `FnMut(char)` closure, found `String`
//~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
}

fn foo2(x: &str) -> bool {
x.starts_with("hi".to_string())
//~^ ERROR expected a `FnMut(char)` closure, found `String`
//~^ ERROR the trait bound `String: Pattern<'_>` is not satisfied [E0277]
}

fn main() {
Expand Down
6 changes: 2 additions & 4 deletions tests/ui/suggestions/issue-104961.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
error[E0277]: expected a `FnMut(char)` closure, found `String`
error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied
--> $DIR/issue-104961.rs:4:19
|
LL | x.starts_with("hi".to_string() + " you")
| ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
| |
| required by a bound introduced by this call
|
= note: the trait bound `String: Pattern<'_>` is not satisfied
= note: required for `String` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::starts_with`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
Expand All @@ -15,15 +14,14 @@ help: consider borrowing here
LL | x.starts_with(&("hi".to_string() + " you"))
| ++ +

error[E0277]: expected a `FnMut(char)` closure, found `String`
error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied
--> $DIR/issue-104961.rs:9:19
|
LL | x.starts_with("hi".to_string())
| ----------- ^^^^^^^^^^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
| |
| required by a bound introduced by this call
|
= note: the trait bound `String: Pattern<'_>` is not satisfied
= note: required for `String` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::starts_with`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/suggestions/issue-62843.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
error[E0277]: expected a `FnMut(char)` closure, found `String`
error[E0277]: the trait bound `String: Pattern<'_>` is not satisfied
--> $DIR/issue-62843.rs:4:32
|
LL | println!("{:?}", line.find(pattern));
| ---- ^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
| |
| required by a bound introduced by this call
|
= note: the trait bound `String: Pattern<'_>` is not satisfied
= note: required for `String` to implement `Pattern<'_>`
note: required by a bound in `core::str::<impl str>::find`
--> $SRC_DIR/core/src/str/mod.rs:LL:COL
Expand Down
Loading

0 comments on commit 596b391

Please sign in to comment.