@@ -23,7 +23,7 @@ use rustc_hir::GenericParam;
2323use rustc_hir:: Item ;
2424use rustc_hir:: Node ;
2525use rustc_infer:: infer:: error_reporting:: same_type_modulo_infer;
26- use rustc_infer:: traits:: TraitEngine ;
26+ use rustc_infer:: traits:: { AmbiguousSelection , TraitEngine } ;
2727use rustc_middle:: thir:: abstract_const:: NotConstEvaluatable ;
2828use rustc_middle:: traits:: select:: OverflowError ;
2929use rustc_middle:: ty:: error:: ExpectedFound ;
@@ -1404,7 +1404,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
14041404 fn annotate_source_of_ambiguity (
14051405 & self ,
14061406 err : & mut Diagnostic ,
1407- impls : & [ DefId ] ,
1407+ impls : & [ AmbiguousSelection ] ,
14081408 predicate : ty:: Predicate < ' tcx > ,
14091409 ) ;
14101410
@@ -2020,6 +2020,14 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
20202020 ) ;
20212021 match selcx. select_from_obligation ( & obligation) {
20222022 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+ }
20232031 self . annotate_source_of_ambiguity ( & mut err, & impls, predicate) ;
20242032 }
20252033 _ => {
@@ -2170,24 +2178,35 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
21702178 fn annotate_source_of_ambiguity (
21712179 & self ,
21722180 err : & mut Diagnostic ,
2173- impls : & [ DefId ] ,
2181+ impls : & [ AmbiguousSelection ] ,
21742182 predicate : ty:: Predicate < ' tcx > ,
21752183 ) {
21762184 let mut spans = vec ! [ ] ;
21772185 let mut crates = vec ! [ ] ;
21782186 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+ }
21862197 }
2198+ } ,
2199+ AmbiguousSelection :: ParamEnv ( span) => {
2200+ or_where_clause = true ;
2201+ spans. push ( * span) ;
21872202 }
21882203 }
21892204 }
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+ ) ;
21912210 let mut crate_names: Vec < _ > = crates. iter ( ) . map ( |n| format ! ( "`{}`" , n) ) . collect ( ) ;
21922211 crate_names. sort ( ) ;
21932212 crate_names. dedup ( ) ;
0 commit comments