Rollup merge of #104394 - oli-obk:suggest_method_call, r=lcnr
various cleanups to try to reduce the use of spans inside method resolution definitely review commit by commit.
This commit is contained in:
commit
163a7090b8
@ -504,7 +504,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// method lookup.
|
// method lookup.
|
||||||
let Ok(pick) = self
|
let Ok(pick) = self
|
||||||
.probe_for_name(
|
.probe_for_name(
|
||||||
call_expr.span,
|
|
||||||
Mode::MethodCall,
|
Mode::MethodCall,
|
||||||
segment.ident,
|
segment.ident,
|
||||||
IsSuggestion(true),
|
IsSuggestion(true),
|
||||||
|
@ -93,17 +93,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
call_expr_id: hir::HirId,
|
call_expr_id: hir::HirId,
|
||||||
allow_private: bool,
|
allow_private: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mode = probe::Mode::MethodCall;
|
|
||||||
match self.probe_for_name(
|
match self.probe_for_name(
|
||||||
method_name.span,
|
probe::Mode::MethodCall,
|
||||||
mode,
|
|
||||||
method_name,
|
method_name,
|
||||||
IsSuggestion(false),
|
IsSuggestion(false),
|
||||||
self_ty,
|
self_ty,
|
||||||
call_expr_id,
|
call_expr_id,
|
||||||
ProbeScope::TraitsInScope,
|
ProbeScope::TraitsInScope,
|
||||||
) {
|
) {
|
||||||
Ok(..) => true,
|
Ok(pick) => {
|
||||||
|
pick.maybe_emit_unstable_name_collision_hint(
|
||||||
|
self.tcx,
|
||||||
|
method_name.span,
|
||||||
|
call_expr_id,
|
||||||
|
);
|
||||||
|
true
|
||||||
|
}
|
||||||
Err(NoMatch(..)) => false,
|
Err(NoMatch(..)) => false,
|
||||||
Err(Ambiguity(..)) => true,
|
Err(Ambiguity(..)) => true,
|
||||||
Err(PrivateMatch(..)) => allow_private,
|
Err(PrivateMatch(..)) => allow_private,
|
||||||
@ -125,10 +130,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
) {
|
) {
|
||||||
let params = self
|
let params = self
|
||||||
.probe_for_name(
|
.probe_for_name(
|
||||||
method_name.span,
|
|
||||||
probe::Mode::MethodCall,
|
probe::Mode::MethodCall,
|
||||||
method_name,
|
method_name,
|
||||||
IsSuggestion(false),
|
IsSuggestion(true),
|
||||||
self_ty,
|
self_ty,
|
||||||
call_expr.hir_id,
|
call_expr.hir_id,
|
||||||
ProbeScope::TraitsInScope,
|
ProbeScope::TraitsInScope,
|
||||||
@ -175,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
args: &'tcx [hir::Expr<'tcx>],
|
args: &'tcx [hir::Expr<'tcx>],
|
||||||
) -> Result<MethodCallee<'tcx>, MethodError<'tcx>> {
|
) -> Result<MethodCallee<'tcx>, MethodError<'tcx>> {
|
||||||
let pick =
|
let pick =
|
||||||
self.lookup_probe(span, segment.ident, self_ty, call_expr, ProbeScope::TraitsInScope)?;
|
self.lookup_probe(segment.ident, self_ty, call_expr, ProbeScope::TraitsInScope)?;
|
||||||
|
|
||||||
self.lint_dot_call_from_2018(self_ty, segment, span, call_expr, self_expr, &pick, args);
|
self.lint_dot_call_from_2018(self_ty, segment, span, call_expr, self_expr, &pick, args);
|
||||||
|
|
||||||
@ -200,13 +204,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.mk_ref(*region, ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() });
|
.mk_ref(*region, ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() });
|
||||||
// We probe again to see if there might be a borrow mutability discrepancy.
|
// We probe again to see if there might be a borrow mutability discrepancy.
|
||||||
match self.lookup_probe(
|
match self.lookup_probe(
|
||||||
span,
|
|
||||||
segment.ident,
|
segment.ident,
|
||||||
trait_type,
|
trait_type,
|
||||||
call_expr,
|
call_expr,
|
||||||
ProbeScope::TraitsInScope,
|
ProbeScope::TraitsInScope,
|
||||||
) {
|
) {
|
||||||
Ok(ref new_pick) if *new_pick != pick => {
|
Ok(ref new_pick) if pick.differs_from(new_pick) => {
|
||||||
needs_mut = true;
|
needs_mut = true;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@ -214,15 +217,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We probe again, taking all traits into account (not only those in scope).
|
// We probe again, taking all traits into account (not only those in scope).
|
||||||
let mut candidates = match self.lookup_probe(
|
let mut candidates =
|
||||||
span,
|
match self.lookup_probe(segment.ident, self_ty, call_expr, ProbeScope::AllTraits) {
|
||||||
segment.ident,
|
|
||||||
self_ty,
|
|
||||||
call_expr,
|
|
||||||
ProbeScope::AllTraits,
|
|
||||||
) {
|
|
||||||
// If we find a different result the caller probably forgot to import a trait.
|
// If we find a different result the caller probably forgot to import a trait.
|
||||||
Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container_id(self.tcx)],
|
Ok(ref new_pick) if pick.differs_from(new_pick) => {
|
||||||
|
vec![new_pick.item.container_id(self.tcx)]
|
||||||
|
}
|
||||||
Err(Ambiguity(ref sources)) => sources
|
Err(Ambiguity(ref sources)) => sources
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|source| {
|
.filter_map(|source| {
|
||||||
@ -247,23 +247,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
#[instrument(level = "debug", skip(self, call_expr))]
|
#[instrument(level = "debug", skip(self, call_expr))]
|
||||||
pub fn lookup_probe(
|
pub fn lookup_probe(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
|
||||||
method_name: Ident,
|
method_name: Ident,
|
||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
call_expr: &'tcx hir::Expr<'tcx>,
|
call_expr: &'tcx hir::Expr<'tcx>,
|
||||||
scope: ProbeScope,
|
scope: ProbeScope,
|
||||||
) -> probe::PickResult<'tcx> {
|
) -> probe::PickResult<'tcx> {
|
||||||
let mode = probe::Mode::MethodCall;
|
let pick = self.probe_for_name(
|
||||||
let self_ty = self.resolve_vars_if_possible(self_ty);
|
probe::Mode::MethodCall,
|
||||||
self.probe_for_name(
|
|
||||||
span,
|
|
||||||
mode,
|
|
||||||
method_name,
|
method_name,
|
||||||
IsSuggestion(false),
|
IsSuggestion(false),
|
||||||
self_ty,
|
self_ty,
|
||||||
call_expr.hir_id,
|
call_expr.hir_id,
|
||||||
scope,
|
scope,
|
||||||
)
|
)?;
|
||||||
|
pick.maybe_emit_unstable_name_collision_hint(self.tcx, method_name.span, call_expr.hir_id);
|
||||||
|
Ok(pick)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn obligation_for_method(
|
pub(super) fn obligation_for_method(
|
||||||
@ -587,7 +585,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let pick = self.probe_for_name(
|
let pick = self.probe_for_name(
|
||||||
span,
|
|
||||||
probe::Mode::Path,
|
probe::Mode::Path,
|
||||||
method_name,
|
method_name,
|
||||||
IsSuggestion(false),
|
IsSuggestion(false),
|
||||||
@ -596,6 +593,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
ProbeScope::TraitsInScope,
|
ProbeScope::TraitsInScope,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
pick.maybe_emit_unstable_name_collision_hint(self.tcx, span, expr_id);
|
||||||
|
|
||||||
self.lint_fully_qualified_call_from_2018(
|
self.lint_fully_qualified_call_from_2018(
|
||||||
span,
|
span,
|
||||||
method_name,
|
method_name,
|
||||||
|
@ -17,6 +17,7 @@ use rustc_infer::infer::{self, InferOk, TyCtxtInferExt};
|
|||||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||||
use rustc_middle::middle::stability;
|
use rustc_middle::middle::stability;
|
||||||
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
|
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
|
||||||
|
use rustc_middle::ty::AssocItem;
|
||||||
use rustc_middle::ty::GenericParamDefKind;
|
use rustc_middle::ty::GenericParamDefKind;
|
||||||
use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable};
|
use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable};
|
||||||
use rustc_middle::ty::{InternalSubsts, SubstsRef};
|
use rustc_middle::ty::{InternalSubsts, SubstsRef};
|
||||||
@ -83,8 +84,6 @@ struct ProbeContext<'a, 'tcx> {
|
|||||||
unsatisfied_predicates:
|
unsatisfied_predicates:
|
||||||
Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>,
|
Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>, Option<ObligationCause<'tcx>>)>,
|
||||||
|
|
||||||
is_suggestion: IsSuggestion,
|
|
||||||
|
|
||||||
scope_expr_id: hir::HirId,
|
scope_expr_id: hir::HirId,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +192,7 @@ impl AutorefOrPtrAdjustment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Pick<'tcx> {
|
pub struct Pick<'tcx> {
|
||||||
pub item: ty::AssocItem,
|
pub item: ty::AssocItem,
|
||||||
pub kind: PickKind<'tcx>,
|
pub kind: PickKind<'tcx>,
|
||||||
@ -209,6 +208,9 @@ pub struct Pick<'tcx> {
|
|||||||
/// `*mut T`, convert it to `*const T`.
|
/// `*mut T`, convert it to `*const T`.
|
||||||
pub autoref_or_ptr_adjustment: Option<AutorefOrPtrAdjustment>,
|
pub autoref_or_ptr_adjustment: Option<AutorefOrPtrAdjustment>,
|
||||||
pub self_ty: Ty<'tcx>,
|
pub self_ty: Ty<'tcx>,
|
||||||
|
|
||||||
|
/// Unstable candidates alongside the stable ones.
|
||||||
|
unstable_candidates: Vec<(Candidate<'tcx>, Symbol)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
@ -298,7 +300,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub fn probe_for_name(
|
pub fn probe_for_name(
|
||||||
&self,
|
&self,
|
||||||
span: Span,
|
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
item_name: Ident,
|
item_name: Ident,
|
||||||
is_suggestion: IsSuggestion,
|
is_suggestion: IsSuggestion,
|
||||||
@ -307,7 +308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
scope: ProbeScope,
|
scope: ProbeScope,
|
||||||
) -> PickResult<'tcx> {
|
) -> PickResult<'tcx> {
|
||||||
self.probe_op(
|
self.probe_op(
|
||||||
span,
|
item_name.span,
|
||||||
mode,
|
mode,
|
||||||
Some(item_name),
|
Some(item_name),
|
||||||
None,
|
None,
|
||||||
@ -446,7 +447,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
return_type,
|
return_type,
|
||||||
orig_values,
|
orig_values,
|
||||||
steps.steps,
|
steps.steps,
|
||||||
is_suggestion,
|
|
||||||
scope_expr_id,
|
scope_expr_id,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -541,7 +541,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
return_type: Option<Ty<'tcx>>,
|
return_type: Option<Ty<'tcx>>,
|
||||||
orig_steps_var_values: OriginalQueryValues<'tcx>,
|
orig_steps_var_values: OriginalQueryValues<'tcx>,
|
||||||
steps: &'tcx [CandidateStep<'tcx>],
|
steps: &'tcx [CandidateStep<'tcx>],
|
||||||
is_suggestion: IsSuggestion,
|
|
||||||
scope_expr_id: hir::HirId,
|
scope_expr_id: hir::HirId,
|
||||||
) -> ProbeContext<'a, 'tcx> {
|
) -> ProbeContext<'a, 'tcx> {
|
||||||
ProbeContext {
|
ProbeContext {
|
||||||
@ -559,7 +558,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
allow_similar_names: false,
|
allow_similar_names: false,
|
||||||
private_candidate: None,
|
private_candidate: None,
|
||||||
unsatisfied_predicates: Vec::new(),
|
unsatisfied_predicates: Vec::new(),
|
||||||
is_suggestion,
|
|
||||||
scope_expr_id,
|
scope_expr_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -881,7 +879,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn matches_return_type(
|
fn matches_return_type(
|
||||||
&self,
|
&self,
|
||||||
method: &ty::AssocItem,
|
method: &ty::AssocItem,
|
||||||
self_ty: Option<Ty<'tcx>>,
|
self_ty: Option<Ty<'tcx>>,
|
||||||
@ -1052,27 +1050,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
|
fn pick_core(&mut self) -> Option<PickResult<'tcx>> {
|
||||||
let mut unstable_candidates = Vec::new();
|
let pick = self.pick_all_method(Some(&mut vec![]));
|
||||||
let pick = self.pick_all_method(Some(&mut unstable_candidates));
|
|
||||||
|
|
||||||
// In this case unstable picking is done by `pick_method`.
|
// In this case unstable picking is done by `pick_method`.
|
||||||
if !self.tcx.sess.opts.unstable_opts.pick_stable_methods_before_any_unstable {
|
if !self.tcx.sess.opts.unstable_opts.pick_stable_methods_before_any_unstable {
|
||||||
return pick;
|
return pick;
|
||||||
}
|
}
|
||||||
|
|
||||||
match pick {
|
if pick.is_none() {
|
||||||
// Emit a lint if there are unstable candidates alongside the stable ones.
|
return self.pick_all_method(None);
|
||||||
//
|
}
|
||||||
// We suppress warning if we're picking the method only because it is a
|
|
||||||
// suggestion.
|
|
||||||
Some(Ok(ref p)) if !self.is_suggestion.0 && !unstable_candidates.is_empty() => {
|
|
||||||
self.emit_unstable_name_collision_hint(p, &unstable_candidates);
|
|
||||||
pick
|
pick
|
||||||
}
|
}
|
||||||
Some(_) => pick,
|
|
||||||
None => self.pick_all_method(None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pick_all_method(
|
fn pick_all_method(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -1216,7 +1205,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
debug!("pick_method_with_unstable(self_ty={})", self.ty_to_string(self_ty));
|
debug!("pick_method_with_unstable(self_ty={})", self.ty_to_string(self_ty));
|
||||||
|
|
||||||
let mut possibly_unsatisfied_predicates = Vec::new();
|
let mut possibly_unsatisfied_predicates = Vec::new();
|
||||||
let mut unstable_candidates = Vec::new();
|
|
||||||
|
|
||||||
for (kind, candidates) in
|
for (kind, candidates) in
|
||||||
&[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
|
&[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)]
|
||||||
@ -1226,26 +1214,17 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
self_ty,
|
self_ty,
|
||||||
candidates.iter(),
|
candidates.iter(),
|
||||||
&mut possibly_unsatisfied_predicates,
|
&mut possibly_unsatisfied_predicates,
|
||||||
Some(&mut unstable_candidates),
|
Some(&mut vec![]),
|
||||||
);
|
);
|
||||||
if let Some(pick) = res {
|
if res.is_some() {
|
||||||
if !self.is_suggestion.0 && !unstable_candidates.is_empty() {
|
return res;
|
||||||
if let Ok(p) = &pick {
|
|
||||||
// Emit a lint if there are unstable candidates alongside the stable ones.
|
|
||||||
//
|
|
||||||
// We suppress warning if we're picking the method only because it is a
|
|
||||||
// suggestion.
|
|
||||||
self.emit_unstable_name_collision_hint(p, &unstable_candidates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Some(pick);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("searching unstable candidates");
|
debug!("searching unstable candidates");
|
||||||
let res = self.consider_candidates(
|
let res = self.consider_candidates(
|
||||||
self_ty,
|
self_ty,
|
||||||
unstable_candidates.iter().map(|(c, _)| c),
|
self.inherent_candidates.iter().chain(&self.extension_candidates),
|
||||||
&mut possibly_unsatisfied_predicates,
|
&mut possibly_unsatisfied_predicates,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
@ -1300,7 +1279,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
Option<ty::Predicate<'tcx>>,
|
Option<ty::Predicate<'tcx>>,
|
||||||
Option<ObligationCause<'tcx>>,
|
Option<ObligationCause<'tcx>>,
|
||||||
)>,
|
)>,
|
||||||
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
|
mut unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
|
||||||
) -> Option<PickResult<'tcx>>
|
) -> Option<PickResult<'tcx>>
|
||||||
where
|
where
|
||||||
ProbesIter: Iterator<Item = &'b Candidate<'tcx>> + Clone,
|
ProbesIter: Iterator<Item = &'b Candidate<'tcx>> + Clone,
|
||||||
@ -1324,7 +1303,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(uc) = unstable_candidates {
|
if let Some(uc) = &mut unstable_candidates {
|
||||||
applicable_candidates.retain(|&(p, _)| {
|
applicable_candidates.retain(|&(p, _)| {
|
||||||
if let stability::EvalResult::Deny { feature, .. } =
|
if let stability::EvalResult::Deny { feature, .. } =
|
||||||
self.tcx.eval_stability(p.item.def_id, None, self.span, None)
|
self.tcx.eval_stability(p.item.def_id, None, self.span, None)
|
||||||
@ -1343,30 +1322,63 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
|
|
||||||
applicable_candidates.pop().map(|(probe, status)| {
|
applicable_candidates.pop().map(|(probe, status)| {
|
||||||
if status == ProbeResult::Match {
|
if status == ProbeResult::Match {
|
||||||
Ok(probe.to_unadjusted_pick(self_ty))
|
Ok(probe
|
||||||
|
.to_unadjusted_pick(self_ty, unstable_candidates.cloned().unwrap_or_default()))
|
||||||
} else {
|
} else {
|
||||||
Err(MethodError::BadReturnType)
|
Err(MethodError::BadReturnType)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_unstable_name_collision_hint(
|
impl<'tcx> Pick<'tcx> {
|
||||||
|
/// In case there were unstable name collisions, emit them as a lint.
|
||||||
|
/// Checks whether two picks do not refer to the same trait item for the same `Self` type.
|
||||||
|
/// Only useful for comparisons of picks in order to improve diagnostics.
|
||||||
|
/// Do not use for type checking.
|
||||||
|
pub fn differs_from(&self, other: &Self) -> bool {
|
||||||
|
let Self {
|
||||||
|
item:
|
||||||
|
AssocItem {
|
||||||
|
def_id,
|
||||||
|
name: _,
|
||||||
|
kind: _,
|
||||||
|
container: _,
|
||||||
|
trait_item_def_id: _,
|
||||||
|
fn_has_self_parameter: _,
|
||||||
|
},
|
||||||
|
kind: _,
|
||||||
|
import_ids: _,
|
||||||
|
autoderefs: _,
|
||||||
|
autoref_or_ptr_adjustment: _,
|
||||||
|
self_ty,
|
||||||
|
unstable_candidates: _,
|
||||||
|
} = *self;
|
||||||
|
self_ty != other.self_ty || def_id != other.item.def_id
|
||||||
|
}
|
||||||
|
|
||||||
|
/// In case there were unstable name collisions, emit them as a lint.
|
||||||
|
pub fn maybe_emit_unstable_name_collision_hint(
|
||||||
&self,
|
&self,
|
||||||
stable_pick: &Pick<'_>,
|
tcx: TyCtxt<'tcx>,
|
||||||
unstable_candidates: &[(Candidate<'tcx>, Symbol)],
|
span: Span,
|
||||||
|
scope_expr_id: hir::HirId,
|
||||||
) {
|
) {
|
||||||
let def_kind = stable_pick.item.kind.as_def_kind();
|
if self.unstable_candidates.is_empty() {
|
||||||
self.tcx.struct_span_lint_hir(
|
return;
|
||||||
|
}
|
||||||
|
let def_kind = self.item.kind.as_def_kind();
|
||||||
|
tcx.struct_span_lint_hir(
|
||||||
lint::builtin::UNSTABLE_NAME_COLLISIONS,
|
lint::builtin::UNSTABLE_NAME_COLLISIONS,
|
||||||
self.scope_expr_id,
|
scope_expr_id,
|
||||||
self.span,
|
span,
|
||||||
format!(
|
format!(
|
||||||
"{} {} with this name may be added to the standard library in the future",
|
"{} {} with this name may be added to the standard library in the future",
|
||||||
def_kind.article(),
|
def_kind.article(),
|
||||||
def_kind.descr(stable_pick.item.def_id),
|
def_kind.descr(self.item.def_id),
|
||||||
),
|
),
|
||||||
|lint| {
|
|lint| {
|
||||||
match (stable_pick.item.kind, stable_pick.item.container) {
|
match (self.item.kind, self.item.container) {
|
||||||
(ty::AssocKind::Fn, _) => {
|
(ty::AssocKind::Fn, _) => {
|
||||||
// FIXME: This should be a `span_suggestion` instead of `help`
|
// FIXME: This should be a `span_suggestion` instead of `help`
|
||||||
// However `self.span` only
|
// However `self.span` only
|
||||||
@ -1375,31 +1387,31 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
lint.help(&format!(
|
lint.help(&format!(
|
||||||
"call with fully qualified syntax `{}(...)` to keep using the current \
|
"call with fully qualified syntax `{}(...)` to keep using the current \
|
||||||
method",
|
method",
|
||||||
self.tcx.def_path_str(stable_pick.item.def_id),
|
tcx.def_path_str(self.item.def_id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
(ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => {
|
(ty::AssocKind::Const, ty::AssocItemContainer::TraitContainer) => {
|
||||||
let def_id = stable_pick.item.container_id(self.tcx);
|
let def_id = self.item.container_id(tcx);
|
||||||
lint.span_suggestion(
|
lint.span_suggestion(
|
||||||
self.span,
|
span,
|
||||||
"use the fully qualified path to the associated const",
|
"use the fully qualified path to the associated const",
|
||||||
format!(
|
format!(
|
||||||
"<{} as {}>::{}",
|
"<{} as {}>::{}",
|
||||||
stable_pick.self_ty,
|
self.self_ty,
|
||||||
self.tcx.def_path_str(def_id),
|
tcx.def_path_str(def_id),
|
||||||
stable_pick.item.name
|
self.item.name
|
||||||
),
|
),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if self.tcx.sess.is_nightly_build() {
|
if tcx.sess.is_nightly_build() {
|
||||||
for (candidate, feature) in unstable_candidates {
|
for (candidate, feature) in &self.unstable_candidates {
|
||||||
lint.help(&format!(
|
lint.help(&format!(
|
||||||
"add `#![feature({})]` to the crate attributes to enable `{}`",
|
"add `#![feature({})]` to the crate attributes to enable `{}`",
|
||||||
feature,
|
feature,
|
||||||
self.tcx.def_path_str(candidate.item.def_id),
|
tcx.def_path_str(candidate.item.def_id),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1408,7 +1420,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
fn select_trait_candidate(
|
fn select_trait_candidate(
|
||||||
&self,
|
&self,
|
||||||
trait_ref: ty::TraitRef<'tcx>,
|
trait_ref: ty::TraitRef<'tcx>,
|
||||||
@ -1667,6 +1681,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
autoderefs: 0,
|
autoderefs: 0,
|
||||||
autoref_or_ptr_adjustment: None,
|
autoref_or_ptr_adjustment: None,
|
||||||
self_ty,
|
self_ty,
|
||||||
|
unstable_candidates: vec![],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1686,7 +1701,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
self.return_type,
|
self.return_type,
|
||||||
self.orig_steps_var_values.clone(),
|
self.orig_steps_var_values.clone(),
|
||||||
steps,
|
steps,
|
||||||
IsSuggestion(true),
|
|
||||||
self.scope_expr_id,
|
self.scope_expr_id,
|
||||||
);
|
);
|
||||||
pcx.allow_similar_names = true;
|
pcx.allow_similar_names = true;
|
||||||
@ -1894,7 +1908,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Candidate<'tcx> {
|
impl<'tcx> Candidate<'tcx> {
|
||||||
fn to_unadjusted_pick(&self, self_ty: Ty<'tcx>) -> Pick<'tcx> {
|
fn to_unadjusted_pick(
|
||||||
|
&self,
|
||||||
|
self_ty: Ty<'tcx>,
|
||||||
|
unstable_candidates: Vec<(Candidate<'tcx>, Symbol)>,
|
||||||
|
) -> Pick<'tcx> {
|
||||||
Pick {
|
Pick {
|
||||||
item: self.item,
|
item: self.item,
|
||||||
kind: match self.kind {
|
kind: match self.kind {
|
||||||
@ -1919,6 +1937,7 @@ impl<'tcx> Candidate<'tcx> {
|
|||||||
autoderefs: 0,
|
autoderefs: 0,
|
||||||
autoref_or_ptr_adjustment: None,
|
autoref_or_ptr_adjustment: None,
|
||||||
self_ty,
|
self_ty,
|
||||||
|
unstable_candidates,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -376,7 +376,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
.hir()
|
.hir()
|
||||||
.expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
|
.expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id));
|
||||||
let probe = self.lookup_probe(
|
let probe = self.lookup_probe(
|
||||||
span,
|
|
||||||
item_name,
|
item_name,
|
||||||
output_ty,
|
output_ty,
|
||||||
call_expr,
|
call_expr,
|
||||||
@ -914,7 +913,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.check_for_inner_self(&mut err, source, span, rcvr_ty, item_name);
|
self.check_for_inner_self(&mut err, source, rcvr_ty, item_name);
|
||||||
|
|
||||||
bound_spans.sort();
|
bound_spans.sort();
|
||||||
bound_spans.dedup();
|
bound_spans.dedup();
|
||||||
@ -1321,7 +1320,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
|
self.tcx.bound_type_of(range_def_id).subst(self.tcx, &[actual.into()]);
|
||||||
|
|
||||||
let pick = self.probe_for_name(
|
let pick = self.probe_for_name(
|
||||||
span,
|
|
||||||
Mode::MethodCall,
|
Mode::MethodCall,
|
||||||
item_name,
|
item_name,
|
||||||
IsSuggestion(true),
|
IsSuggestion(true),
|
||||||
@ -1500,7 +1498,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
span,
|
span,
|
||||||
&|_, field_ty| {
|
&|_, field_ty| {
|
||||||
self.lookup_probe(
|
self.lookup_probe(
|
||||||
span,
|
|
||||||
item_name,
|
item_name,
|
||||||
field_ty,
|
field_ty,
|
||||||
call_expr,
|
call_expr,
|
||||||
@ -1548,7 +1545,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&self,
|
&self,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
source: SelfSource<'tcx>,
|
source: SelfSource<'tcx>,
|
||||||
span: Span,
|
|
||||||
actual: Ty<'tcx>,
|
actual: Ty<'tcx>,
|
||||||
item_name: Ident,
|
item_name: Ident,
|
||||||
) {
|
) {
|
||||||
@ -1571,13 +1567,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.lookup_probe(
|
self.lookup_probe(item_name, field_ty, call_expr, ProbeScope::TraitsInScope)
|
||||||
span,
|
|
||||||
item_name,
|
|
||||||
field_ty,
|
|
||||||
call_expr,
|
|
||||||
ProbeScope::TraitsInScope,
|
|
||||||
)
|
|
||||||
.ok()
|
.ok()
|
||||||
.map(|pick| (variant, field, pick))
|
.map(|pick| (variant, field, pick))
|
||||||
})
|
})
|
||||||
@ -1644,7 +1634,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let [first] = ***substs else { return; };
|
let [first] = ***substs else { return; };
|
||||||
let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
|
let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
|
||||||
let Ok(pick) = self.lookup_probe(
|
let Ok(pick) = self.lookup_probe(
|
||||||
span,
|
|
||||||
item_name,
|
item_name,
|
||||||
ty,
|
ty,
|
||||||
call_expr,
|
call_expr,
|
||||||
@ -1899,7 +1888,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let SelfSource::QPath(ty) = self_source else { return; };
|
let SelfSource::QPath(ty) = self_source else { return; };
|
||||||
for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
|
for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
|
||||||
if let Ok(pick) = self.probe_for_name(
|
if let Ok(pick) = self.probe_for_name(
|
||||||
ty.span,
|
|
||||||
Mode::Path,
|
Mode::Path,
|
||||||
item_name,
|
item_name,
|
||||||
IsSuggestion(true),
|
IsSuggestion(true),
|
||||||
@ -2107,7 +2095,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
(self.tcx.mk_mut_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&mut "),
|
(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), "&"),
|
(self.tcx.mk_imm_ref(self.tcx.lifetimes.re_erased, rcvr_ty), "&"),
|
||||||
] {
|
] {
|
||||||
match self.lookup_probe(span, item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
|
match self.lookup_probe(item_name, *rcvr_ty, rcvr, ProbeScope::AllTraits) {
|
||||||
Ok(pick) => {
|
Ok(pick) => {
|
||||||
// If the method is defined for the receiver we have, it likely wasn't `use`d.
|
// If the method is defined for the receiver we have, it likely wasn't `use`d.
|
||||||
// We point at the method, but we just skip the rest of the check for arbitrary
|
// We point at the method, but we just skip the rest of the check for arbitrary
|
||||||
@ -2141,7 +2129,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
] {
|
] {
|
||||||
if let Some(new_rcvr_t) = *rcvr_ty
|
if let Some(new_rcvr_t) = *rcvr_ty
|
||||||
&& let Ok(pick) = self.lookup_probe(
|
&& let Ok(pick) = self.lookup_probe(
|
||||||
span,
|
|
||||||
item_name,
|
item_name,
|
||||||
new_rcvr_t,
|
new_rcvr_t,
|
||||||
rcvr,
|
rcvr,
|
||||||
@ -2522,7 +2509,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
span: method_name.span,
|
span: method_name.span,
|
||||||
};
|
};
|
||||||
let probe = self.lookup_probe(
|
let probe = self.lookup_probe(
|
||||||
expr.span,
|
|
||||||
new_name,
|
new_name,
|
||||||
self_ty,
|
self_ty,
|
||||||
self_expr,
|
self_expr,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user