Skip to content

Commit 87de9bd

Browse files
committed
Prevent auto-application of associated functions with placeholders
1 parent 371100b commit 87de9bd

File tree

1 file changed

+34
-17
lines changed

1 file changed

+34
-17
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
1818
use rustc_middle::traits::util::supertraits;
1919
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
2020
use rustc_middle::ty::print::with_crate_prefix;
21-
use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
21+
use rustc_middle::ty::{self, DefIdTree, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable};
2222
use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
2323
use rustc_span::symbol::{kw, sym, Ident};
2424
use rustc_span::Symbol;
@@ -392,28 +392,45 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
392392
custom_span_label = true;
393393
}
394394
if static_candidates.len() == 1 {
395-
let ty_str =
396-
if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
397-
// When the "method" is resolved through dereferencing, we really want the
398-
// original type that has the associated function for accurate suggestions.
399-
// (#61411)
400-
let ty = tcx.at(span).type_of(*impl_did);
401-
match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
402-
(ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
403-
// Use `actual` as it will have more `substs` filled in.
404-
self.ty_to_value_string(actual.peel_refs())
405-
}
406-
_ => self.ty_to_value_string(ty.peel_refs()),
395+
let (ty_str, placeholders) = if let Some(CandidateSource::Impl(impl_did)) =
396+
static_candidates.get(0)
397+
{
398+
// When the "method" is resolved through dereferencing, we really want the
399+
// original type that has the associated function for accurate suggestions.
400+
// (#61411)
401+
let ty = tcx.at(span).type_of(*impl_did);
402+
match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
403+
(ty::Adt(def, _), ty::Adt(def_actual, substs)) if def == def_actual => {
404+
// If there are any inferred arguments, (`{integer}`), we shouldn't mark
405+
// this as machine-applicable.
406+
let placeholders = substs
407+
.iter()
408+
.filter_map(|arg| {
409+
if let GenericArgKind::Type(ty) = arg.unpack() {
410+
Some(ty)
411+
} else {
412+
None
413+
}
414+
})
415+
.any(|ty| matches!(ty.kind(), ty::Infer(_)));
416+
// Use `actual` as it will have more `substs` filled in.
417+
(self.ty_to_value_string(actual.peel_refs()), placeholders)
407418
}
408-
} else {
409-
self.ty_to_value_string(actual.peel_refs())
410-
};
419+
_ => (self.ty_to_value_string(ty.peel_refs()), true),
420+
}
421+
} else {
422+
(self.ty_to_value_string(actual.peel_refs()), true)
423+
};
424+
let applicability = match placeholders {
425+
true => Applicability::HasPlaceholders,
426+
false => Applicability::MachineApplicable,
427+
};
411428
if let SelfSource::MethodCall(expr) = source {
412429
err.span_suggestion(
413430
expr.span.to(span),
414431
"use associated function syntax instead",
415432
format!("{}::{}", ty_str, item_name),
416-
Applicability::MachineApplicable,
433+
applicability,
417434
);
418435
} else {
419436
err.help(&format!("try with `{}::{}`", ty_str, item_name,));

0 commit comments

Comments
 (0)