mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-09 13:33:43 +00:00
Add lookup_probe_for_diagnostic
This commit is contained in:
parent
38491c6579
commit
2600d6245b
@ -1,4 +1,4 @@
|
||||
use super::method::probe::{IsSuggestion, Mode, ProbeScope};
|
||||
use super::method::probe::ProbeScope;
|
||||
use super::method::MethodCallee;
|
||||
use super::{Expectation, FnCtxt, TupleArgumentsFlag};
|
||||
|
||||
@ -496,16 +496,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// any strange errors. If it's successful, then we'll do a true
|
||||
// method lookup.
|
||||
let Ok(pick) = self
|
||||
.probe_for_name(
|
||||
Mode::MethodCall,
|
||||
.lookup_probe_for_diagnostic(
|
||||
segment.ident,
|
||||
expected.only_has_type(self),
|
||||
IsSuggestion(true),
|
||||
callee_ty,
|
||||
call_expr.hir_id,
|
||||
call_expr,
|
||||
// We didn't record the in scope traits during late resolution
|
||||
// so we need to probe AllTraits unfortunately
|
||||
ProbeScope::AllTraits,
|
||||
expected.only_has_type(self),
|
||||
) else {
|
||||
return None;
|
||||
};
|
||||
|
@ -303,11 +303,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// Get the evaluated type *after* calling the method call, so that the influence
|
||||
// of the arguments can be reflected in the receiver type. The receiver
|
||||
// expression has the type *before* theis analysis is done.
|
||||
let ty = match self.lookup_probe(
|
||||
let ty = match self.lookup_probe_for_diagnostic(
|
||||
segment.ident,
|
||||
rcvr_ty,
|
||||
expr,
|
||||
probe::ProbeScope::TraitsInScope,
|
||||
None,
|
||||
) {
|
||||
Ok(pick) => pick.self_ty,
|
||||
Err(_) => rcvr_ty,
|
||||
@ -557,14 +558,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else { return; };
|
||||
|
||||
let Ok(pick) = self
|
||||
.probe_for_name(
|
||||
probe::Mode::MethodCall,
|
||||
.lookup_probe_for_diagnostic(
|
||||
path.ident,
|
||||
None,
|
||||
probe::IsSuggestion(true),
|
||||
self_ty,
|
||||
deref.hir_id,
|
||||
deref,
|
||||
probe::ProbeScope::TraitsInScope,
|
||||
None,
|
||||
) else {
|
||||
return;
|
||||
};
|
||||
@ -1835,7 +1834,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn check_for_range_as_method_call(
|
||||
&self,
|
||||
err: &mut Diagnostic,
|
||||
expr: &hir::Expr<'_>,
|
||||
expr: &hir::Expr<'tcx>,
|
||||
checked_ty: Ty<'tcx>,
|
||||
expected_ty: Ty<'tcx>,
|
||||
) {
|
||||
@ -1876,14 +1875,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = method_name.kind else { return; };
|
||||
let [hir::PathSegment { ident, .. }] = p.segments else { return; };
|
||||
let self_ty = self.typeck_results.borrow().expr_ty(start.expr);
|
||||
let Ok(_pick) = self.probe_for_name(
|
||||
probe::Mode::MethodCall,
|
||||
let Ok(_pick) = self.lookup_probe_for_diagnostic(
|
||||
*ident,
|
||||
expectation,
|
||||
probe::IsSuggestion(true),
|
||||
self_ty,
|
||||
expr.hir_id,
|
||||
expr,
|
||||
probe::ProbeScope::AllTraits,
|
||||
expectation,
|
||||
) else { return; };
|
||||
let mut sugg = ".";
|
||||
let mut span = start.expr.span.between(end.expr.span);
|
||||
|
@ -2431,7 +2431,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
fn ban_private_field_access(
|
||||
&self,
|
||||
expr: &hir::Expr<'_>,
|
||||
expr: &hir::Expr<'tcx>,
|
||||
expr_t: Ty<'tcx>,
|
||||
field: Ident,
|
||||
base_did: DefId,
|
||||
@ -2462,7 +2462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
err.emit();
|
||||
}
|
||||
|
||||
fn ban_take_value_of_method(&self, expr: &hir::Expr<'_>, expr_t: Ty<'tcx>, field: Ident) {
|
||||
fn ban_take_value_of_method(&self, expr: &hir::Expr<'tcx>, expr_t: Ty<'tcx>, field: Ident) {
|
||||
let mut err = type_error_struct!(
|
||||
self.tcx().sess,
|
||||
field.span,
|
||||
|
@ -132,18 +132,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
msg: &str,
|
||||
method_name: Ident,
|
||||
self_ty: Ty<'tcx>,
|
||||
call_expr: &hir::Expr<'_>,
|
||||
call_expr: &hir::Expr<'tcx>,
|
||||
span: Option<Span>,
|
||||
) {
|
||||
let params = self
|
||||
.probe_for_name(
|
||||
probe::Mode::MethodCall,
|
||||
.lookup_probe_for_diagnostic(
|
||||
method_name,
|
||||
None,
|
||||
IsSuggestion(true),
|
||||
self_ty,
|
||||
call_expr.hir_id,
|
||||
call_expr,
|
||||
ProbeScope::TraitsInScope,
|
||||
None,
|
||||
)
|
||||
.map(|pick| {
|
||||
let sig = self.tcx.fn_sig(pick.item.def_id);
|
||||
@ -224,25 +222,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
|
||||
// We probe again, taking all traits into account (not only those in scope).
|
||||
let candidates =
|
||||
match self.lookup_probe(segment.ident, self_ty, call_expr, ProbeScope::AllTraits) {
|
||||
// If we find a different result the caller probably forgot to import a trait.
|
||||
Ok(ref new_pick) if pick.differs_from(new_pick) => {
|
||||
vec![new_pick.item.container_id(self.tcx)]
|
||||
}
|
||||
Err(Ambiguity(ref sources)) => sources
|
||||
.iter()
|
||||
.filter_map(|source| {
|
||||
match *source {
|
||||
// Note: this cannot come from an inherent impl,
|
||||
// because the first probing succeeded.
|
||||
CandidateSource::Impl(def) => self.tcx.trait_id_of_impl(def),
|
||||
CandidateSource::Trait(_) => None,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
let candidates = match self.lookup_probe_for_diagnostic(
|
||||
segment.ident,
|
||||
self_ty,
|
||||
call_expr,
|
||||
ProbeScope::AllTraits,
|
||||
None,
|
||||
) {
|
||||
// If we find a different result the caller probably forgot to import a trait.
|
||||
Ok(ref new_pick) if pick.differs_from(new_pick) => {
|
||||
vec![new_pick.item.container_id(self.tcx)]
|
||||
}
|
||||
Err(Ambiguity(ref sources)) => sources
|
||||
.iter()
|
||||
.filter_map(|source| {
|
||||
match *source {
|
||||
// Note: this cannot come from an inherent impl,
|
||||
// because the first probing succeeded.
|
||||
CandidateSource::Impl(def) => self.tcx.trait_id_of_impl(def),
|
||||
CandidateSource::Trait(_) => None,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
_ => Vec::new(),
|
||||
};
|
||||
|
||||
return Err(IllegalSizedBound { candidates, needs_mut, bound_span: span, self_expr });
|
||||
}
|
||||
@ -255,7 +258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&self,
|
||||
method_name: Ident,
|
||||
self_ty: Ty<'tcx>,
|
||||
call_expr: &'tcx hir::Expr<'tcx>,
|
||||
call_expr: &hir::Expr<'_>,
|
||||
scope: ProbeScope,
|
||||
) -> probe::PickResult<'tcx> {
|
||||
let pick = self.probe_for_name(
|
||||
@ -271,6 +274,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
Ok(pick)
|
||||
}
|
||||
|
||||
pub fn lookup_probe_for_diagnostic(
|
||||
&self,
|
||||
method_name: Ident,
|
||||
self_ty: Ty<'tcx>,
|
||||
call_expr: &hir::Expr<'_>,
|
||||
scope: ProbeScope,
|
||||
return_type: Option<Ty<'tcx>>,
|
||||
) -> probe::PickResult<'tcx> {
|
||||
let pick = self.probe_for_name(
|
||||
probe::Mode::MethodCall,
|
||||
method_name,
|
||||
return_type,
|
||||
IsSuggestion(true),
|
||||
self_ty,
|
||||
call_expr.hir_id,
|
||||
scope,
|
||||
)?;
|
||||
Ok(pick)
|
||||
}
|
||||
|
||||
pub(super) fn obligation_for_method(
|
||||
&self,
|
||||
cause: ObligationCause<'tcx>,
|
||||
|
@ -370,8 +370,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| {
|
||||
let call_expr =
|
||||
self.tcx.hir().expect_expr(self.tcx.hir().parent_id(rcvr_expr.hir_id));
|
||||
let probe =
|
||||
self.lookup_probe(item_name, output_ty, call_expr, ProbeScope::AllTraits);
|
||||
let probe = self.lookup_probe_for_diagnostic(
|
||||
item_name,
|
||||
output_ty,
|
||||
call_expr,
|
||||
ProbeScope::AllTraits,
|
||||
expected.only_has_type(self),
|
||||
);
|
||||
probe.is_ok()
|
||||
});
|
||||
}
|
||||
@ -1386,14 +1391,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let range_ty =
|
||||
self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
|
||||
|
||||
let pick = self.probe_for_name(
|
||||
Mode::MethodCall,
|
||||
let pick = self.lookup_probe_for_diagnostic(
|
||||
item_name,
|
||||
None,
|
||||
IsSuggestion(true),
|
||||
range_ty,
|
||||
expr.hir_id,
|
||||
expr,
|
||||
ProbeScope::AllTraits,
|
||||
None,
|
||||
);
|
||||
if pick.is_ok() {
|
||||
let range_span = parent_expr.span.with_hi(expr.span.hi());
|
||||
@ -1573,11 +1576,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&& let Some(expr) = visitor.result
|
||||
&& let Some(self_ty) = self.node_ty_opt(expr.hir_id)
|
||||
{
|
||||
let probe = self.lookup_probe(
|
||||
let probe = self.lookup_probe_for_diagnostic(
|
||||
seg2.ident,
|
||||
self_ty,
|
||||
call_expr,
|
||||
ProbeScope::TraitsInScope,
|
||||
None,
|
||||
);
|
||||
if probe.is_ok() {
|
||||
let sm = self.infcx.tcx.sess.source_map();
|
||||
@ -1624,14 +1628,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.check_for_nested_field_satisfying(
|
||||
span,
|
||||
&|_, field_ty| {
|
||||
self.probe_for_name(
|
||||
Mode::MethodCall,
|
||||
self.lookup_probe_for_diagnostic(
|
||||
item_name,
|
||||
return_type,
|
||||
IsSuggestion(true),
|
||||
field_ty,
|
||||
call_expr.hir_id,
|
||||
call_expr,
|
||||
ProbeScope::TraitsInScope,
|
||||
return_type,
|
||||
)
|
||||
.map_or(false, |pick| {
|
||||
!never_mention_traits
|
||||
@ -1697,9 +1699,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
return None;
|
||||
}
|
||||
|
||||
self.lookup_probe(item_name, field_ty, call_expr, ProbeScope::TraitsInScope)
|
||||
.ok()
|
||||
.map(|pick| (variant, field, pick))
|
||||
self.lookup_probe_for_diagnostic(
|
||||
item_name,
|
||||
field_ty,
|
||||
call_expr,
|
||||
ProbeScope::TraitsInScope,
|
||||
None,
|
||||
)
|
||||
.ok()
|
||||
.map(|pick| (variant, field, pick))
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -1763,11 +1771,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ty::AdtKind::Struct | ty::AdtKind::Union => {
|
||||
let [first] = ***substs else { return; };
|
||||
let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
|
||||
let Ok(pick) = self.lookup_probe(
|
||||
let Ok(pick) = self.lookup_probe_for_diagnostic(
|
||||
item_name,
|
||||
ty,
|
||||
call_expr,
|
||||
ProbeScope::TraitsInScope,
|
||||
None,
|
||||
) else { return; };
|
||||
|
||||
let name = self.ty_to_value_string(actual);
|
||||
@ -2243,14 +2252,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
(self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
|
||||
(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
|
||||
] {
|
||||
match self.probe_for_name(
|
||||
Mode::MethodCall,
|
||||
match self.lookup_probe_for_diagnostic(
|
||||
item_name,
|
||||
return_type,
|
||||
IsSuggestion(true),
|
||||
*rcvr_ty,
|
||||
rcvr.hir_id,
|
||||
rcvr,
|
||||
ProbeScope::AllTraits,
|
||||
return_type,
|
||||
) {
|
||||
Ok(pick) => {
|
||||
// If the method is defined for the receiver we have, it likely wasn't `use`d.
|
||||
@ -2284,14 +2291,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
(self.tcx.mk_diagnostic_item(*rcvr_ty, sym::Rc), "Rc::new"),
|
||||
] {
|
||||
if let Some(new_rcvr_t) = *rcvr_ty
|
||||
&& let Ok(pick) = self.probe_for_name(
|
||||
Mode::MethodCall,
|
||||
&& let Ok(pick) = self.lookup_probe_for_diagnostic(
|
||||
item_name,
|
||||
return_type,
|
||||
IsSuggestion(true),
|
||||
new_rcvr_t,
|
||||
rcvr.hir_id,
|
||||
rcvr,
|
||||
ProbeScope::AllTraits,
|
||||
return_type,
|
||||
)
|
||||
{
|
||||
debug!("try_alt_rcvr: pick candidate {:?}", pick);
|
||||
@ -2670,11 +2675,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
name: Symbol::intern(&format!("{}_else", method_name.as_str())),
|
||||
span: method_name.span,
|
||||
};
|
||||
let probe = self.lookup_probe(
|
||||
let probe = self.lookup_probe_for_diagnostic(
|
||||
new_name,
|
||||
self_ty,
|
||||
self_expr,
|
||||
ProbeScope::TraitsInScope,
|
||||
Some(expected),
|
||||
);
|
||||
|
||||
// check the method arguments number
|
||||
|
Loading…
Reference in New Issue
Block a user