about summary refs log tree commit diff
diff options
context:
space:
mode:
authorclubby789 <jamie@hill-daniel.co.uk>2022-09-19 00:53:41 +0100
committerclubby789 <jamie@hill-daniel.co.uk>2022-11-05 22:56:19 +0000
commita3b5ca7b6d8a1aa42544f5bb1b854f357678e612 (patch)
tree6a340bac6e934405f3a0d81236db5ab341a58528
parent87de9bd1088ec0f1a2e8893a517cde2005a546a0 (diff)
downloadrust-a3b5ca7b6d8a1aa42544f5bb1b854f357678e612.tar.gz
rust-a3b5ca7b6d8a1aa42544f5bb1b854f357678e612.zip
Allow inferring generic arguments for associated methods
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs62
1 files changed, 40 insertions, 22 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 613acd3d705..85c003ff605 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -14,7 +14,11 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{ExprKind, Node, QPath};
-use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::{
+    type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
+    RegionVariableOrigin,
+};
+use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
 use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::with_crate_prefix;
@@ -392,7 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     custom_span_label = true;
                 }
                 if static_candidates.len() == 1 {
-                    let (ty_str, placeholders) = if let Some(CandidateSource::Impl(impl_did)) =
+                    let ty_str = if let Some(CandidateSource::Impl(impl_did)) =
                     static_candidates.get(0)
                     {
                         // When the "method" is resolved through dereferencing, we really want the
@@ -401,36 +405,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         let ty = tcx.at(span).type_of(*impl_did);
                         match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
                             (ty::Adt(def, _), ty::Adt(def_actual, substs)) if def == def_actual => {
-                                // If there are any inferred arguments, (`{integer}`), we shouldn't mark
-                                // this as machine-applicable.
-                                let placeholders = substs
-                                    .iter()
-                                    .filter_map(|arg| {
-                                        if let GenericArgKind::Type(ty) = arg.unpack() {
-                                            Some(ty)
-                                        } else {
-                                            None
-                                        }
+                                // If there are any inferred arguments, (`{integer}`), we should replace
+                                // them with underscores to allow the compiler to infer them
+                                let substs = substs
+                                    .into_iter()
+                                    .filter(|arg| !arg.is_suggestable(tcx, true))
+                                    .map(|arg| match arg.unpack() {
+                                        GenericArgKind::Lifetime(_) => self
+                                            .next_region_var(RegionVariableOrigin::MiscVariable(
+                                                rustc_span::DUMMY_SP,
+                                            ))
+                                            .into(),
+                                        GenericArgKind::Type(_) => self
+                                            .next_ty_var(TypeVariableOrigin {
+                                                span: rustc_span::DUMMY_SP,
+                                                kind: TypeVariableOriginKind::MiscVariable,
+                                            })
+                                            .into(),
+                                        GenericArgKind::Const(arg) => self
+                                            .next_const_var(
+                                                arg.ty(),
+                                                ConstVariableOrigin {
+                                                    span: rustc_span::DUMMY_SP,
+                                                    kind: ConstVariableOriginKind::MiscVariable,
+                                                },
+                                            )
+                                            .into(),
                                     })
-                                    .any(|ty| matches!(ty.kind(), ty::Infer(_)));
-                                // Use `actual` as it will have more `substs` filled in.
-                                (self.ty_to_value_string(actual.peel_refs()), placeholders)
+                                    .collect::<Vec<_>>();
+                                format!(
+                                    "{}",
+                                    ty::Instance::new(def_actual.did(), tcx.intern_substs(&substs))
+                                )
                             }
-                            _ => (self.ty_to_value_string(ty.peel_refs()), true),
+                            _ => self.ty_to_value_string(ty.peel_refs()),
                         }
                     } else {
-                        (self.ty_to_value_string(actual.peel_refs()), true)
-                    };
-                    let applicability = match placeholders {
-                        true => Applicability::HasPlaceholders,
-                        false => Applicability::MachineApplicable,
+                        self.ty_to_value_string(actual.peel_refs())
                     };
                     if let SelfSource::MethodCall(expr) = source {
                         err.span_suggestion(
                             expr.span.to(span),
                             "use associated function syntax instead",
                             format!("{}::{}", ty_str, item_name),
-                            applicability,
+                            Applicability::MachineApplicable,
                         );
                     } else {
                         err.help(&format!("try with `{}::{}`", ty_str, item_name,));