@@ -34,6 +34,7 @@ use std::iter;
3434
3535use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
3636use crate :: traits:: query:: normalize:: AtExt as _;
37+ use crate :: traits:: specialize:: to_pretty_impl_header;
3738use on_unimplemented:: InferCtxtExt as _;
3839use suggestions:: InferCtxtExt as _;
3940
@@ -241,6 +242,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
241242 let mut span = obligation. cause . span ;
242243
243244 let mut err = match * error {
245+ SelectionError :: Ambiguous ( ref impls) => {
246+ let mut err = self . tcx . sess . struct_span_err (
247+ obligation. cause . span ,
248+ & format ! ( "multiple applicable `impl`s for `{}`" , obligation. predicate) ,
249+ ) ;
250+ self . annotate_source_of_ambiguity ( & mut err, impls, obligation. predicate ) ;
251+ err. emit ( ) ;
252+ return ;
253+ }
244254 SelectionError :: Unimplemented => {
245255 // If this obligation was generated as a result of well-formedness checking, see if we
246256 // can get a better error message by performing HIR-based well-formedness checking.
@@ -1138,6 +1148,13 @@ trait InferCtxtPrivExt<'tcx> {
11381148 obligation : & PredicateObligation < ' tcx > ,
11391149 ) ;
11401150
1151+ fn annotate_source_of_ambiguity (
1152+ & self ,
1153+ err : & mut DiagnosticBuilder < ' tcx > ,
1154+ impls : & [ DefId ] ,
1155+ predicate : ty:: Predicate < ' tcx > ,
1156+ ) ;
1157+
11411158 fn maybe_suggest_unsized_generics (
11421159 & self ,
11431160 err : & mut DiagnosticBuilder < ' tcx > ,
@@ -1549,11 +1566,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
15491566 ?predicate, ?obligation. cause. code,
15501567 ) ;
15511568
1552- // Ambiguity errors are often caused as fallout from earlier
1553- // errors. So just ignore them if this infcx is tainted.
1554- if self . is_tainted_by_errors ( ) {
1555- return ;
1556- }
1569+ // Ambiguity errors are often caused as fallout from earlier errors.
1570+ // We ignore them if this `infcx` is tainted in some cases below.
15571571
15581572 let bound_predicate = predicate. kind ( ) ;
15591573 let mut err = match bound_predicate. skip_binder ( ) {
@@ -1601,10 +1615,19 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
16011615 // check upstream for type errors and don't add the obligations to
16021616 // begin with in those cases.
16031617 if self . tcx . lang_items ( ) . sized_trait ( ) == Some ( trait_ref. def_id ( ) ) {
1604- self . emit_inference_failure_err ( body_id, span, subst, vec ! [ ] , ErrorCode :: E0282 )
1618+ if !self . is_tainted_by_errors ( ) {
1619+ self . emit_inference_failure_err (
1620+ body_id,
1621+ span,
1622+ subst,
1623+ vec ! [ ] ,
1624+ ErrorCode :: E0282 ,
1625+ )
16051626 . emit ( ) ;
1627+ }
16061628 return ;
16071629 }
1630+
16081631 let impl_candidates = self . find_similar_impl_candidates ( trait_ref) ;
16091632 let mut err = self . emit_inference_failure_err (
16101633 body_id,
@@ -1613,7 +1636,29 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
16131636 impl_candidates,
16141637 ErrorCode :: E0283 ,
16151638 ) ;
1616- err. note ( & format ! ( "cannot satisfy `{}`" , predicate) ) ;
1639+
1640+ let obligation = Obligation :: new (
1641+ obligation. cause . clone ( ) ,
1642+ obligation. param_env ,
1643+ trait_ref. to_poly_trait_predicate ( ) ,
1644+ ) ;
1645+ let mut selcx = SelectionContext :: with_query_mode (
1646+ & self ,
1647+ crate :: traits:: TraitQueryMode :: Standard ,
1648+ ) ;
1649+ match selcx. select_from_obligation ( & obligation) {
1650+ Err ( SelectionError :: Ambiguous ( impls) ) if impls. len ( ) > 1 => {
1651+ self . annotate_source_of_ambiguity ( & mut err, & impls, predicate) ;
1652+ }
1653+ _ => {
1654+ if self . is_tainted_by_errors ( ) {
1655+ err. cancel ( ) ;
1656+ return ;
1657+ }
1658+ err. note ( & format ! ( "cannot satisfy `{}`" , predicate) ) ;
1659+ }
1660+ }
1661+
16171662 if let ObligationCauseCode :: ItemObligation ( def_id) = obligation. cause . code {
16181663 self . suggest_fully_qualified_path ( & mut err, def_id, span, trait_ref. def_id ( ) ) ;
16191664 } else if let (
@@ -1674,15 +1719,21 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
16741719 ty:: PredicateKind :: WellFormed ( arg) => {
16751720 // Same hacky approach as above to avoid deluging user
16761721 // with error messages.
1677- if arg. references_error ( ) || self . tcx . sess . has_errors ( ) {
1722+ if arg. references_error ( )
1723+ || self . tcx . sess . has_errors ( )
1724+ || self . is_tainted_by_errors ( )
1725+ {
16781726 return ;
16791727 }
16801728
16811729 self . emit_inference_failure_err ( body_id, span, arg, vec ! [ ] , ErrorCode :: E0282 )
16821730 }
16831731
16841732 ty:: PredicateKind :: Subtype ( data) => {
1685- if data. references_error ( ) || self . tcx . sess . has_errors ( ) {
1733+ if data. references_error ( )
1734+ || self . tcx . sess . has_errors ( )
1735+ || self . is_tainted_by_errors ( )
1736+ {
16861737 // no need to overload user in such cases
16871738 return ;
16881739 }
@@ -1694,7 +1745,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
16941745 ty:: PredicateKind :: Projection ( data) => {
16951746 let self_ty = data. projection_ty . self_ty ( ) ;
16961747 let ty = data. ty ;
1697- if predicate. references_error ( ) {
1748+ if predicate. references_error ( ) || self . is_tainted_by_errors ( ) {
16981749 return ;
16991750 }
17001751 if self_ty. needs_infer ( ) && ty. needs_infer ( ) {
@@ -1722,7 +1773,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
17221773 }
17231774
17241775 _ => {
1725- if self . tcx . sess . has_errors ( ) {
1776+ if self . tcx . sess . has_errors ( ) || self . is_tainted_by_errors ( ) {
17261777 return ;
17271778 }
17281779 let mut err = struct_span_err ! (
@@ -1740,6 +1791,96 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
17401791 err. emit ( ) ;
17411792 }
17421793
1794+ fn annotate_source_of_ambiguity (
1795+ & self ,
1796+ err : & mut DiagnosticBuilder < ' tcx > ,
1797+ impls : & [ DefId ] ,
1798+ predicate : ty:: Predicate < ' tcx > ,
1799+ ) {
1800+ let mut spans = vec ! [ ] ;
1801+ let mut crates = vec ! [ ] ;
1802+ let mut post = vec ! [ ] ;
1803+ for def_id in impls {
1804+ match self . tcx . span_of_impl ( * def_id) {
1805+ Ok ( span) => spans. push ( self . tcx . sess . source_map ( ) . guess_head_span ( span) ) ,
1806+ Err ( name) => {
1807+ crates. push ( name) ;
1808+ if let Some ( header) = to_pretty_impl_header ( self . tcx , * def_id) {
1809+ post. push ( header) ;
1810+ }
1811+ }
1812+ }
1813+ }
1814+ let msg = format ! ( "multiple `impl`s satisfying `{}` found" , predicate) ;
1815+ let mut crate_names: Vec < _ > = crates. iter ( ) . map ( |n| format ! ( "`{}`" , n) ) . collect ( ) ;
1816+ crate_names. sort ( ) ;
1817+ crate_names. dedup ( ) ;
1818+ post. sort ( ) ;
1819+ post. dedup ( ) ;
1820+
1821+ if self . is_tainted_by_errors ( )
1822+ && crate_names. len ( ) == 1
1823+ && crate_names[ 0 ] == "`core`"
1824+ && spans. len ( ) == 0
1825+ {
1826+ // Avoid complaining about other inference issues for expressions like
1827+ // `42 >> 1`, where the types are still `{integer}`, but we want to
1828+ // Do we need `trait_ref.skip_binder().self_ty().is_numeric() &&` too?
1829+ err. cancel ( ) ;
1830+ return ;
1831+ }
1832+ let post = if post. len ( ) > 4 {
1833+ format ! (
1834+ ":\n {}\n and {} more" ,
1835+ post. iter( ) . map( |p| format!( "- {}" , p) ) . take( 4 ) . collect:: <Vec <_>>( ) . join( "\n " ) ,
1836+ post. len( ) - 4 ,
1837+ )
1838+ } else if post. len ( ) > 1 || ( post. len ( ) == 1 && post[ 0 ] . contains ( "\n " ) ) {
1839+ format ! ( ":\n {}" , post. iter( ) . map( |p| format!( "- {}" , p) ) . collect:: <Vec <_>>( ) . join( "\n " ) , )
1840+ } else if post. len ( ) == 1 {
1841+ format ! ( ": `{}`" , post[ 0 ] )
1842+ } else {
1843+ String :: new ( )
1844+ } ;
1845+
1846+ match ( spans. len ( ) , crates. len ( ) , crate_names. len ( ) ) {
1847+ ( 0 , 0 , 0 ) => {
1848+ err. note ( & format ! ( "cannot satisfy `{}`" , predicate) ) ;
1849+ }
1850+ ( 0 , _, 1 ) => {
1851+ err. note ( & format ! ( "{} in the `{}` crate{}" , msg, crates[ 0 ] , post, ) ) ;
1852+ }
1853+ ( 0 , _, _) => {
1854+ err. note ( & format ! (
1855+ "{} in the following crates: {}{}" ,
1856+ msg,
1857+ crate_names. join( ", " ) ,
1858+ post,
1859+ ) ) ;
1860+ }
1861+ ( _, 0 , 0 ) => {
1862+ let span: MultiSpan = spans. into ( ) ;
1863+ err. span_note ( span, & msg) ;
1864+ }
1865+ ( _, 1 , 1 ) => {
1866+ let span: MultiSpan = spans. into ( ) ;
1867+ err. span_note ( span, & msg) ;
1868+ err. note (
1869+ & format ! ( "and another `impl` found in the `{}` crate{}" , crates[ 0 ] , post, ) ,
1870+ ) ;
1871+ }
1872+ _ => {
1873+ let span: MultiSpan = spans. into ( ) ;
1874+ err. span_note ( span, & msg) ;
1875+ err. note ( & format ! (
1876+ "and more `impl`s found in the following crates: {}{}" ,
1877+ crate_names. join( ", " ) ,
1878+ post,
1879+ ) ) ;
1880+ }
1881+ }
1882+ }
1883+
17431884 /// Returns `true` if the trait predicate may apply for *some* assignment
17441885 /// to the type parameters.
17451886 fn predicate_can_apply (
0 commit comments