diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index ddb582ffab0ba..e6cb28df593af 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -5,6 +5,7 @@ use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation}; use rustc_middle::ty; use rustc_span::{Span, DUMMY_SP}; +use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::ObligationCtxt; #[derive(Debug)] @@ -52,10 +53,21 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( _ => return false, } - let impl_predicates = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_args); - ocx.register_obligations(impl_predicates.predicates.iter().map(|&predicate| { - Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) - })); + let obligations = tcx + .predicates_of(impl_def_id) + .instantiate(tcx, impl_args) + .into_iter() + .map(|(predicate, _)| { + Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) + }) + // Kinda hacky, but let's just throw away obligations that overflow. + // This may reduce the accuracy of this check (if the obligation guides + // inference or it actually resulted in error after others are processed) + // ... but this is diagnostics code. + .filter(|obligation| { + infcx.next_trait_solver() || infcx.evaluate_obligation(obligation).is_ok() + }); + ocx.register_obligations(obligations); ocx.select_where_possible().is_empty() }) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 144971b63c0ad..33fc1d0d3316e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2398,12 +2398,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if ambiguities.len() > 5 { let infcx = self.infcx; if !ambiguities.iter().all(|option| match option { - DefId(did) => infcx.fresh_args_for_item(DUMMY_SP, *did).is_empty(), + DefId(did) => infcx.tcx.generics_of(*did).count() == 0, ParamEnv(_) => true, }) { // If not all are blanket impls, we filter blanked impls out. ambiguities.retain(|option| match option { - DefId(did) => infcx.fresh_args_for_item(DUMMY_SP, *did).is_empty(), + DefId(did) => infcx.tcx.generics_of(*did).count() == 0, ParamEnv(_) => true, }); } diff --git a/tests/ui/traits/overflow-computing-ambiguity.rs b/tests/ui/traits/overflow-computing-ambiguity.rs new file mode 100644 index 0000000000000..b8f11efeda283 --- /dev/null +++ b/tests/ui/traits/overflow-computing-ambiguity.rs @@ -0,0 +1,14 @@ +trait Hello {} + +struct Foo<'a, T: ?Sized>(&'a T); + +impl<'a, T: ?Sized> Hello for Foo<'a, &'a T> where Foo<'a, T>: Hello {} + +impl Hello for Foo<'static, i32> {} + +fn hello() {} + +fn main() { + hello(); + //~^ ERROR type annotations needed +} diff --git a/tests/ui/traits/overflow-computing-ambiguity.stderr b/tests/ui/traits/overflow-computing-ambiguity.stderr new file mode 100644 index 0000000000000..a2e255865bf48 --- /dev/null +++ b/tests/ui/traits/overflow-computing-ambiguity.stderr @@ -0,0 +1,23 @@ +error[E0283]: type annotations needed + --> $DIR/overflow-computing-ambiguity.rs:12:5 + | +LL | hello(); + | ^^^^^ cannot infer type of the type parameter `T` declared on the function `hello` + | + = note: cannot satisfy `_: Hello` + = help: the following types implement trait `Hello`: + Foo<'a, &'a T> + Foo<'static, i32> +note: required by a bound in `hello` + --> $DIR/overflow-computing-ambiguity.rs:9:22 + | +LL | fn hello() {} + | ^^^^^ required by this bound in `hello` +help: consider specifying the generic argument + | +LL | hello::(); + | +++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`.