Auto merge of #127172 - compiler-errors:full-can_eq-everywhere, r=lcnr
Make `can_eq` process obligations (almost) everywhere Move `can_eq` to an extension trait on `InferCtxt` in `rustc_trait_selection`, and change it so that it processes obligations. This should strengthen it to be more accurate in some cases, but is most important for the new trait solver which delays relating aliases to `AliasRelate` goals. Without this, we always basically just return true when passing aliases to `can_eq`, which can lead to weird errors, for example #127149. I'm not actually certain if we should *have* `can_eq` be called on the good path. In cases where we need `can_eq`, we probably should just be using a regular probe. Fixes #127149 r? lcnr
This commit is contained in:
commit
89aefb9c53
30 changed files with 133 additions and 154 deletions
|
@ -21,6 +21,7 @@ use rustc_middle::ty::{
|
|||
use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
|
|
|
@ -39,6 +39,7 @@ use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _
|
|||
use rustc_trait_selection::traits::{
|
||||
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
|
||||
};
|
||||
use rustc_type_ir::solve::NoSolution;
|
||||
use rustc_type_ir::TypeFlags;
|
||||
|
||||
use std::cell::LazyCell;
|
||||
|
@ -1712,13 +1713,12 @@ fn receiver_is_valid<'tcx>(
|
|||
let cause =
|
||||
ObligationCause::new(span, wfcx.body_def_id, traits::ObligationCauseCode::MethodReceiver);
|
||||
|
||||
let can_eq_self = |ty| infcx.can_eq(wfcx.param_env, self_ty, ty);
|
||||
|
||||
// `self: Self` is always valid.
|
||||
if can_eq_self(receiver_ty) {
|
||||
if let Err(err) = wfcx.eq(&cause, wfcx.param_env, self_ty, receiver_ty) {
|
||||
infcx.err_ctxt().report_mismatched_types(&cause, self_ty, receiver_ty, err).emit();
|
||||
}
|
||||
// Special case `receiver == self_ty`, which doesn't necessarily require the `Receiver` lang item.
|
||||
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
|
||||
let ocx = ObligationCtxt::new(wfcx.infcx);
|
||||
ocx.eq(&cause, wfcx.param_env, self_ty, receiver_ty)?;
|
||||
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
|
||||
}) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1729,58 +1729,51 @@ fn receiver_is_valid<'tcx>(
|
|||
autoderef = autoderef.include_raw_pointers();
|
||||
}
|
||||
|
||||
// The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
|
||||
autoderef.next();
|
||||
|
||||
let receiver_trait_def_id = tcx.require_lang_item(LangItem::Receiver, Some(span));
|
||||
|
||||
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
|
||||
loop {
|
||||
if let Some((potential_self_ty, _)) = autoderef.next() {
|
||||
debug!(
|
||||
"receiver_is_valid: potential self type `{:?}` to match `{:?}`",
|
||||
potential_self_ty, self_ty
|
||||
);
|
||||
while let Some((potential_self_ty, _)) = autoderef.next() {
|
||||
debug!(
|
||||
"receiver_is_valid: potential self type `{:?}` to match `{:?}`",
|
||||
potential_self_ty, self_ty
|
||||
);
|
||||
|
||||
if can_eq_self(potential_self_ty) {
|
||||
wfcx.register_obligations(autoderef.into_obligations());
|
||||
|
||||
if let Err(err) = wfcx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty) {
|
||||
infcx
|
||||
.err_ctxt()
|
||||
.report_mismatched_types(&cause, self_ty, potential_self_ty, err)
|
||||
.emit();
|
||||
}
|
||||
// Check if the self type unifies. If it does, then commit the result
|
||||
// since it may have region side-effects.
|
||||
if let Ok(()) = wfcx.infcx.commit_if_ok(|_| {
|
||||
let ocx = ObligationCtxt::new(wfcx.infcx);
|
||||
ocx.eq(&cause, wfcx.param_env, self_ty, potential_self_ty)?;
|
||||
if ocx.select_all_or_error().is_empty() { Ok(()) } else { Err(NoSolution) }
|
||||
}) {
|
||||
wfcx.register_obligations(autoderef.into_obligations());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Without `feature(arbitrary_self_types)`, we require that each step in the
|
||||
// deref chain implement `receiver`.
|
||||
if !arbitrary_self_types_enabled {
|
||||
if !receiver_is_implemented(
|
||||
wfcx,
|
||||
receiver_trait_def_id,
|
||||
cause.clone(),
|
||||
potential_self_ty,
|
||||
) {
|
||||
// We cannot proceed.
|
||||
break;
|
||||
} else {
|
||||
// Without `feature(arbitrary_self_types)`, we require that each step in the
|
||||
// deref chain implement `receiver`
|
||||
if !arbitrary_self_types_enabled
|
||||
&& !receiver_is_implemented(
|
||||
wfcx,
|
||||
receiver_trait_def_id,
|
||||
cause.clone(),
|
||||
potential_self_ty,
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
|
||||
return false;
|
||||
|
||||
// Register the bound, in case it has any region side-effects.
|
||||
wfcx.register_bound(
|
||||
cause.clone(),
|
||||
wfcx.param_env,
|
||||
potential_self_ty,
|
||||
receiver_trait_def_id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Without `feature(arbitrary_self_types)`, we require that `receiver_ty` implements `Receiver`.
|
||||
if !arbitrary_self_types_enabled
|
||||
&& !receiver_is_implemented(wfcx, receiver_trait_def_id, cause.clone(), receiver_ty)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
|
||||
false
|
||||
}
|
||||
|
||||
fn receiver_is_implemented<'tcx>(
|
||||
|
|
|
@ -49,6 +49,7 @@ use rustc_span::edit_distance::find_best_match_for_name;
|
|||
use rustc_span::symbol::{kw, Ident, Symbol};
|
||||
use rustc_span::{sym, Span, DUMMY_SP};
|
||||
use rustc_target::spec::abi;
|
||||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::wf::object_region_bounds;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue