@@ -96,25 +96,36 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
96
96
97
97
#[ derive( Clone ) ]
98
98
pub enum IntercrateAmbiguityCause {
99
- DownstreamCrate ( DefId ) ,
100
- UpstreamCrateUpdate ( DefId ) ,
99
+ DownstreamCrate {
100
+ trait_desc : String ,
101
+ self_desc : Option < String > ,
102
+ } ,
103
+ UpstreamCrateUpdate {
104
+ trait_desc : String ,
105
+ self_desc : Option < String > ,
106
+ } ,
101
107
}
102
108
103
109
impl IntercrateAmbiguityCause {
104
110
/// Emits notes when the overlap is caused by complex intercrate ambiguities.
105
111
/// See #23980 for details.
106
112
pub fn add_intercrate_ambiguity_hint < ' a , ' tcx > ( & self ,
107
- tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
108
113
err : & mut :: errors:: DiagnosticBuilder ) {
109
114
match self {
110
- & IntercrateAmbiguityCause :: DownstreamCrate ( def_id) => {
111
- err. note ( & format ! ( "downstream crates may implement `{}`" ,
112
- tcx. item_path_str( def_id) ) ) ;
113
- }
114
- & IntercrateAmbiguityCause :: UpstreamCrateUpdate ( def_id) => {
115
- err. note ( & format ! ( "upstream crates may add new impl for `{}` \
115
+ & IntercrateAmbiguityCause :: DownstreamCrate { ref trait_desc, ref self_desc } => {
116
+ let self_desc = if let & Some ( ref ty) = self_desc {
117
+ format ! ( " for type `{}`" , ty)
118
+ } else { "" . to_string ( ) } ;
119
+ err. note ( & format ! ( "downstream crates may implement trait `{}`{}" ,
120
+ trait_desc, self_desc) ) ;
121
+ }
122
+ & IntercrateAmbiguityCause :: UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
123
+ let self_desc = if let & Some ( ref ty) = self_desc {
124
+ format ! ( " for type `{}`" , ty)
125
+ } else { "" . to_string ( ) } ;
126
+ err. note ( & format ! ( "upstream crates may add new impl of trait `{}`{} \
116
127
in future versions",
117
- tcx . item_path_str ( def_id ) ) ) ;
128
+ trait_desc , self_desc ) ) ;
118
129
}
119
130
}
120
131
}
@@ -794,9 +805,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
794
805
// Heuristics: show the diagnostics when there are no candidates in crate.
795
806
if let Ok ( candidate_set) = self . assemble_candidates ( stack) {
796
807
if !candidate_set. ambiguous && candidate_set. vec . is_empty ( ) {
797
- let did = stack. fresh_trait_ref . def_id ( ) ;
798
- self . intercrate_ambiguity_causes . push (
799
- IntercrateAmbiguityCause :: DownstreamCrate ( did) ) ;
808
+ let trait_ref = stack. obligation . predicate . skip_binder ( ) . trait_ref ;
809
+ let self_ty = trait_ref. self_ty ( ) ;
810
+ let cause = IntercrateAmbiguityCause :: DownstreamCrate {
811
+ trait_desc : trait_ref. to_string ( ) ,
812
+ self_desc : if self_ty. has_concrete_skeleton ( ) {
813
+ Some ( self_ty. to_string ( ) )
814
+ } else {
815
+ None
816
+ } ,
817
+ } ;
818
+ self . intercrate_ambiguity_causes . push ( cause) ;
800
819
}
801
820
}
802
821
return EvaluatedToAmbig ;
@@ -1048,9 +1067,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
1048
1067
// Heuristics: show the diagnostics when there are no candidates in crate.
1049
1068
let candidate_set = self . assemble_candidates ( stack) ?;
1050
1069
if !candidate_set. ambiguous && candidate_set. vec . is_empty ( ) {
1051
- let did = stack. obligation . predicate . def_id ( ) ;
1052
- self . intercrate_ambiguity_causes . push (
1053
- IntercrateAmbiguityCause :: UpstreamCrateUpdate ( did) ) ;
1070
+ let trait_ref = stack. obligation . predicate . skip_binder ( ) . trait_ref ;
1071
+ let self_ty = trait_ref. self_ty ( ) ;
1072
+ let cause = IntercrateAmbiguityCause :: UpstreamCrateUpdate {
1073
+ trait_desc : trait_ref. to_string ( ) ,
1074
+ self_desc : if self_ty. has_concrete_skeleton ( ) {
1075
+ Some ( self_ty. to_string ( ) )
1076
+ } else {
1077
+ None
1078
+ } ,
1079
+ } ;
1080
+ self . intercrate_ambiguity_causes . push ( cause) ;
1054
1081
}
1055
1082
return Ok ( None ) ;
1056
1083
}
0 commit comments