eagerly prove WF when resolving fully qualified paths
This commit is contained in:
parent
c241e14650
commit
81c6d5ec9b
2 changed files with 47 additions and 25 deletions
|
@ -798,13 +798,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
bug!("`resolve_ty_and_res_fully_qualified_call` called on `LangItem`")
|
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)
|
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
|
// Return directly on cache hit. This is useful to avoid doubly reporting
|
||||||
// errors with default match binding modes. See #44614.
|
// errors with default match binding modes. See #44614.
|
||||||
let def = cached_result.map_or(Res::Err, |(kind, def_id)| Res::Def(kind, def_id));
|
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 =
|
let trait_missing_method =
|
||||||
matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
|
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 {
|
if item_name.name != kw::Empty {
|
||||||
self.report_method_error(
|
self.report_method_error(
|
||||||
hir_id,
|
hir_id,
|
||||||
|
@ -849,14 +840,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
result
|
result
|
||||||
});
|
});
|
||||||
|
|
||||||
if result.is_ok() {
|
|
||||||
self.register_wf_obligation(
|
|
||||||
ty.raw.into(),
|
|
||||||
qself.span,
|
|
||||||
ObligationCauseCode::WellFormed(None),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write back the new resolution.
|
// Write back the new resolution.
|
||||||
self.write_resolution(hir_id, result);
|
self.write_resolution(hir_id, result);
|
||||||
(
|
(
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
//@ compile-flags: -Znext-solver
|
||||||
|
//@ check-pass
|
||||||
|
|
||||||
|
// A regression test for trait-system-refactor-initiative#161
|
||||||
|
|
||||||
|
trait Constrain<T> {
|
||||||
|
type Assoc;
|
||||||
|
}
|
||||||
|
impl<T> Constrain<T> for () {
|
||||||
|
type Assoc = ();
|
||||||
|
}
|
||||||
|
struct Foo<T, U = <() as Constrain<T>>::Assoc>(T, U);
|
||||||
|
|
||||||
|
impl<T: Copy> Foo<T> {
|
||||||
|
fn foo() {}
|
||||||
|
}
|
||||||
|
struct B;
|
||||||
|
impl Foo<B> {
|
||||||
|
fn foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Alias<T> = Foo<T>;
|
||||||
|
fn via_guidance<T: Copy>()
|
||||||
|
where
|
||||||
|
(): Constrain<T>,
|
||||||
|
{
|
||||||
|
// Method selection on `Foo<?t, <() as Constrain<?t>>::Assoc>` is ambiguous.
|
||||||
|
// only by unnecessarily constraining `?t` to `T` when proving `(): Constrain<?t>`
|
||||||
|
// are we able to select the first impl.
|
||||||
|
//
|
||||||
|
// This happens in the old solver when normalizing `Alias<?t>`. The new solver doesn't try
|
||||||
|
// to eagerly normalize `<() as Constrain<?t>>::Assoc` so we instead always prove that the
|
||||||
|
// self type is well-formed before method lookup.
|
||||||
|
Alias::foo();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
via_guidance::<()>();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue