Skip to content

Commit 465e7d5

Browse files
Rework receiver_is_valid
1 parent fb8d5f1 commit 465e7d5

File tree

1 file changed

+42
-50
lines changed

1 file changed

+42
-50
lines changed

Diff for: compiler/rustc_hir_analysis/src/check/wfcheck.rs

+42-50
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use rustc_session::parse::feature_err;
2929
use rustc_span::symbol::{sym, Ident};
3030
use rustc_span::{Span, DUMMY_SP};
3131
use rustc_target::spec::abi::Abi;
32-
use rustc_trait_selection::infer::InferCtxtExt;
3332
use rustc_trait_selection::regions::InferCtxtRegionExt;
3433
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
3534
use rustc_trait_selection::traits::misc::{
@@ -40,6 +39,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
4039
use rustc_trait_selection::traits::{
4140
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
4241
};
42+
use rustc_type_ir::solve::NoSolution;
4343
use rustc_type_ir::TypeFlags;
4444

4545
use std::cell::LazyCell;
@@ -1713,13 +1713,12 @@ fn receiver_is_valid<'tcx>(
17131713
let cause =
17141714
ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
17151715

1716-
let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty);
1717-
1718-
// `self: Self` is always valid.
1719-
if can_eq_self(receiver_ty) {
1720-
if let Err(err) = wfcx.eq(&cause, wfcx.param_env, self_ty, receiver_ty) {
1721-
infcx.err_ctxt().report_mismatched_types(&cause, self_ty, receiver_ty, err).emit();
1722-
}
1716+
// Special case `receiver == self_ty`, which doesn't necessarily require the `Receiver` lang item.
1717+
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
1718+
let ocx = ObligationCtxt::new(wfcx.infcx);
1719+
ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
1720+
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
1721+
}) {
17231722
return true;
17241723
}
17251724

@@ -1730,58 +1729,51 @@ fn receiver_is_valid<'tcx>(
17301729
autoderef = autoderef.include_raw_pointers();
17311730
}
17321731

1733-
// The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
1734-
autoderef.next();
1735-
17361732
let receiver_trait_def_id = tcx.require_lang_item(LangItem::Receiver, Some(span));
17371733

17381734
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
1739-
loop {
1740-
if let Some((potential_self_ty, _)) = autoderef.next() {
1741-
debug!(
1742-
"receiver_is_valid: potential self type `{:?}` to match `{:?}`",
1743-
potential_self_ty, self_ty
1744-
);
1745-
1746-
if can_eq_self(potential_self_ty) {
1747-
wfcx.register_obligations(autoderef.into_obligations());
1735+
while let Some((potential_self_ty, _)) = autoderef.next() {
1736+
debug!(
1737+
"receiver_is_valid: potential self type `{:?}` to match `{:?}`",
1738+
potential_self_ty, self_ty
1739+
);
17481740

1749-
if let Err(err) = wfcx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty) {
1750-
infcx
1751-
.err_ctxt()
1752-
.report_mismatched_types(&cause, self_ty, potential_self_ty, err)
1753-
.emit();
1754-
}
1741+
// Check if the self type unifies. If it does, then commit the result
1742+
// since it may have region side-effects.
1743+
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
1744+
let ocx = ObligationCtxt::new(wfcx.infcx);
1745+
ocx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty)?;
1746+
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
1747+
}) {
1748+
wfcx.register_obligations(autoderef.into_obligations());
1749+
return true;
1750+
}
17551751

1752+
// Without `feature(arbitrary_self_types)`, we require that each step in the
1753+
// deref chain implement `receiver`.
1754+
if !arbitrary_self_types_enabled {
1755+
if !receiver_is_implemented(
1756+
wfcx,
1757+
receiver_trait_def_id,
1758+
cause.clone(),
1759+
potential_self_ty,
1760+
) {
1761+
// We cannot proceed.
17561762
break;
1757-
} else {
1758-
// Without `feature(arbitrary_self_types)`, we require that each step in the
1759-
// deref chain implement `receiver`
1760-
if !arbitrary_self_types_enabled
1761-
&& !receiver_is_implemented(
1762-
wfcx,
1763-
receiver_trait_def_id,
1764-
cause.clone(),
1765-
potential_self_ty,
1766-
)
1767-
{
1768-
return false;
1769-
}
17701763
}
1771-
} else {
1772-
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
1773-
return false;
1774-
}
1775-
}
17761764

1777-
// Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
1778-
if !arbitrary_self_types_enabled
1779-
&& !receiver_is_implemented(wfcx, receiver_trait_def_id, cause.clone(), receiver_ty)
1780-
{
1781-
return false;
1765+
// Register the bound, in case it has any region side-effects.
1766+
wfcx.register_bound(
1767+
cause.clone(),
1768+
wfcx.param_env,
1769+
potential_self_ty,
1770+
receiver_trait_def_id,
1771+
);
1772+
}
17821773
}
17831774

1784-
true
1775+
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
1776+
false
17851777
}
17861778

17871779
fn receiver_is_implemented<'tcx>(

0 commit comments

Comments
 (0)