Rollup merge of #123962 - oli-obk:define_opaque_types5, r=lcnr
change method resolution to constrain hidden types instead of rejecting method candidates Some of these are in probes and may affect inference. This is therefore a breaking change. This allows new code to compile on stable: ```rust trait Trait {} impl Trait for u32 {} struct Bar<T>(T); impl Bar<u32> { fn foo(self) {} } fn foo(x: bool) -> Bar<impl Sized> { if x { let x = foo(false); x.foo(); //^ this used to not find the `foo` method, because while we did equate `x`'s type with possible candidates, we didn't allow opaque type inference while doing so } todo!() } ``` r? ```````@compiler-errors``````` fixes #121404 cc https://github.com/rust-lang/rust/issues/116652
This commit is contained in:
commit
0468462538
42 changed files with 922 additions and 79 deletions
|
@ -628,7 +628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
return;
|
||||
};
|
||||
|
||||
let pick = self.confirm_method(
|
||||
let pick = self.confirm_method_for_diagnostic(
|
||||
call_expr.span,
|
||||
callee_expr,
|
||||
call_expr,
|
||||
|
|
|
@ -1418,7 +1418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
let impl_ty = self.normalize(span, tcx.type_of(impl_def_id).instantiate(tcx, args));
|
||||
let self_ty = self.normalize(span, self_ty);
|
||||
match self.at(&self.misc(span), self.param_env).eq(
|
||||
DefineOpaqueTypes::No,
|
||||
DefineOpaqueTypes::Yes,
|
||||
impl_ty,
|
||||
self_ty,
|
||||
) {
|
||||
|
|
|
@ -497,7 +497,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||
args,
|
||||
})),
|
||||
);
|
||||
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::No, method_self_ty, self_ty) {
|
||||
match self.at(&cause, self.param_env).sup(DefineOpaqueTypes::Yes, method_self_ty, self_ty) {
|
||||
Ok(InferOk { obligations, value: () }) => {
|
||||
self.register_predicates(obligations);
|
||||
}
|
||||
|
|
|
@ -634,8 +634,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_probe(&mut self, self_ty: &Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>) {
|
||||
debug!("assemble_probe: self_ty={:?}", self_ty);
|
||||
let raw_self_ty = self_ty.value.value;
|
||||
match *raw_self_ty.kind() {
|
||||
ty::Dynamic(data, ..) if let Some(p) = data.principal() => {
|
||||
|
@ -713,13 +713,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_inherent_impl_probe(&mut self, impl_def_id: DefId) {
|
||||
if !self.impl_dups.insert(impl_def_id) {
|
||||
return; // already visited
|
||||
}
|
||||
|
||||
debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
|
||||
|
||||
for item in self.impl_or_trait_item(impl_def_id) {
|
||||
if !self.has_applicable_self(&item) {
|
||||
// No receiver declared. Not a candidate.
|
||||
|
@ -737,9 +736,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_inherent_candidates_from_object(&mut self, self_ty: Ty<'tcx>) {
|
||||
debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty);
|
||||
|
||||
let principal = match self_ty.kind() {
|
||||
ty::Dynamic(ref data, ..) => Some(data),
|
||||
_ => None,
|
||||
|
@ -768,9 +766,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
});
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_inherent_candidates_from_param(&mut self, param_ty: ty::ParamTy) {
|
||||
// FIXME: do we want to commit to this behavior for param bounds?
|
||||
debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty);
|
||||
|
||||
let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
|
||||
let bound_predicate = predicate.kind();
|
||||
|
@ -826,6 +824,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_extension_candidates_for_traits_in_scope(&mut self) {
|
||||
let mut duplicates = FxHashSet::default();
|
||||
let opt_applicable_traits = self.tcx.in_scope_traits(self.scope_expr_id);
|
||||
|
@ -842,6 +841,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_extension_candidates_for_all_traits(&mut self) {
|
||||
let mut duplicates = FxHashSet::default();
|
||||
for trait_info in suggest::all_traits(self.tcx) {
|
||||
|
@ -863,12 +863,12 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn assemble_extension_candidates_for_trait(
|
||||
&mut self,
|
||||
import_ids: &SmallVec<[LocalDefId; 1]>,
|
||||
trait_def_id: DefId,
|
||||
) {
|
||||
debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id);
|
||||
let trait_args = self.fresh_args_for_item(self.span, trait_def_id);
|
||||
let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, trait_args);
|
||||
|
||||
|
@ -958,6 +958,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// THE ACTUAL SEARCH
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn pick(mut self) -> PickResult<'tcx> {
|
||||
assert!(self.method_name.is_some());
|
||||
|
||||
|
@ -1386,6 +1387,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, possibly_unsatisfied_predicates), ret)]
|
||||
fn consider_probe(
|
||||
&self,
|
||||
self_ty: Ty<'tcx>,
|
||||
|
@ -1415,15 +1417,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, impl_ty, impl_args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
|
||||
match self.at(cause, self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
xform_self_ty,
|
||||
self_ty,
|
||||
) {
|
||||
Ok(infer_ok) => {
|
||||
ocx.register_infer_ok_obligations(infer_ok);
|
||||
}
|
||||
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
|
@ -1484,19 +1479,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
|
||||
match self.at(cause, self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
xform_self_ty,
|
||||
self_ty,
|
||||
) {
|
||||
Ok(infer_ok) => {
|
||||
ocx.register_infer_ok_obligations(infer_ok);
|
||||
}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
match self_ty.kind() {
|
||||
// HACK: opaque types will match anything for which their bounds hold.
|
||||
// Thus we need to prevent them from trying to match the `&_` autoref
|
||||
// candidates that get created for `&self` trait methods.
|
||||
ty::Alias(ty::Opaque, alias_ty)
|
||||
if self.infcx.can_define_opaque_ty(alias_ty.def_id)
|
||||
&& !xform_self_ty.is_ty_var() =>
|
||||
{
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
_ => match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
}
|
||||
},
|
||||
}
|
||||
let obligation = traits::Obligation::new(
|
||||
self.tcx,
|
||||
|
@ -1536,15 +1535,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
(xform_self_ty, xform_ret_ty) =
|
||||
self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
|
||||
xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
|
||||
// FIXME: Make this `ocx.sup` once we define opaques more eagerly.
|
||||
match self.at(cause, self.param_env).sup(
|
||||
DefineOpaqueTypes::No,
|
||||
xform_self_ty,
|
||||
self_ty,
|
||||
) {
|
||||
Ok(infer_ok) => {
|
||||
ocx.register_infer_ok_obligations(infer_ok);
|
||||
}
|
||||
match ocx.sup(cause, self.param_env, xform_self_ty, self_ty) {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
debug!("--> cannot relate self-types {:?}", err);
|
||||
return ProbeResult::NoMatch;
|
||||
|
@ -1665,6 +1657,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||
/// Similarly to `probe_for_return_type`, this method attempts to find the best matching
|
||||
/// candidate method where the method name may have been misspelled. Similarly to other
|
||||
/// edit distance based suggestions, we provide at most one such suggestion.
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
pub(crate) fn probe_for_similar_candidate(
|
||||
&mut self,
|
||||
) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
|
||||
|
|
|
@ -156,7 +156,7 @@ pub struct CandidateStep<'tcx> {
|
|||
|
||||
#[derive(Copy, Clone, Debug, HashStable)]
|
||||
pub struct MethodAutoderefStepsResult<'tcx> {
|
||||
/// The valid autoderef steps that could be find.
|
||||
/// The valid autoderef steps that could be found.
|
||||
pub steps: &'tcx [CandidateStep<'tcx>],
|
||||
/// If Some(T), a type autoderef reported an error on.
|
||||
pub opt_bad_ty: Option<&'tcx MethodAutoderefBadTy<'tcx>>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue