diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index e74ffeff343a..1113f7f70953 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -798,13 +798,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`") } }; + + self.register_wf_obligation( + ty.raw.into(), + qself.span, + ObligationCauseCode::WellFormed(None), + ); + self.select_obligations_where_possible(|_| {}); + if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id) { - self.register_wf_obligation( - ty.raw.into(), - qself.span, - ObligationCauseCode::WellFormed(None), - ); // Return directly on cache hit. This is useful to avoid doubly reporting // errors with default match binding modes. See #44614. let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id)); @@ -824,18 +827,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_missing_method = matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait(); - // If we have a path like `MyTrait::missing_method`, then don't register - // a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise, - // register a WF obligation so that we can detect any additional - // errors in the self type. - if !trait_missing_method { - self.register_wf_obligation( - ty.raw.into(), - qself.span, - ObligationCauseCode::WellFormed(None), - ); - } - if item_name.name != kw::Empty { self.report_method_error( hir_id, @@ -849,14 +840,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { result }); - if result.is_ok() { - self.register_wf_obligation( - ty.raw.into(), - qself.span, - ObligationCauseCode::WellFormed(None), - ); - } - // Write back the new resolution. self.write_resolution(hir_id, result); ( diff --git a/tests/ui/traits/next-solver/method/path_lookup_wf_constraints.rs b/tests/ui/traits/next-solver/method/path_lookup_wf_constraints.rs new file mode 100644 index 000000000000..fbe170b1990e --- /dev/null +++ b/tests/ui/traits/next-solver/method/path_lookup_wf_constraints.rs @@ -0,0 +1,39 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// A regression test for trait-system-refactor-initiative#161 + +trait Constrain { + type Assoc; +} +impl Constrain for () { + type Assoc = (); +} +struct Foo>::Assoc>(T, U); + +impl Foo { + fn foo() {} +} +struct B; +impl Foo { + fn foo() {} +} + +type Alias = Foo; +fn via_guidance() +where + (): Constrain, +{ + // Method selection on `Foo>::Assoc>` is ambiguous. + // only by unnecessarily constraining `?t` to `T` when proving `(): Constrain` + // are we able to select the first impl. + // + // This happens in the old solver when normalizing `Alias`. The new solver doesn't try + // to eagerly normalize `<() as Constrain>::Assoc` so we instead always prove that the + // self type is well-formed before method lookup. + Alias::foo(); +} + +fn main() { + via_guidance::<()>(); +}