@@ -814,6 +814,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
814
814
}
815
815
}
816
816
817
+ /// On missing type parameters, emit an E0393 error and provide a structured suggestion using
818
+ /// the type parameter's name as a placeholder.
817
819
fn complain_about_missing_type_params (
818
820
& self ,
819
821
missing_type_params : Vec < String > ,
@@ -1010,15 +1012,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1010
1012
ty:: TraitRef :: new ( trait_def_id, substs)
1011
1013
}
1012
1014
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 (
1014
1018
& self ,
1015
1019
span : Span ,
1016
1020
trait_def_id : DefId ,
1017
- self_ty : Ty < ' tcx > ,
1018
1021
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
+ ) {
1022
1023
let trait_def = self . tcx ( ) . trait_def ( trait_def_id) ;
1023
1024
1024
1025
if !self . tcx ( ) . features ( ) . unboxed_closures
@@ -1068,6 +1069,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1068
1069
}
1069
1070
err. emit ( ) ;
1070
1071
}
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) ;
1071
1084
1072
1085
self . create_substs_for_ast_path (
1073
1086
span,
@@ -1452,8 +1465,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1452
1465
. filter ( |( trait_ref, _) | !tcx. trait_is_auto ( trait_ref. def_id ( ) ) ) ;
1453
1466
1454
1467
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 ! [ ] ;
1457
1468
for trait_ref in traits:: elaborate_trait_ref ( tcx, base_trait_ref) {
1458
1469
debug ! (
1459
1470
"conv_object_ty_poly_trait_ref: observing object predicate `{:?}`" ,
@@ -1486,17 +1497,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1486
1497
// but actually supporting that would "expand" to an infinitely-long type
1487
1498
// `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
1488
1499
//
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.
1491
1503
if !references_self {
1492
1504
// Include projections defined on supertraits.
1493
- new_bounds . push ( ( pred, span) ) ;
1505
+ bounds . projection_bounds . push ( ( pred, span) ) ;
1494
1506
}
1495
1507
}
1496
1508
_ => ( ) ,
1497
1509
}
1498
1510
}
1499
- bounds. projection_bounds . extend ( new_bounds) ;
1500
1511
}
1501
1512
1502
1513
for ( projection_bound, _) in & bounds. projection_bounds {
@@ -1598,27 +1609,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1598
1609
ty
1599
1610
}
1600
1611
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.
1601
1616
fn complain_about_missing_associated_types (
1602
1617
& self ,
1603
- mut associated_types : FxHashMap < Span , BTreeSet < DefId > > ,
1618
+ associated_types : FxHashMap < Span , BTreeSet < DefId > > ,
1604
1619
potential_assoc_types : Vec < Span > ,
1605
1620
trait_bounds : & [ hir:: PolyTraitRef ] ,
1606
1621
) {
1607
1622
if !associated_types. values ( ) . any ( |v| v. len ( ) > 0 ) {
1608
1623
return ;
1609
1624
}
1610
1625
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 ( ) ;
1611
1634
let mut names = vec ! [ ] ;
1612
1635
1613
1636
// Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
1614
1637
// `issue-22560.rs`.
1615
1638
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 ( ) {
1618
1641
trait_bound_spans. push ( * span) ;
1619
1642
}
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 {
1622
1644
let trait_def_id = assoc_item. container . id ( ) ;
1623
1645
names. push ( format ! (
1624
1646
"`{}` (from trait `{}`)" ,
@@ -1657,7 +1679,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1657
1679
trait_bound_spans = vec ! [ segment. ident. span] ;
1658
1680
associated_types = associated_types
1659
1681
. into_iter ( )
1660
- . map ( |( _, defs ) | ( segment. ident . span , defs ) )
1682
+ . map ( |( _, items ) | ( segment. ident . span , items ) )
1661
1683
. collect ( ) ;
1662
1684
}
1663
1685
_ => { }
@@ -1675,16 +1697,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1675
1697
let mut suggestions = vec ! [ ] ;
1676
1698
let mut types_count = 0 ;
1677
1699
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 {
1681
1701
let mut names: FxHashMap < _ , usize > = FxHashMap :: default ( ) ;
1682
- for item in & assoc_items {
1702
+ for item in assoc_items {
1683
1703
types_count += 1 ;
1684
1704
* names. entry ( item. ident . name ) . or_insert ( 0 ) += 1 ;
1685
1705
}
1686
1706
let mut dupes = false ;
1687
- for item in & assoc_items {
1707
+ for item in assoc_items {
1688
1708
let prefix = if names[ & item. ident . name ] > 1 {
1689
1709
let trait_def_id = item. container . id ( ) ;
1690
1710
dupes = true ;
@@ -1738,16 +1758,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
1738
1758
}
1739
1759
if suggestions. len ( ) != 1 {
1740
1760
// 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 {
1744
1762
let mut names: FxHashMap < _ , usize > = FxHashMap :: default ( ) ;
1745
- for item in & assoc_items {
1763
+ for item in assoc_items {
1746
1764
types_count += 1 ;
1747
1765
* names. entry ( item. ident . name ) . or_insert ( 0 ) += 1 ;
1748
1766
}
1749
1767
let mut label = vec ! [ ] ;
1750
- for item in & assoc_items {
1768
+ for item in assoc_items {
1751
1769
let postfix = if names[ & item. ident . name ] > 1 {
1752
1770
let trait_def_id = item. container . id ( ) ;
1753
1771
format ! ( " (from trait `{}`)" , tcx. def_path_str( trait_def_id) )
0 commit comments