Skip to content

Commit 81c6d5e

Browse files
committed
eagerly prove WF when resolving fully qualified paths
1 parent c241e14 commit 81c6d5e

File tree

2 files changed

+47
-25
lines changed

2 files changed

+47
-25
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -798,13 +798,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
798798
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
799799
}
800800
};
801+
802+
self.register_wf_obligation(
803+
ty.raw.into(),
804+
qself.span,
805+
ObligationCauseCode::WellFormed(None),
806+
);
807+
self.select_obligations_where_possible(|_| {});
808+
801809
if let Some(&cached_result) = self.typeck_results.borrow().type_dependent_defs().get(hir_id)
802810
{
803-
self.register_wf_obligation(
804-
ty.raw.into(),
805-
qself.span,
806-
ObligationCauseCode::WellFormed(None),
807-
);
808811
// Return directly on cache hit. This is useful to avoid doubly reporting
809812
// errors with default match binding modes. See #44614.
810813
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> {
824827

825828
let trait_missing_method =
826829
matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
827-
// If we have a path like `MyTrait::missing_method`, then don't register
828-
// a WF obligation for `dyn MyTrait` when method lookup fails. Otherwise,
829-
// register a WF obligation so that we can detect any additional
830-
// errors in the self type.
831-
if !trait_missing_method {
832-
self.register_wf_obligation(
833-
ty.raw.into(),
834-
qself.span,
835-
ObligationCauseCode::WellFormed(None),
836-
);
837-
}
838-
839830
if item_name.name != kw::Empty {
840831
self.report_method_error(
841832
hir_id,
@@ -849,14 +840,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
849840
result
850841
});
851842

852-
if result.is_ok() {
853-
self.register_wf_obligation(
854-
ty.raw.into(),
855-
qself.span,
856-
ObligationCauseCode::WellFormed(None),
857-
);
858-
}
859-
860843
// Write back the new resolution.
861844
self.write_resolution(hir_id, result);
862845
(
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//@ compile-flags: -Znext-solver
2+
//@ check-pass
3+
4+
// A regression test for trait-system-refactor-initiative#161
5+
6+
trait Constrain<T> {
7+
type Assoc;
8+
}
9+
impl<T> Constrain<T> for () {
10+
type Assoc = ();
11+
}
12+
struct Foo<T, U = <() as Constrain<T>>::Assoc>(T, U);
13+
14+
impl<T: Copy> Foo<T> {
15+
fn foo() {}
16+
}
17+
struct B;
18+
impl Foo<B> {
19+
fn foo() {}
20+
}
21+
22+
type Alias<T> = Foo<T>;
23+
fn via_guidance<T: Copy>()
24+
where
25+
(): Constrain<T>,
26+
{
27+
// Method selection on `Foo<?t, <() as Constrain<?t>>::Assoc>` is ambiguous.
28+
// only by unnecessarily constraining `?t` to `T` when proving `(): Constrain<?t>`
29+
// are we able to select the first impl.
30+
//
31+
// This happens in the old solver when normalizing `Alias<?t>`. The new solver doesn't try
32+
// to eagerly normalize `<() as Constrain<?t>>::Assoc` so we instead always prove that the
33+
// self type is well-formed before method lookup.
34+
Alias::foo();
35+
}
36+
37+
fn main() {
38+
via_guidance::<()>();
39+
}

0 commit comments

Comments
 (0)