@@ -23,7 +23,7 @@ use rustc_hir::GenericParam;
23
23
use rustc_hir:: Item ;
24
24
use rustc_hir:: Node ;
25
25
use rustc_infer:: infer:: error_reporting:: same_type_modulo_infer;
26
- use rustc_infer:: traits:: TraitEngine ;
26
+ use rustc_infer:: traits:: { AmbiguousSelection , TraitEngine } ;
27
27
use rustc_middle:: thir:: abstract_const:: NotConstEvaluatable ;
28
28
use rustc_middle:: traits:: select:: OverflowError ;
29
29
use rustc_middle:: ty:: error:: ExpectedFound ;
@@ -1404,7 +1404,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
1404
1404
fn annotate_source_of_ambiguity (
1405
1405
& self ,
1406
1406
err : & mut Diagnostic ,
1407
- impls : & [ DefId ] ,
1407
+ impls : & [ AmbiguousSelection ] ,
1408
1408
predicate : ty:: Predicate < ' tcx > ,
1409
1409
) ;
1410
1410
@@ -2020,6 +2020,14 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
2020
2020
) ;
2021
2021
match selcx. select_from_obligation ( & obligation) {
2022
2022
Err ( SelectionError :: Ambiguous ( impls) ) if impls. len ( ) > 1 => {
2023
+ if self . is_tainted_by_errors ( ) && subst. is_none ( ) {
2024
+ // If `subst.is_none()`, then this is probably two param-env
2025
+ // candidates or impl candidates that are equal modulo lifetimes.
2026
+ // Therefore, if we've already emitted an error, just skip this
2027
+ // one, since it's not particularly actionable.
2028
+ err. cancel ( ) ;
2029
+ return ;
2030
+ }
2023
2031
self . annotate_source_of_ambiguity ( & mut err, & impls, predicate) ;
2024
2032
}
2025
2033
_ => {
@@ -2170,24 +2178,35 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
2170
2178
fn annotate_source_of_ambiguity (
2171
2179
& self ,
2172
2180
err : & mut Diagnostic ,
2173
- impls : & [ DefId ] ,
2181
+ impls : & [ AmbiguousSelection ] ,
2174
2182
predicate : ty:: Predicate < ' tcx > ,
2175
2183
) {
2176
2184
let mut spans = vec ! [ ] ;
2177
2185
let mut crates = vec ! [ ] ;
2178
2186
let mut post = vec ! [ ] ;
2179
- for def_id in impls {
2180
- match self . tcx . span_of_impl ( * def_id) {
2181
- Ok ( span) => spans. push ( span) ,
2182
- Err ( name) => {
2183
- crates. push ( name) ;
2184
- if let Some ( header) = to_pretty_impl_header ( self . tcx , * def_id) {
2185
- post. push ( header) ;
2187
+ let mut or_where_clause = false ;
2188
+ for ambig in impls {
2189
+ match ambig {
2190
+ AmbiguousSelection :: Impl ( def_id) => match self . tcx . span_of_impl ( * def_id) {
2191
+ Ok ( span) => spans. push ( span) ,
2192
+ Err ( name) => {
2193
+ crates. push ( name) ;
2194
+ if let Some ( header) = to_pretty_impl_header ( self . tcx , * def_id) {
2195
+ post. push ( header) ;
2196
+ }
2186
2197
}
2198
+ } ,
2199
+ AmbiguousSelection :: ParamEnv ( span) => {
2200
+ or_where_clause = true ;
2201
+ spans. push ( * span) ;
2187
2202
}
2188
2203
}
2189
2204
}
2190
- let msg = format ! ( "multiple `impl`s satisfying `{}` found" , predicate) ;
2205
+ let msg = format ! (
2206
+ "multiple `impl`s{} satisfying `{}` found" ,
2207
+ if or_where_clause { " or `where` clauses" } else { "" } ,
2208
+ predicate
2209
+ ) ;
2191
2210
let mut crate_names: Vec < _ > = crates. iter ( ) . map ( |n| format ! ( "`{}`" , n) ) . collect ( ) ;
2192
2211
crate_names. sort ( ) ;
2193
2212
crate_names. dedup ( ) ;
0 commit comments