Skip to content

Commit a3b5ca7

Browse files
committed
Allow inferring generic arguments for associated methods
1 parent 87de9bd commit a3b5ca7

File tree

1 file changed

+40
-22
lines changed

1 file changed

+40
-22
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ use rustc_hir::def::DefKind;
1414
use rustc_hir::def_id::DefId;
1515
use rustc_hir::lang_items::LangItem;
1616
use rustc_hir::{ExprKind, Node, QPath};
17-
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
17+
use rustc_infer::infer::{
18+
type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
19+
RegionVariableOrigin,
20+
};
21+
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
1822
use rustc_middle::traits::util::supertraits;
1923
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
2024
use rustc_middle::ty::print::with_crate_prefix;
@@ -392,7 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
392396
custom_span_label = true;
393397
}
394398
if static_candidates.len() == 1 {
395-
let (ty_str, placeholders) = if let Some(CandidateSource::Impl(impl_did)) =
399+
let ty_str = if let Some(CandidateSource::Impl(impl_did)) =
396400
static_candidates.get(0)
397401
{
398402
// When the "method" is resolved through dereferencing, we really want the
@@ -401,36 +405,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
401405
let ty = tcx.at(span).type_of(*impl_did);
402406
match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
403407
(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-
}
408+
// If there are any inferred arguments, (`{integer}`), we should replace
409+
// them with underscores to allow the compiler to infer them
410+
let substs = substs
411+
.into_iter()
412+
.filter(|arg| !arg.is_suggestable(tcx, true))
413+
.map(|arg| match arg.unpack() {
414+
GenericArgKind::Lifetime(_) => self
415+
.next_region_var(RegionVariableOrigin::MiscVariable(
416+
rustc_span::DUMMY_SP,
417+
))
418+
.into(),
419+
GenericArgKind::Type(_) => self
420+
.next_ty_var(TypeVariableOrigin {
421+
span: rustc_span::DUMMY_SP,
422+
kind: TypeVariableOriginKind::MiscVariable,
423+
})
424+
.into(),
425+
GenericArgKind::Const(arg) => self
426+
.next_const_var(
427+
arg.ty(),
428+
ConstVariableOrigin {
429+
span: rustc_span::DUMMY_SP,
430+
kind: ConstVariableOriginKind::MiscVariable,
431+
},
432+
)
433+
.into(),
414434
})
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)
435+
.collect::<Vec<_>>();
436+
format!(
437+
"{}",
438+
ty::Instance::new(def_actual.did(), tcx.intern_substs(&substs))
439+
)
418440
}
419-
_ => (self.ty_to_value_string(ty.peel_refs()), true),
441+
_ => self.ty_to_value_string(ty.peel_refs()),
420442
}
421443
} 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,
444+
self.ty_to_value_string(actual.peel_refs())
427445
};
428446
if let SelfSource::MethodCall(expr) = source {
429447
err.span_suggestion(
430448
expr.span.to(span),
431449
"use associated function syntax instead",
432450
format!("{}::{}", ty_str, item_name),
433-
applicability,
451+
Applicability::MachineApplicable,
434452
);
435453
} else {
436454
err.help(&format!("try with `{}::{}`", ty_str, item_name,));

0 commit comments

Comments
 (0)