about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs47
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs17
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs49
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs1
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs49
-rw-r--r--tests/crashes/130372-1.rs9
-rw-r--r--tests/crashes/130372-2.rs11
-rw-r--r--tests/crashes/130372-3.rs7
-rw-r--r--tests/ui/methods/probe-error-on-infinite-deref.rs16
-rw-r--r--tests/ui/methods/probe-error-on-infinite-deref.stderr21
-rw-r--r--tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.rs12
-rw-r--r--tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.stderr19
-rw-r--r--tests/ui/resolve/auxiliary/foreign-trait-with-assoc.rs3
-rw-r--r--tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs11
-rw-r--r--tests/ui/resolve/dont-compute-arg-names-for-non-fn.stderr14
17 files changed, 196 insertions, 94 deletions
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 3bada1de148..fca7babea30 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1049,7 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// trait or region sub-obligations. (presumably we could, but it's not
     /// particularly important for diagnostics...)
     pub(crate) fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
-        self.autoderef(DUMMY_SP, expr_ty).nth(1).and_then(|(deref_ty, _)| {
+        self.autoderef(DUMMY_SP, expr_ty).silence_errors().nth(1).and_then(|(deref_ty, _)| {
             self.infcx
                 .type_implements_trait(
                     self.tcx.lang_items().deref_mut_trait()?,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 6fd509ed32f..821a90d7a8c 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2864,13 +2864,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             (expr_t, "")
         };
         for (found_fields, args) in
-            self.get_field_candidates_considering_privacy(span, ty, mod_id, id)
+            self.get_field_candidates_considering_privacy_for_diag(span, ty, mod_id, id)
         {
             let field_names = found_fields.iter().map(|field| field.name).collect::<Vec<_>>();
             let mut candidate_fields: Vec<_> = found_fields
                 .into_iter()
                 .filter_map(|candidate_field| {
-                    self.check_for_nested_field_satisfying(
+                    self.check_for_nested_field_satisfying_condition_for_diag(
                         span,
                         &|candidate_field, _| candidate_field.ident(self.tcx()) == field,
                         candidate_field,
@@ -2933,7 +2933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         .with_span_label(field.span, "private field")
     }
 
-    pub(crate) fn get_field_candidates_considering_privacy(
+    pub(crate) fn get_field_candidates_considering_privacy_for_diag(
         &self,
         span: Span,
         base_ty: Ty<'tcx>,
@@ -2942,7 +2942,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
         debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);
 
-        self.autoderef(span, base_ty)
+        let mut autoderef = self.autoderef(span, base_ty).silence_errors();
+        let deref_chain: Vec<_> = autoderef.by_ref().collect();
+
+        // Don't probe if we hit the recursion limit, since it may result in
+        // quadratic blowup if we then try to further deref the results of this
+        // function. This is a best-effort method, after all.
+        if autoderef.reached_recursion_limit() {
+            return vec![];
+        }
+
+        deref_chain
+            .into_iter()
             .filter_map(move |(base_t, _)| {
                 match base_t.kind() {
                     ty::Adt(base_def, args) if !base_def.is_enum() => {
@@ -2975,7 +2986,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// This method is called after we have encountered a missing field error to recursively
     /// search for the field
-    pub(crate) fn check_for_nested_field_satisfying(
+    pub(crate) fn check_for_nested_field_satisfying_condition_for_diag(
         &self,
         span: Span,
         matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool,
@@ -3000,20 +3011,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if matches(candidate_field, field_ty) {
                 return Some(field_path);
             } else {
-                for (nested_fields, subst) in
-                    self.get_field_candidates_considering_privacy(span, field_ty, mod_id, hir_id)
+                for (nested_fields, subst) in self
+                    .get_field_candidates_considering_privacy_for_diag(
+                        span, field_ty, mod_id, hir_id,
+                    )
                 {
                     // recursively search fields of `candidate_field` if it's a ty::Adt
                     for field in nested_fields {
-                        if let Some(field_path) = self.check_for_nested_field_satisfying(
-                            span,
-                            matches,
-                            field,
-                            subst,
-                            field_path.clone(),
-                            mod_id,
-                            hir_id,
-                        ) {
+                        if let Some(field_path) = self
+                            .check_for_nested_field_satisfying_condition_for_diag(
+                                span,
+                                matches,
+                                field,
+                                subst,
+                                field_path.clone(),
+                                mod_id,
+                                hir_id,
+                            )
+                        {
                             return Some(field_path);
                         }
                     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 8348c6e9a16..8810f14aaa9 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -2619,9 +2619,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         is_method: bool,
     ) -> Option<Vec<(Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
         let fn_node = self.tcx.hir().get_if_local(def_id)?;
+        let fn_decl = fn_node.fn_decl()?;
 
-        let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_node
-            .fn_decl()?
+        let generic_params: Vec<Option<&hir::GenericParam<'_>>> = fn_decl
             .inputs
             .into_iter()
             .skip(if is_method { 1 } else { 0 })
@@ -2642,7 +2642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             })
             .collect();
 
-        let params: Vec<&hir::Param<'_>> = self
+        let mut params: Vec<&hir::Param<'_>> = self
             .tcx
             .hir()
             .body(fn_node.body_id()?)
@@ -2651,7 +2651,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .skip(if is_method { 1 } else { 0 })
             .collect();
 
-        Some(generic_params.into_iter().zip_eq(params).collect())
+        // The surrounding code expects variadic functions to not have a parameter representing
+        // the "..." parameter. This is already true of the FnDecl but not of the body params, so
+        // we drop it if it exists.
+
+        if fn_decl.c_variadic {
+            params.pop();
+        }
+
+        debug_assert_eq!(params.len(), generic_params.len());
+        Some(generic_params.into_iter().zip(params).collect())
     }
 }
 
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 3ba3429cbb3..5dc341653e5 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -375,7 +375,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // If our autoderef loop had reached the recursion limit,
         // report an overflow error, but continue going on with
         // the truncated autoderef list.
-        if steps.reached_recursion_limit {
+        if steps.reached_recursion_limit && !is_suggestion.0 {
             self.probe(|_| {
                 let ty = &steps
                     .steps
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 9ede809ead2..deabf693af2 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -62,14 +62,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // It might seem that we can use `predicate_must_hold_modulo_regions`,
                 // but since a Dummy binder is used to fill in the FnOnce trait's arguments,
                 // type resolution always gives a "maybe" here.
-                if self.autoderef(span, ty).any(|(ty, _)| {
+                if self.autoderef(span, ty).silence_errors().any(|(ty, _)| {
                     info!("check deref {:?} error", ty);
                     matches!(ty.kind(), ty::Error(_) | ty::Infer(_))
                 }) {
                     return false;
                 }
 
-                self.autoderef(span, ty).any(|(ty, _)| {
+                self.autoderef(span, ty).silence_errors().any(|(ty, _)| {
                     info!("check deref {:?} impl FnOnce", ty);
                     self.probe(|_| {
                         let trait_ref =
@@ -90,7 +90,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
-        self.autoderef(span, ty).any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
+        self.autoderef(span, ty)
+            .silence_errors()
+            .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
     }
 
     fn impl_into_iterator_should_be_iterator(
@@ -672,7 +674,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut ty_str_reported = ty_str.clone();
         if let ty::Adt(_, generics) = rcvr_ty.kind() {
             if generics.len() > 0 {
-                let mut autoderef = self.autoderef(span, rcvr_ty);
+                let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
                 let candidate_found = autoderef.any(|(ty, _)| {
                     if let ty::Adt(adt_def, _) = ty.kind() {
                         self.tcx
@@ -2237,6 +2239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
             let target_ty = self
                 .autoderef(sugg_span, rcvr_ty)
+                .silence_errors()
                 .find(|(rcvr_ty, _)| {
                     DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify(*rcvr_ty, impl_ty)
                 })
@@ -2352,17 +2355,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         err: &mut Diag<'_>,
     ) -> bool {
         let tcx = self.tcx;
-        let field_receiver = self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
-            ty::Adt(def, args) if !def.is_enum() => {
-                let variant = &def.non_enum_variant();
-                tcx.find_field_index(item_name, variant).map(|index| {
-                    let field = &variant.fields[index];
-                    let field_ty = field.ty(tcx, args);
-                    (field, field_ty)
-                })
-            }
-            _ => None,
-        });
+        let field_receiver =
+            self.autoderef(span, rcvr_ty).silence_errors().find_map(|(ty, _)| match ty.kind() {
+                ty::Adt(def, args) if !def.is_enum() => {
+                    let variant = &def.non_enum_variant();
+                    tcx.find_field_index(item_name, variant).map(|index| {
+                        let field = &variant.fields[index];
+                        let field_ty = field.ty(tcx, args);
+                        (field, field_ty)
+                    })
+                }
+                _ => None,
+            });
         if let Some((field, field_ty)) = field_receiver {
             let scope = tcx.parent_module_from_def_id(self.body_id);
             let is_accessible = field.vis.is_accessible_from(scope, tcx);
@@ -2675,9 +2679,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         if let SelfSource::MethodCall(expr) = source {
             let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
-            for (fields, args) in
-                self.get_field_candidates_considering_privacy(span, actual, mod_id, expr.hir_id)
-            {
+            for (fields, args) in self.get_field_candidates_considering_privacy_for_diag(
+                span,
+                actual,
+                mod_id,
+                expr.hir_id,
+            ) {
                 let call_expr = self.tcx.hir().expect_expr(self.tcx.parent_hir_id(expr.hir_id));
 
                 let lang_items = self.tcx.lang_items();
@@ -2693,7 +2700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let mut candidate_fields: Vec<_> = fields
                     .into_iter()
                     .filter_map(|candidate_field| {
-                        self.check_for_nested_field_satisfying(
+                        self.check_for_nested_field_satisfying_condition_for_diag(
                             span,
                             &|_, field_ty| {
                                 self.lookup_probe_for_diagnostic(
@@ -3195,7 +3202,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let SelfSource::QPath(ty) = self_source else {
             return;
         };
-        for (deref_ty, _) in self.autoderef(DUMMY_SP, rcvr_ty).skip(1) {
+        for (deref_ty, _) in self.autoderef(DUMMY_SP, rcvr_ty).silence_errors().skip(1) {
             if let Ok(pick) = self.probe_for_name(
                 Mode::Path,
                 item_name,
@@ -4221,7 +4228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return is_local(rcvr_ty);
         }
 
-        self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
+        self.autoderef(span, rcvr_ty).silence_errors().any(|(ty, _)| is_local(ty))
     }
 }
 
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index c8c95ddcfce..45a6efc7a6a 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -2533,6 +2533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             err.help("the semantics of slice patterns changed recently; see issue #62254");
         } else if self
             .autoderef(span, expected_ty)
+            .silence_errors()
             .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
             && let Some(span) = ti.span
             && let Some(_) = ti.origin_expr
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 676b242fda1..b5974e001aa 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2068,33 +2068,34 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             ) {
                 let res = binding.res();
                 if filter_fn(res) {
-                    let def_id = res.def_id();
-                    let has_self = match def_id.as_local() {
-                        Some(def_id) => {
-                            self.r.delegation_fn_sigs.get(&def_id).map_or(false, |sig| sig.has_self)
-                        }
-                        None => self
-                            .r
-                            .tcx
-                            .fn_arg_names(def_id)
-                            .first()
-                            .is_some_and(|ident| ident.name == kw::SelfLower),
-                    };
-                    if has_self {
-                        return Some(AssocSuggestion::MethodWithSelf { called });
-                    } else {
-                        match res {
-                            Res::Def(DefKind::AssocFn, _) => {
+                    match res {
+                        Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => {
+                            let has_self = match def_id.as_local() {
+                                Some(def_id) => self
+                                    .r
+                                    .delegation_fn_sigs
+                                    .get(&def_id)
+                                    .map_or(false, |sig| sig.has_self),
+                                None => self
+                                    .r
+                                    .tcx
+                                    .fn_arg_names(def_id)
+                                    .first()
+                                    .is_some_and(|ident| ident.name == kw::SelfLower),
+                            };
+                            if has_self {
+                                return Some(AssocSuggestion::MethodWithSelf { called });
+                            } else {
                                 return Some(AssocSuggestion::AssocFn { called });
                             }
-                            Res::Def(DefKind::AssocConst, _) => {
-                                return Some(AssocSuggestion::AssocConst);
-                            }
-                            Res::Def(DefKind::AssocTy, _) => {
-                                return Some(AssocSuggestion::AssocType);
-                            }
-                            _ => {}
                         }
+                        Res::Def(DefKind::AssocConst, _) => {
+                            return Some(AssocSuggestion::AssocConst);
+                        }
+                        Res::Def(DefKind::AssocTy, _) => {
+                            return Some(AssocSuggestion::AssocType);
+                        }
+                        _ => {}
                     }
                 }
             }
diff --git a/tests/crashes/130372-1.rs b/tests/crashes/130372-1.rs
deleted file mode 100644
index 5d58c14e7ab..00000000000
--- a/tests/crashes/130372-1.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: rust-lang/rust#130372
-
-pub fn variadic_fn(n: usize, mut args: ...) {}
-
-reuse variadic_fn;
-
-fn main() {
-        variadic_fn();
-}
diff --git a/tests/crashes/130372-2.rs b/tests/crashes/130372-2.rs
deleted file mode 100644
index 46404191e32..00000000000
--- a/tests/crashes/130372-2.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: rust-lang/rust#130372
-
-pub fn test_va_copy(_: u64, mut ap: ...) {}
-
-pub fn main() {
-    unsafe {
-        test_va_copy();
-
-        call(x);
-    }
-}
diff --git a/tests/crashes/130372-3.rs b/tests/crashes/130372-3.rs
deleted file mode 100644
index 6e1c57437c8..00000000000
--- a/tests/crashes/130372-3.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ known-bug: rust-lang/rust#130372
-
-fn bar() -> impl Fn() {
-    wrap()
-}
-
-fn wrap(...: impl ...) -> impl Fn() {}
diff --git a/tests/ui/methods/probe-error-on-infinite-deref.rs b/tests/ui/methods/probe-error-on-infinite-deref.rs
new file mode 100644
index 00000000000..85c1c0c09c1
--- /dev/null
+++ b/tests/ui/methods/probe-error-on-infinite-deref.rs
@@ -0,0 +1,16 @@
+use std::ops::Deref;
+
+// Make sure that method probe error reporting doesn't get too tangled up
+// on this infinite deref impl. See #130224.
+
+struct Wrap<T>(T);
+impl<T> Deref for Wrap<T> {
+    type Target = Wrap<Wrap<T>>;
+    fn deref(&self) -> &Wrap<Wrap<T>> { todo!() }
+}
+
+fn main() {
+    Wrap(1).lmao();
+    //~^ ERROR reached the recursion limit
+    //~| ERROR no method named `lmao`
+}
diff --git a/tests/ui/methods/probe-error-on-infinite-deref.stderr b/tests/ui/methods/probe-error-on-infinite-deref.stderr
new file mode 100644
index 00000000000..57a9ca2eaa8
--- /dev/null
+++ b/tests/ui/methods/probe-error-on-infinite-deref.stderr
@@ -0,0 +1,21 @@
+error[E0055]: reached the recursion limit while auto-dereferencing `Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<{integer}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+  --> $DIR/probe-error-on-infinite-deref.rs:13:13
+   |
+LL |     Wrap(1).lmao();
+   |             ^^^^ deref recursion limit reached
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`probe_error_on_infinite_deref`)
+
+error[E0599]: no method named `lmao` found for struct `Wrap<{integer}>` in the current scope
+  --> $DIR/probe-error-on-infinite-deref.rs:13:13
+   |
+LL | struct Wrap<T>(T);
+   | -------------- method `lmao` not found for this struct
+...
+LL |     Wrap(1).lmao();
+   |             ^^^^ method not found in `Wrap<{integer}>`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0055, E0599.
+For more information about an error, try `rustc --explain E0055`.
diff --git a/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.rs b/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.rs
new file mode 100644
index 00000000000..60a3b47010e
--- /dev/null
+++ b/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.rs
@@ -0,0 +1,12 @@
+#![feature(c_variadic)]
+
+// Regression test that covers all 3 cases of https://github.com/rust-lang/rust/issues/130372
+
+unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) {}
+
+pub fn main() {
+    unsafe {
+        test_va_copy();
+        //~^ ERROR this function takes at least 1 argument but 0 arguments were supplied
+    }
+}
diff --git a/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.stderr b/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.stderr
new file mode 100644
index 00000000000..38f76970358
--- /dev/null
+++ b/tests/ui/mismatched_types/mismatch-args-vargs-issue-130372.stderr
@@ -0,0 +1,19 @@
+error[E0060]: this function takes at least 1 argument but 0 arguments were supplied
+  --> $DIR/mismatch-args-vargs-issue-130372.rs:9:9
+   |
+LL |         test_va_copy();
+   |         ^^^^^^^^^^^^-- argument #1 of type `u64` is missing
+   |
+note: function defined here
+  --> $DIR/mismatch-args-vargs-issue-130372.rs:5:22
+   |
+LL | unsafe extern "C" fn test_va_copy(_: u64, mut ap: ...) {}
+   |                      ^^^^^^^^^^^^ ------
+help: provide the argument
+   |
+LL |         test_va_copy(/* u64 */);
+   |                     ~~~~~~~~~~~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0060`.
diff --git a/tests/ui/resolve/auxiliary/foreign-trait-with-assoc.rs b/tests/ui/resolve/auxiliary/foreign-trait-with-assoc.rs
new file mode 100644
index 00000000000..952957ec480
--- /dev/null
+++ b/tests/ui/resolve/auxiliary/foreign-trait-with-assoc.rs
@@ -0,0 +1,3 @@
+pub trait Foo {
+    type Bar;
+}
diff --git a/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs b/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs
new file mode 100644
index 00000000000..20bbbff8fd2
--- /dev/null
+++ b/tests/ui/resolve/dont-compute-arg-names-for-non-fn.rs
@@ -0,0 +1,11 @@
+//@ aux-build:foreign-trait-with-assoc.rs
+
+extern crate foreign_trait_with_assoc;
+use foreign_trait_with_assoc::Foo;
+
+// Make sure we don't try to call `fn_arg_names` on a non-fn item.
+
+impl Foo for Bar {}
+//~^ ERROR cannot find type `Bar` in this scope
+
+fn main() {}
diff --git a/tests/ui/resolve/dont-compute-arg-names-for-non-fn.stderr b/tests/ui/resolve/dont-compute-arg-names-for-non-fn.stderr
new file mode 100644
index 00000000000..a1a8bb575e1
--- /dev/null
+++ b/tests/ui/resolve/dont-compute-arg-names-for-non-fn.stderr
@@ -0,0 +1,14 @@
+error[E0412]: cannot find type `Bar` in this scope
+  --> $DIR/dont-compute-arg-names-for-non-fn.rs:8:14
+   |
+LL | impl Foo for Bar {}
+   |              ^^^
+   |
+help: you might have meant to use the associated type
+   |
+LL | impl Foo for Self::Bar {}
+   |              ++++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0412`.