From f1551bfc02845eb198a71cc5c0264bd71e336274 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 19 Oct 2022 17:17:19 +0200 Subject: [PATCH 1/3] selection failure: recompute applicable impls --- compiler/rustc_middle/src/traits/mod.rs | 3 -- compiler/rustc_middle/src/ty/mod.rs | 8 +-- .../src/traits/chalk_fulfill.rs | 15 +++++- .../src/traits/engine.rs | 17 +++--- .../src/traits/error_reporting/ambiguity.rs | 52 +++++++++++++++++++ .../src/traits/error_reporting/mod.rs | 38 +++++++------- .../src/traits/select/candidate_assembly.rs | 12 +---- .../src/traits/select/mod.rs | 4 -- src/test/ui/error-codes/E0282.rs | 3 +- src/test/ui/error-codes/E0401.rs | 4 +- src/test/ui/error-codes/E0401.stderr | 27 ++++++++-- .../impl-trait/cross-return-site-inference.rs | 9 ++-- .../cross-return-site-inference.stderr | 4 +- src/test/ui/inference/cannot-infer-async.rs | 3 +- src/test/ui/inference/cannot-infer-closure.rs | 3 +- src/test/ui/inference/issue-71732.rs | 3 +- src/test/ui/inference/issue-72616.rs | 3 +- src/test/ui/inference/issue-72616.stderr | 18 ++++++- .../ui/inference/question-mark-type-infer.rs | 3 +- src/test/ui/issues/issue-71584.rs | 3 +- src/test/ui/traits/issue-77982.stderr | 7 +-- 21 files changed, 166 insertions(+), 73 deletions(-) create mode 100644 compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index a29f0722ff705..05382bd887cd9 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), } /// 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 27090c62d21ed..b509ae6dd3b85 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 { - 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 { + 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 81e1d64493e14..d32a990f182dc 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>, relationships: FxHashMap, + + 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> { - 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 21516c93efb53..0eafc49816d49 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 { 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>( @@ -144,6 +141,10 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { } } + pub fn select_where_possible(&self) -> Vec> { + self.engine.borrow_mut().select_where_possible(self.infcx) + } + pub fn select_all_or_error(&self) -> Vec> { 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 0000000000000..58da54afb75b9 --- /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 { + 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 c7dee4a18ac5d..bcb00796cbaba 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,8 +2136,21 @@ 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.cancel(); + return; + } + err.note(&format!("cannot satisfy `{}`", predicate)); + } } _ => { if self.is_tainted_by_errors() { @@ -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::>().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::>().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 4c5bc333961dc..3671a0d87df57 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 84be1ced520fe..2954a2c163f40 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 9bd16abb7bb83..f1f93b3aed615 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 c30e5f4718871..8f8d6b87ef209 100644 --- a/src/test/ui/error-codes/E0401.rs +++ b/src/test/ui/error-codes/E0401.rs @@ -8,7 +8,9 @@ fn foo(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 b0e2ef5b6f7e3..9687eca61fab0 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 Iterator for A { | ---- `Self` type implicitly declared here, by this `impl` @@ -43,7 +43,28 @@ help: consider specifying the generic arguments LL | bfnr::(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 Fn for &F + where A: Tuple, F: Fn, F: ?Sized; + - impl Fn for Box + where Args: Tuple, F: Fn, A: Allocator, F: ?Sized; +note: required by a bound in `bfnr` + --> $DIR/E0401.rs:4:30 + | +LL | fn bfnr, W: Fn()>(y: T) { + | ^^^^ required by this bound in `bfnr` +help: consider specifying the type arguments in the function call + | +LL | bfnr::(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 d881af9ed8fe1..00aed2ad95a28 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 1ff777e65037c..766614e9e50ff 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 e7fabd0ffbc8b..b5152d04f6959 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 1c350b18f5a6f..bd5d10b417342 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 30063a0957c74..8a9d2b235f0e4 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) -> 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 5e5a3babfe020..7b0f5936d84ec 100644 --- a/src/test/ui/inference/issue-72616.rs +++ b/src/test/ui/inference/issue-72616.rs @@ -18,7 +18,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 a71ce9a8ef27a..da1a7ccdee15e 100644 --- a/src/test/ui/inference/issue-72616.stderr +++ b/src/test/ui/inference/issue-72616.stderr @@ -16,6 +16,22 @@ help: try using a fully qualified path to specify the expected types LL | if String::from("a") == <&str as TryInto>::try_into("a").unwrap() {} | +++++++++++++++++++++++++++++++ ~ -error: aborting due to previous error +error[E0283]: type annotations needed + --> $DIR/issue-72616.rs:20: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 TryFrom for T + where U: Into; + = 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>::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 64333a29313b3..10560f85ed480 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 { fn g() -> Result, ()> { 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 c96cd598f0ce0..7bf3ed60ec104 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 e210f11b3e0c1..b6a04585583c9 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 for u32; - - impl From for u32; - - impl From for u32; - - impl From 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(>::into(0u32))).collect(); From 003ed76e41e9b8247d2b2fc040da76969e86d4a6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 31 Oct 2022 10:27:51 +0100 Subject: [PATCH 2/3] delay errors as bug --- .../rustc_trait_selection/src/traits/error_reporting/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 bcb00796cbaba..0f5d05afcf809 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2146,7 +2146,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.annotate_source_of_ambiguity(&mut err, &impls, predicate); } else { if self.is_tainted_by_errors() { - err.cancel(); + err.delay_as_bug(); return; } err.note(&format!("cannot satisfy `{}`", predicate)); @@ -2154,7 +2154,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } _ => { if self.is_tainted_by_errors() { - err.cancel(); + err.delay_as_bug(); return; } err.note(&format!("cannot satisfy `{}`", predicate)); From 91d5a32bc59c50af762928da5a02b024b36c1891 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 8 Nov 2022 14:16:49 +0100 Subject: [PATCH 3/3] ignore wasm in test --- src/test/ui/inference/issue-72616.rs | 2 ++ src/test/ui/inference/issue-72616.stderr | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/ui/inference/issue-72616.rs b/src/test/ui/inference/issue-72616.rs index 7b0f5936d84ec..69ade1a7515cb 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 diff --git a/src/test/ui/inference/issue-72616.stderr b/src/test/ui/inference/issue-72616.stderr index da1a7ccdee15e..6ee0626cab857 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() {} | -- ^^^^^^^^ @@ -17,7 +17,7 @@ LL | if String::from("a") == <&str as TryInto>::try_into("a").unwrap( | +++++++++++++++++++++++++++++++ ~ 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() {} | ^^^^^^^^