about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-11-08 19:35:08 +0000
committerbors <bors@rust-lang.org>2022-11-08 19:35:08 +0000
commit85f4f41deb1557ca8ab228319d33003dd2f20f45 (patch)
treeb7604f9fd3635321f3ecabf75f3d4c180e68fbcb
parentc5842b0be783dffa5a49693541acb79115c7eeef (diff)
parent91d5a32bc59c50af762928da5a02b024b36c1891 (diff)
Auto merge of #103252 - lcnr:recompute_applicable_impls, r=jackh726
selection failure: recompute applicable impls

The way we currently skip errors for ambiguous trait obligations seems pretty fragile so we get some duplicate errors because of this.

Removing this info from selection errors changes this system to be closer to my image of our new trait solver and is also making it far easier to change overflow errors to be non-fatal :sparkles:

r? types cc `@estebank`
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs3
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs15
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs17
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs52
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs40
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs4
-rw-r--r--src/test/ui/error-codes/E0282.rs3
-rw-r--r--src/test/ui/error-codes/E0401.rs4
-rw-r--r--src/test/ui/error-codes/E0401.stderr27
-rw-r--r--src/test/ui/impl-trait/cross-return-site-inference.rs9
-rw-r--r--src/test/ui/impl-trait/cross-return-site-inference.stderr4
-rw-r--r--src/test/ui/inference/cannot-infer-async.rs3
-rw-r--r--src/test/ui/inference/cannot-infer-closure.rs3
-rw-r--r--src/test/ui/inference/issue-71732.rs3
-rw-r--r--src/test/ui/inference/issue-72616.rs5
-rw-r--r--src/test/ui/inference/issue-72616.stderr20
-rw-r--r--src/test/ui/inference/question-mark-type-infer.rs3
-rw-r--r--src/test/ui/issues/issue-71584.rs3
-rw-r--r--src/test/ui/traits/issue-77982.stderr7
21 files changed, 170 insertions, 75 deletions
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index a29f0722ff7..05382bd887c 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -576,9 +576,6 @@ pub enum SelectionError<'tcx> {
     /// Signaling that an error has already been emitted, to avoid
     /// multiple errors being shown.
     ErrorReporting,
-    /// Multiple applicable `impl`s where found. The `DefId`s correspond to
-    /// all the `impl`s' Items.
-    Ambiguous(Vec<DefId>),
 }
 
 /// When performing resolution, it is typically the case that there
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 27090c62d21..b509ae6dd3b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2550,11 +2550,11 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err`
     /// with the name of the crate containing the impl.
-    pub fn span_of_impl(self, impl_did: DefId) -> Result<Span, Symbol> {
-        if let Some(impl_did) = impl_did.as_local() {
-            Ok(self.def_span(impl_did))
+    pub fn span_of_impl(self, impl_def_id: DefId) -> Result<Span, Symbol> {
+        if let Some(impl_def_id) = impl_def_id.as_local() {
+            Ok(self.def_span(impl_def_id))
         } else {
-            Err(self.crate_name(impl_did.krate))
+            Err(self.crate_name(impl_def_id.krate))
         }
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
index 81e1d64493e..d32a990f182 100644
--- a/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/chalk_fulfill.rs
@@ -14,6 +14,8 @@ pub struct FulfillmentContext<'tcx> {
     obligations: FxIndexSet<PredicateObligation<'tcx>>,
 
     relationships: FxHashMap<ty::TyVid, ty::FoundRelationships>,
+
+    usable_in_snapshot: bool,
 }
 
 impl FulfillmentContext<'_> {
@@ -21,8 +23,13 @@ impl FulfillmentContext<'_> {
         FulfillmentContext {
             obligations: FxIndexSet::default(),
             relationships: FxHashMap::default(),
+            usable_in_snapshot: false,
         }
     }
+
+    pub(crate) fn new_in_snapshot() -> Self {
+        FulfillmentContext { usable_in_snapshot: true, ..Self::new() }
+    }
 }
 
 impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
@@ -41,7 +48,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
         infcx: &InferCtxt<'tcx>,
         obligation: PredicateObligation<'tcx>,
     ) {
-        assert!(!infcx.is_in_snapshot());
+        if !self.usable_in_snapshot {
+            assert!(!infcx.is_in_snapshot());
+        }
         let obligation = infcx.resolve_vars_if_possible(obligation);
 
         super::relationships::update(self, infcx, &obligation);
@@ -72,7 +81,9 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
     }
 
     fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> {
-        assert!(!infcx.is_in_snapshot());
+        if !self.usable_in_snapshot {
+            assert!(!infcx.is_in_snapshot());
+        }
 
         let mut errors = Vec::new();
         let mut next_round = FxIndexSet::default();
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 21516c93efb..0eafc49816d 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -38,7 +38,7 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> {
 
     fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box<Self> {
         if tcx.sess.opts.unstable_opts.chalk {
-            Box::new(ChalkFulfillmentContext::new())
+            Box::new(ChalkFulfillmentContext::new_in_snapshot())
         } else {
             Box::new(FulfillmentContext::new_in_snapshot())
         }
@@ -119,13 +119,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         expected: T,
         actual: T,
     ) -> Result<(), TypeError<'tcx>> {
-        match self.infcx.at(cause, param_env).eq(expected, actual) {
-            Ok(InferOk { obligations, value: () }) => {
-                self.register_obligations(obligations);
-                Ok(())
-            }
-            Err(e) => Err(e),
-        }
+        self.infcx
+            .at(cause, param_env)
+            .eq(expected, actual)
+            .map(|infer_ok| self.register_infer_ok_obligations(infer_ok))
     }
 
     pub fn sup<T: ToTrace<'tcx>>(
@@ -144,6 +141,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
         }
     }
 
+    pub fn select_where_possible(&self) -> Vec<FulfillmentError<'tcx>> {
+        self.engine.borrow_mut().select_where_possible(self.infcx)
+    }
+
     pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> {
         self.engine.borrow_mut().select_all_or_error(self.infcx)
     }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
new file mode 100644
index 00000000000..58da54afb75
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs
@@ -0,0 +1,52 @@
+use rustc_hir::def_id::DefId;
+use rustc_infer::infer::InferCtxt;
+use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation};
+use rustc_span::DUMMY_SP;
+
+use crate::traits::ObligationCtxt;
+
+pub fn recompute_applicable_impls<'tcx>(
+    infcx: &InferCtxt<'tcx>,
+    obligation: &TraitObligation<'tcx>,
+) -> Vec<DefId> {
+    let tcx = infcx.tcx;
+    let param_env = obligation.param_env;
+    let dummy_cause = ObligationCause::dummy();
+    let impl_may_apply = |impl_def_id| {
+        let ocx = ObligationCtxt::new_in_snapshot(infcx);
+        let placeholder_obligation =
+            infcx.replace_bound_vars_with_placeholders(obligation.predicate);
+        let obligation_trait_ref =
+            ocx.normalize(dummy_cause.clone(), param_env, placeholder_obligation.trait_ref);
+
+        let impl_substs = infcx.fresh_substs_for_item(DUMMY_SP, impl_def_id);
+        let impl_trait_ref = tcx.bound_impl_trait_ref(impl_def_id).unwrap().subst(tcx, impl_substs);
+        let impl_trait_ref = ocx.normalize(ObligationCause::dummy(), param_env, impl_trait_ref);
+
+        if let Err(_) = ocx.eq(&dummy_cause, param_env, obligation_trait_ref, impl_trait_ref) {
+            return false;
+        }
+
+        let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs);
+        ocx.register_obligations(
+            impl_predicates
+                .predicates
+                .iter()
+                .map(|&predicate| Obligation::new(dummy_cause.clone(), param_env, predicate)),
+        );
+
+        ocx.select_where_possible().is_empty()
+    };
+
+    let mut impls = Vec::new();
+    tcx.for_each_relevant_impl(
+        obligation.predicate.def_id(),
+        obligation.predicate.skip_binder().trait_ref.self_ty(),
+        |impl_def_id| {
+            if infcx.probe(move |_snapshot| impl_may_apply(impl_def_id)) {
+                impls.push(impl_def_id)
+            }
+        },
+    );
+    impls
+}
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index c7dee4a18ac..0f5d05afcf8 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1,3 +1,4 @@
+mod ambiguity;
 pub mod on_unimplemented;
 pub mod suggestions;
 
@@ -535,15 +536,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let mut span = obligation.cause.span;
 
         let mut err = match *error {
-            SelectionError::Ambiguous(ref impls) => {
-                let mut err = self.tcx.sess.struct_span_err(
-                    obligation.cause.span,
-                    &format!("multiple applicable `impl`s for `{}`", obligation.predicate),
-                );
-                self.annotate_source_of_ambiguity(&mut err, impls, obligation.predicate);
-                err.emit();
-                return;
-            }
             SelectionError::Unimplemented => {
                 // If this obligation was generated as a result of well-formedness checking, see if we
                 // can get a better error message by performing HIR-based well-formedness checking.
@@ -2144,12 +2136,25 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     crate::traits::TraitQueryMode::Standard,
                 );
                 match selcx.select_from_obligation(&obligation) {
-                    Err(SelectionError::Ambiguous(impls)) if impls.len() > 1 => {
-                        self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
+                    Ok(None) => {
+                        let impls = ambiguity::recompute_applicable_impls(self.infcx, &obligation);
+                        let has_non_region_infer =
+                            trait_ref.skip_binder().substs.types().any(|t| !t.is_ty_infer());
+                        // It doesn't make sense to talk about applicable impls if there are more
+                        // than a handful of them.
+                        if impls.len() > 1 && impls.len() < 5 && has_non_region_infer {
+                            self.annotate_source_of_ambiguity(&mut err, &impls, predicate);
+                        } else {
+                            if self.is_tainted_by_errors() {
+                                err.delay_as_bug();
+                                return;
+                            }
+                            err.note(&format!("cannot satisfy `{}`", predicate));
+                        }
                     }
                     _ => {
                         if self.is_tainted_by_errors() {
-                            err.cancel();
+                            err.delay_as_bug();
                             return;
                         }
                         err.note(&format!("cannot satisfy `{}`", predicate));
@@ -2441,7 +2446,6 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 }
             }
         }
-        let msg = format!("multiple `impl`s satisfying `{}` found", predicate);
         let mut crate_names: Vec<_> = crates.iter().map(|n| format!("`{}`", n)).collect();
         crate_names.sort();
         crate_names.dedup();
@@ -2462,13 +2466,9 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             err.downgrade_to_delayed_bug();
             return;
         }
-        let post = if post.len() > 4 {
-            format!(
-                ":\n{}\nand {} more",
-                post.iter().map(|p| format!("- {}", p)).take(4).collect::<Vec<_>>().join("\n"),
-                post.len() - 4,
-            )
-        } else if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
+
+        let msg = format!("multiple `impl`s satisfying `{}` found", predicate);
+        let post = if post.len() > 1 || (post.len() == 1 && post[0].contains('\n')) {
             format!(":\n{}", post.iter().map(|p| format!("- {}", p)).collect::<Vec<_>>().join("\n"),)
         } else if post.len() == 1 {
             format!(": `{}`", post[0])
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 4c5bc333961..3671a0d87df 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -20,7 +20,7 @@ use crate::traits;
 use crate::traits::coherence::Conflict;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::{util, SelectionResult};
-use crate::traits::{Ambiguous, ErrorReporting, Overflow, Unimplemented};
+use crate::traits::{ErrorReporting, Overflow, Unimplemented};
 
 use super::BuiltinImplConditions;
 use super::IntercrateAmbiguityCause;
@@ -200,15 +200,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // and report ambiguity.
                     if i > 1 {
                         debug!("multiple matches, ambig");
-                        return Err(Ambiguous(
-                            candidates
-                                .into_iter()
-                                .filter_map(|c| match c.candidate {
-                                    SelectionCandidate::ImplCandidate(def_id) => Some(def_id),
-                                    _ => None,
-                                })
-                                .collect(),
-                        ));
+                        return Ok(None);
                     }
                 }
             }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 84be1ced520..2954a2c163f 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -294,9 +294,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 assert!(self.query_mode == TraitQueryMode::Canonical);
                 return Err(SelectionError::Overflow(OverflowError::Canonical));
             }
-            Err(SelectionError::Ambiguous(_)) => {
-                return Ok(None);
-            }
             Err(e) => {
                 return Err(e);
             }
@@ -931,7 +928,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         match self.candidate_from_obligation(stack) {
             Ok(Some(c)) => self.evaluate_candidate(stack, &c),
-            Err(SelectionError::Ambiguous(_)) => Ok(EvaluatedToAmbig),
             Ok(None) => Ok(EvaluatedToAmbig),
             Err(Overflow(OverflowError::Canonical)) => Err(OverflowError::Canonical),
             Err(ErrorReporting) => Err(OverflowError::ErrorReporting),
diff --git a/src/test/ui/error-codes/E0282.rs b/src/test/ui/error-codes/E0282.rs
index 9bd16abb7bb..f1f93b3aed6 100644
--- a/src/test/ui/error-codes/E0282.rs
+++ b/src/test/ui/error-codes/E0282.rs
@@ -1,3 +1,4 @@
 fn main() {
-    let x = "hello".chars().rev().collect(); //~ ERROR E0282
+    let x = "hello".chars().rev().collect();
+    //~^ ERROR E0282
 }
diff --git a/src/test/ui/error-codes/E0401.rs b/src/test/ui/error-codes/E0401.rs
index c30e5f47188..8f8d6b87ef2 100644
--- a/src/test/ui/error-codes/E0401.rs
+++ b/src/test/ui/error-codes/E0401.rs
@@ -8,7 +8,9 @@ fn foo<T>(x: T) {
            W: Fn()>
            (y: T) { //~ ERROR E0401
     }
-    bfnr(x); //~ ERROR type annotations needed
+    bfnr(x);
+    //~^ ERROR type annotations needed
+    //~| ERROR type annotations needed
 }
 
 
diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr
index b0e2ef5b6f7..9687eca61fa 100644
--- a/src/test/ui/error-codes/E0401.stderr
+++ b/src/test/ui/error-codes/E0401.stderr
@@ -21,7 +21,7 @@ LL |            (y: T) {
    |                ^ use of generic parameter from outer function
 
 error[E0401]: can't use generic parameters from outer function
-  --> $DIR/E0401.rs:22:25
+  --> $DIR/E0401.rs:24:25
    |
 LL | impl<T> Iterator for A<T> {
    | ---- `Self` type implicitly declared here, by this `impl`
@@ -43,7 +43,28 @@ help: consider specifying the generic arguments
 LL |     bfnr::<U, V, W>(x);
    |         +++++++++++
 
-error: aborting due to 4 previous errors
+error[E0283]: type annotations needed
+  --> $DIR/E0401.rs:11:5
+   |
+LL |     bfnr(x);
+   |     ^^^^ cannot infer type of the type parameter `W` declared on the function `bfnr`
+   |
+   = note: multiple `impl`s satisfying `_: Fn<()>` found in the following crates: `alloc`, `core`:
+           - impl<A, F> Fn<A> for &F
+             where A: Tuple, F: Fn<A>, F: ?Sized;
+           - impl<Args, F, A> Fn<Args> for Box<F, A>
+             where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
+note: required by a bound in `bfnr`
+  --> $DIR/E0401.rs:4:30
+   |
+LL |     fn bfnr<U, V: Baz<U>, W: Fn()>(y: T) {
+   |                              ^^^^ required by this bound in `bfnr`
+help: consider specifying the type arguments in the function call
+   |
+LL |     bfnr::<U, V, W>(x);
+   |         +++++++++++
+
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0282, E0401.
+Some errors have detailed explanations: E0282, E0283, E0401.
 For more information about an error, try `rustc --explain E0282`.
diff --git a/src/test/ui/impl-trait/cross-return-site-inference.rs b/src/test/ui/impl-trait/cross-return-site-inference.rs
index d881af9ed8f..00aed2ad95a 100644
--- a/src/test/ui/impl-trait/cross-return-site-inference.rs
+++ b/src/test/ui/impl-trait/cross-return-site-inference.rs
@@ -30,16 +30,19 @@ fn baa(b: bool) -> impl std::fmt::Debug {
 
 fn muh() -> Result<(), impl std::fmt::Debug> {
     Err("whoops")?;
-    Ok(()) //~ ERROR type annotations needed
+    Ok(())
+    //~^ ERROR type annotations needed
 }
 
 fn muh2() -> Result<(), impl std::fmt::Debug> {
-    return Err(From::from("foo")); //~ ERROR type annotations needed
+    return Err(From::from("foo"));
+    //~^ ERROR type annotations needed
     Ok(())
 }
 
 fn muh3() -> Result<(), impl std::fmt::Debug> {
-    Err(From::from("foo")) //~ ERROR type annotations needed
+    Err(From::from("foo"))
+    //~^ ERROR type annotations needed
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/cross-return-site-inference.stderr b/src/test/ui/impl-trait/cross-return-site-inference.stderr
index 1ff777e6503..766614e9e50 100644
--- a/src/test/ui/impl-trait/cross-return-site-inference.stderr
+++ b/src/test/ui/impl-trait/cross-return-site-inference.stderr
@@ -10,7 +10,7 @@ LL |     Ok::<(), E>(())
    |       +++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/cross-return-site-inference.rs:37:12
+  --> $DIR/cross-return-site-inference.rs:38:12
    |
 LL |     return Err(From::from("foo"));
    |            ^^^ cannot infer type of the type parameter `E` declared on the enum `Result`
@@ -21,7 +21,7 @@ LL |     return Err::<(), E>(From::from("foo"));
    |               +++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/cross-return-site-inference.rs:42:5
+  --> $DIR/cross-return-site-inference.rs:44:5
    |
 LL |     Err(From::from("foo"))
    |     ^^^ cannot infer type of the type parameter `E` declared on the enum `Result`
diff --git a/src/test/ui/inference/cannot-infer-async.rs b/src/test/ui/inference/cannot-infer-async.rs
index e7fabd0ffbc..b5152d04f69 100644
--- a/src/test/ui/inference/cannot-infer-async.rs
+++ b/src/test/ui/inference/cannot-infer-async.rs
@@ -10,6 +10,7 @@ fn main() {
     let fut = async {
         make_unit()?;
 
-        Ok(()) //~ ERROR type annotations needed
+        Ok(())
+        //~^ ERROR type annotations needed
     };
 }
diff --git a/src/test/ui/inference/cannot-infer-closure.rs b/src/test/ui/inference/cannot-infer-closure.rs
index 1c350b18f5a..bd5d10b4173 100644
--- a/src/test/ui/inference/cannot-infer-closure.rs
+++ b/src/test/ui/inference/cannot-infer-closure.rs
@@ -1,6 +1,7 @@
 fn main() {
     let x = |a: (), b: ()| {
         Err(a)?;
-        Ok(b) //~ ERROR type annotations needed
+        Ok(b)
+        //~^ ERROR type annotations needed
     };
 }
diff --git a/src/test/ui/inference/issue-71732.rs b/src/test/ui/inference/issue-71732.rs
index 30063a0957c..8a9d2b235f0 100644
--- a/src/test/ui/inference/issue-71732.rs
+++ b/src/test/ui/inference/issue-71732.rs
@@ -15,7 +15,8 @@ use std::collections::hash_map::HashMap;
 
 fn foo(parameters: &HashMap<String, String>) -> bool {
     parameters
-        .get(&"key".into()) //~ ERROR: type annotations needed
+        .get(&"key".into())
+        //~^ ERROR type annotations needed
         .and_then(|found: &String| Some(false))
         .unwrap_or(false)
 }
diff --git a/src/test/ui/inference/issue-72616.rs b/src/test/ui/inference/issue-72616.rs
index 5e5a3babfe0..69ade1a7515 100644
--- a/src/test/ui/inference/issue-72616.rs
+++ b/src/test/ui/inference/issue-72616.rs
@@ -1,3 +1,5 @@
+// ignore-wasm32 FIXME: ignoring wasm as it suggests slightly different impls
+
 // Regression test for #72616, it used to emit incorrect diagnostics, like:
 // error[E0283]: type annotations needed for `String`
 //  --> src/main.rs:8:30
@@ -18,7 +20,8 @@ pub fn main() {
     }
     {
         if String::from("a") == "a".try_into().unwrap() {}
-        //~^ ERROR: type annotations needed
+        //~^ ERROR type annotations needed
+        //~| ERROR type annotations needed
     }
     {
         let _: String = match "_".try_into() {
diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr
index a71ce9a8ef2..6ee0626cab8 100644
--- a/src/test/ui/inference/issue-72616.stderr
+++ b/src/test/ui/inference/issue-72616.stderr
@@ -1,5 +1,5 @@
 error[E0283]: type annotations needed
-  --> $DIR/issue-72616.rs:20:37
+  --> $DIR/issue-72616.rs:22:37
    |
 LL |         if String::from("a") == "a".try_into().unwrap() {}
    |                              --     ^^^^^^^^
@@ -16,6 +16,22 @@ help: try using a fully qualified path to specify the expected types
 LL |         if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {}
    |                                 +++++++++++++++++++++++++++++++   ~
 
-error: aborting due to previous error
+error[E0283]: type annotations needed
+  --> $DIR/issue-72616.rs:22:37
+   |
+LL |         if String::from("a") == "a".try_into().unwrap() {}
+   |                                     ^^^^^^^^
+   |
+   = note: multiple `impl`s satisfying `_: TryFrom<&str>` found in the following crates: `core`, `std`:
+           - impl<> TryFrom<&str> for std::sys_common::net::LookupHost;
+           - impl<T, U> TryFrom<U> for T
+             where U: Into<T>;
+   = note: required for `&str` to implement `TryInto<_>`
+help: try using a fully qualified path to specify the expected types
+   |
+LL |         if String::from("a") == <&str as TryInto<T>>::try_into("a").unwrap() {}
+   |                                 +++++++++++++++++++++++++++++++   ~
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0283`.
diff --git a/src/test/ui/inference/question-mark-type-infer.rs b/src/test/ui/inference/question-mark-type-infer.rs
index 64333a29313..10560f85ed4 100644
--- a/src/test/ui/inference/question-mark-type-infer.rs
+++ b/src/test/ui/inference/question-mark-type-infer.rs
@@ -7,7 +7,8 @@ fn f(x: &i32) -> Result<i32, ()> {
 
 fn g() -> Result<Vec<i32>, ()> {
     let l = [1, 2, 3, 4];
-    l.iter().map(f).collect()? //~ ERROR type annotations needed
+    l.iter().map(f).collect()?
+    //~^ ERROR type annotations needed
 }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-71584.rs b/src/test/ui/issues/issue-71584.rs
index c96cd598f0c..7bf3ed60ec1 100644
--- a/src/test/ui/issues/issue-71584.rs
+++ b/src/test/ui/issues/issue-71584.rs
@@ -1,5 +1,6 @@
 fn main() {
     let n: u32 = 1;
     let mut d: u64 = 2;
-    d = d % n.into(); //~ ERROR type annotations needed
+    d = d % n.into();
+    //~^ ERROR type annotations needed
 }
diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr
index e210f11b3e0..b6a04585583 100644
--- a/src/test/ui/traits/issue-77982.stderr
+++ b/src/test/ui/traits/issue-77982.stderr
@@ -46,12 +46,7 @@ LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect(
    |                                            |
    |                                            required by a bound introduced by this call
    |
-   = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
-           - impl From<Ipv4Addr> for u32;
-           - impl From<NonZeroU32> for u32;
-           - impl From<bool> for u32;
-           - impl From<char> for u32;
-           and 3 more
+   = note: cannot satisfy `u32: From<_>`
 help: try using a fully qualified path to specify the expected types
    |
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(<u32 as Into<T>>::into(0u32))).collect();