diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 161f5e981d430..a7444b45ab0f2 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -2,6 +2,7 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] #![feature(array_windows)] +#![feature(assert_matches)] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_intersperse)] diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 6090c0f9aee22..725240b480ba9 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1,3 +1,4 @@ +use std::assert_matches::debug_assert_matches; use std::cell::{Cell, RefCell}; use std::cmp::max; use std::ops::Deref; @@ -16,7 +17,7 @@ use rustc_infer::traits::ObligationCauseCode; use rustc_middle::middle::stability; use rustc_middle::query::Providers; use rustc_middle::ty::elaborate::supertrait_def_ids; -use rustc_middle::ty::fast_reject::{TreatParams, simplify_type}; +use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type}; use rustc_middle::ty::{ self, AssocItem, AssocItemContainer, GenericArgs, GenericArgsRef, GenericParamDefKind, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt, Upcast, @@ -807,8 +808,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ); } } - ty::Param(p) => { - self.assemble_inherent_candidates_from_param(p); + ty::Param(_) => { + self.assemble_inherent_candidates_from_param(raw_self_ty); } ty::Bool | ty::Char @@ -909,18 +910,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } #[instrument(level = "debug", skip(self))] - fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) { + fn assemble_inherent_candidates_from_param(&mut self, param_ty: Ty<'tcx>) { + debug_assert_matches!(param_ty.kind(), ty::Param(_)); + + let tcx = self.tcx; let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| { let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { - ty::ClauseKind::Trait(trait_predicate) => { - match *trait_predicate.trait_ref.self_ty().kind() { - ty::Param(p) if p == param_ty => { - Some(bound_predicate.rebind(trait_predicate.trait_ref)) - } - _ => None, - } - } + ty::ClauseKind::Trait(trait_predicate) => DeepRejectCtxt::relate_rigid_rigid(tcx) + .types_may_unify(param_ty, trait_predicate.trait_ref.self_ty()) + .then(|| bound_predicate.rebind(trait_predicate.trait_ref)), ty::ClauseKind::RegionOutlives(_) | ty::ClauseKind::TypeOutlives(_) | ty::ClauseKind::Projection(_) diff --git a/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env-2.rs b/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env-2.rs new file mode 100644 index 0000000000000..ffb99d6d63855 --- /dev/null +++ b/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env-2.rs @@ -0,0 +1,29 @@ +//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Regression test for . +// See comment below. + +trait A { + fn hello(&self) {} +} + +trait B { + fn hello(&self) {} +} + +impl A for T {} +impl B for T {} + +fn test(q: F::Item) +where + F: Iterator, + // We want to prefer `A` for `R.hello()` + F::Item: A, +{ + q.hello(); +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env.rs b/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env.rs new file mode 100644 index 0000000000000..dde4f745879e4 --- /dev/null +++ b/tests/ui/traits/next-solver/method/param-method-from-unnormalized-param-env.rs @@ -0,0 +1,17 @@ +//@ check-pass +//@ compile-flags: -Znext-solver + +// Regression test for . + +fn execute(q: F::Item) -> R +where + F: Iterator, + // Both of the below bounds should be considered for `.into()`, and then be combined + // into a single `R: Into` bound which can be inferred to `?0 = R`. + F::Item: Into, + R: Into, +{ + q.into() +} + +fn main() {}