@@ -275,10 +275,10 @@ impl<'tcx> TyCtxt<'tcx> {
275275 `.await`ing on both of them") ;
276276 }
277277 }
278- if let ( ty :: Infer ( ty :: IntVar ( _ ) ) , ty :: Float ( _ ) ) =
279- ( & values . found . sty , & values . expected . sty ) // Issue #53280
280- {
281- if let Ok ( snippet ) = self . sess . source_map ( ) . span_to_snippet ( sp) {
278+ match ( & values . expected . sty , & values . found . sty ) {
279+ ( ty :: Float ( _ ) , ty :: Infer ( ty :: IntVar ( _ ) ) ) => if let Ok ( // Issue #53280
280+ snippet ,
281+ ) = self . sess . source_map ( ) . span_to_snippet ( sp) {
282282 if snippet. chars ( ) . all ( |c| c. is_digit ( 10 ) || c == '-' || c == '_' ) {
283283 db. span_suggestion (
284284 sp,
@@ -287,8 +287,96 @@ impl<'tcx> TyCtxt<'tcx> {
287287 Applicability :: MachineApplicable
288288 ) ;
289289 }
290+ } ,
291+ ( ty:: Param ( _) , ty:: Param ( _) ) => {
292+ db. note ( "a type parameter was expected, but a different one was found; \
293+ you might be missing a type parameter or trait bound") ;
294+ db. note ( "for more information, visit \
295+ https://doc.rust-lang.org/book/ch10-02-traits.html\
296+ #traits-as-parameters") ;
297+ }
298+ ( ty:: Projection ( _) , ty:: Projection ( _) ) => {
299+ db. note ( "an associated type was expected, but a different one was found" ) ;
300+ }
301+ ( ty:: Param ( _) , ty:: Projection ( _) ) | ( ty:: Projection ( _) , ty:: Param ( _) ) => {
302+ db. note ( "you might be missing a type parameter or trait bound" ) ;
303+ }
304+ ( ty:: Param ( _) , _) | ( _, ty:: Param ( _) ) => {
305+ db. help ( "type parameters must be constrained to match other types" ) ;
306+ if self . sess . teach ( & db. get_code ( ) . unwrap ( ) ) {
307+ db. help ( "given a type parameter `T` and a method `foo`:
308+ ```
309+ trait Trait<T> { fn foo(&self) -> T; }
310+ ```
311+ the only ways to implement method `foo` are:
312+ - constrain `T` with an explicit type:
313+ ```
314+ impl Trait<String> for X {
315+ fn foo(&self) -> String { String::new() }
316+ }
317+ ```
318+ - add a trait bound to `T` and call a method on that trait that returns `Self`:
319+ ```
320+ impl<T: std::default::Default> Trait<T> for X {
321+ fn foo(&self) -> T { <T as std::default::Default>::default() }
322+ }
323+ ```
324+ - change `foo` to return an argument of type `T`:
325+ ```
326+ impl<T> Trait<T> for X {
327+ fn foo(&self, x: T) -> T { x }
328+ }
329+ ```" ) ;
330+ }
331+ db. note ( "for more information, visit \
332+ https://doc.rust-lang.org/book/ch10-02-traits.html\
333+ #traits-as-parameters") ;
334+ }
335+ ( ty:: Projection ( _) , _) => {
336+ db. note ( & format ! (
337+ "consider constraining the associated type `{}` to `{}` or calling a \
338+ method that returns `{}`",
339+ values. expected,
340+ values. found,
341+ values. expected,
342+ ) ) ;
343+ if self . sess . teach ( & db. get_code ( ) . unwrap ( ) ) {
344+ db. help ( "given an associated type `T` and a method `foo`:
345+ ```
346+ trait Trait {
347+ type T;
348+ fn foo(&self) -> Self::T;
349+ }
350+ ```
351+ the only way of implementing method `foo` is to constrain `T` with an explicit associated type:
352+ ```
353+ impl Trait for X {
354+ type T = String;
355+ fn foo(&self) -> Self::T { String::new() }
356+ }
357+ ```" ) ;
358+ }
359+ db. note ( "for more information, visit \
360+ https://doc.rust-lang.org/book/ch19-03-advanced-traits.html") ;
361+ }
362+ ( _, ty:: Projection ( _) ) => {
363+ db. note ( & format ! (
364+ "consider constraining the associated type `{}` to `{}`" ,
365+ values. found,
366+ values. expected,
367+ ) ) ;
368+ db. note ( "for more information, visit \
369+ https://doc.rust-lang.org/book/ch19-03-advanced-traits.html") ;
290370 }
371+ _ => { }
291372 }
373+ debug ! (
374+ "note_and_explain_type_err expected={:?} ({:?}) found={:?} ({:?})" ,
375+ values. expected,
376+ values. expected. sty,
377+ values. found,
378+ values. found. sty,
379+ ) ;
292380 } ,
293381 CyclicTy ( ty) => {
294382 // Watch out for various cases of cyclic types and try to explain.
0 commit comments