@@ -814,6 +814,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
814814 }
815815 }
816816
817+ /// On missing type parameters, emit an E0393 error and provide a structured suggestion using
818+ /// the type parameter's name as a placeholder.
817819 fn complain_about_missing_type_params (
818820 & self ,
819821 missing_type_params : Vec < String > ,
@@ -1010,15 +1012,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10101012 ty:: TraitRef :: new ( trait_def_id, substs)
10111013 }
10121014
1013- fn create_substs_for_ast_trait_ref < ' a > (
1015+ /// When the code is using the `Fn` traits directly, instead of the `Fn(A) -> B` syntax, emit
1016+ /// an error and attempt to build a reasonable structured suggestion.
1017+ fn complain_about_internal_fn_trait (
10141018 & self ,
10151019 span : Span ,
10161020 trait_def_id : DefId ,
1017- self_ty : Ty < ' tcx > ,
10181021 trait_segment : & ' a hir:: PathSegment ,
1019- ) -> ( SubstsRef < ' tcx > , Vec < ConvertedBinding < ' a , ' tcx > > , Option < Vec < Span > > ) {
1020- debug ! ( "create_substs_for_ast_trait_ref(trait_segment={:?})" , trait_segment) ;
1021-
1022+ ) {
10221023 let trait_def = self . tcx ( ) . trait_def ( trait_def_id) ;
10231024
10241025 if !self . tcx ( ) . features ( ) . unboxed_closures
@@ -1068,6 +1069,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10681069 }
10691070 err. emit ( ) ;
10701071 }
1072+ }
1073+
1074+ fn create_substs_for_ast_trait_ref < ' a > (
1075+ & self ,
1076+ span : Span ,
1077+ trait_def_id : DefId ,
1078+ self_ty : Ty < ' tcx > ,
1079+ trait_segment : & ' a hir:: PathSegment ,
1080+ ) -> ( SubstsRef < ' tcx > , Vec < ConvertedBinding < ' a , ' tcx > > , Option < Vec < Span > > ) {
1081+ debug ! ( "create_substs_for_ast_trait_ref(trait_segment={:?})" , trait_segment) ;
1082+
1083+ self . complain_about_internal_fn_trait ( span, trait_def_id, trait_segment) ;
10711084
10721085 self . create_substs_for_ast_path (
10731086 span,
@@ -1452,8 +1465,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14521465 . filter ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) ) ;
14531466
14541467 for ( base_trait_ref, span) in regular_traits_refs_spans {
1455- debug ! ( "conv_object_ty_poly_trait_ref regular_trait_ref `{:?}`" , base_trait_ref) ;
1456- let mut new_bounds = vec ! [ ] ;
14571468 for trait_ref in traits:: elaborate_trait_ref ( tcx, base_trait_ref) {
14581469 debug ! (
14591470 "conv_object_ty_poly_trait_ref: observing object predicate `{:?}`" ,
@@ -1486,17 +1497,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14861497 // but actually supporting that would "expand" to an infinitely-long type
14871498 // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
14881499 //
1489- // Instead, we force the user to write `dyn MyTrait<MyOutput = X, Output = X>`,
1490- // which is uglier but works. See the discussion in #56288 for alternatives.
1500+ // Instead, we force the user to write
1501+ // `dyn MyTrait<MyOutput = X, Output = X>`, which is uglier but works. See
1502+ // the discussion in #56288 for alternatives.
14911503 if !references_self {
14921504 // Include projections defined on supertraits.
1493- new_bounds . push ( ( pred, span) ) ;
1505+ bounds . projection_bounds . push ( ( pred, span) ) ;
14941506 }
14951507 }
14961508 _ => ( ) ,
14971509 }
14981510 }
1499- bounds. projection_bounds . extend ( new_bounds) ;
15001511 }
15011512
15021513 for ( projection_bound, _) in & bounds. projection_bounds {
@@ -1598,27 +1609,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15981609 ty
15991610 }
16001611
1612+ /// When there are any missing associated types, emit an E0191 error and attempt to supply a
1613+ /// reasonable suggestion on how to write it. For the case of multiple associated types in the
1614+ /// same trait bound have the same name (as they come from different super-traits), we instead
1615+ /// emit a generic note suggesting using a `where` clause to constraint instead.
16011616 fn complain_about_missing_associated_types (
16021617 & self ,
1603- mut associated_types : FxHashMap < Span , BTreeSet < DefId > > ,
1618+ associated_types : FxHashMap < Span , BTreeSet < DefId > > ,
16041619 potential_assoc_types : Vec < Span > ,
16051620 trait_bounds : & [ hir:: PolyTraitRef ] ,
16061621 ) {
16071622 if !associated_types. values ( ) . any ( |v| v. len ( ) > 0 ) {
16081623 return ;
16091624 }
16101625 let tcx = self . tcx ( ) ;
1626+ // FIXME: Marked `mut` so that we can replace the spans further below with a more
1627+ // appropriate one, but this should be handled earlier in the span assignment.
1628+ let mut associated_types: FxHashMap < Span , Vec < _ > > = associated_types
1629+ . into_iter ( )
1630+ . map ( |( span, def_ids) | {
1631+ ( span, def_ids. into_iter ( ) . map ( |did| tcx. associated_item ( did) ) . collect ( ) )
1632+ } )
1633+ . collect ( ) ;
16111634 let mut names = vec ! [ ] ;
16121635
16131636 // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
16141637 // `issue-22560.rs`.
16151638 let mut trait_bound_spans: Vec < Span > = vec ! [ ] ;
1616- for ( span, item_def_ids ) in & associated_types {
1617- if !item_def_ids . is_empty ( ) {
1639+ for ( span, items ) in & associated_types {
1640+ if !items . is_empty ( ) {
16181641 trait_bound_spans. push ( * span) ;
16191642 }
1620- for item_def_id in item_def_ids {
1621- let assoc_item = tcx. associated_item ( * item_def_id) ;
1643+ for assoc_item in items {
16221644 let trait_def_id = assoc_item. container . id ( ) ;
16231645 names. push ( format ! (
16241646 "`{}` (from trait `{}`)" ,
@@ -1657,7 +1679,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16571679 trait_bound_spans = vec ! [ segment. ident. span] ;
16581680 associated_types = associated_types
16591681 . into_iter ( )
1660- . map ( |( _, defs ) | ( segment. ident . span , defs ) )
1682+ . map ( |( _, items ) | ( segment. ident . span , items ) )
16611683 . collect ( ) ;
16621684 }
16631685 _ => { }
@@ -1675,16 +1697,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
16751697 let mut suggestions = vec ! [ ] ;
16761698 let mut types_count = 0 ;
16771699 let mut where_constraints = vec ! [ ] ;
1678- for ( span, def_ids) in & associated_types {
1679- let assoc_items: Vec < _ > =
1680- def_ids. iter ( ) . map ( |def_id| tcx. associated_item ( * def_id) ) . collect ( ) ;
1700+ for ( span, assoc_items) in & associated_types {
16811701 let mut names: FxHashMap < _ , usize > = FxHashMap :: default ( ) ;
1682- for item in & assoc_items {
1702+ for item in assoc_items {
16831703 types_count += 1 ;
16841704 * names. entry ( item. ident . name ) . or_insert ( 0 ) += 1 ;
16851705 }
16861706 let mut dupes = false ;
1687- for item in & assoc_items {
1707+ for item in assoc_items {
16881708 let prefix = if names[ & item. ident . name ] > 1 {
16891709 let trait_def_id = item. container . id ( ) ;
16901710 dupes = true ;
@@ -1738,16 +1758,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
17381758 }
17391759 if suggestions. len ( ) != 1 {
17401760 // We don't need this label if there's an inline suggestion, show otherwise.
1741- for ( span, def_ids) in & associated_types {
1742- let assoc_items: Vec < _ > =
1743- def_ids. iter ( ) . map ( |def_id| tcx. associated_item ( * def_id) ) . collect ( ) ;
1761+ for ( span, assoc_items) in & associated_types {
17441762 let mut names: FxHashMap < _ , usize > = FxHashMap :: default ( ) ;
1745- for item in & assoc_items {
1763+ for item in assoc_items {
17461764 types_count += 1 ;
17471765 * names. entry ( item. ident . name ) . or_insert ( 0 ) += 1 ;
17481766 }
17491767 let mut label = vec ! [ ] ;
1750- for item in & assoc_items {
1768+ for item in assoc_items {
17511769 let postfix = if names[ & item. ident . name ] > 1 {
17521770 let trait_def_id = item. container . id ( ) ;
17531771 format ! ( " (from trait `{}`)" , tcx. def_path_str( trait_def_id) )
0 commit comments