about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCrauzer <filip.quitko@gmail.com>2022-11-29 00:32:13 +0100
committerCrauzer <filip.quitko@gmail.com>2022-11-29 00:32:13 +0100
commitb3bd5a471e314841fb1d2d94fdc50ef3c8d8548f (patch)
tree134b526742108abec41dc37eeba6a7ac7d6dd1df
parent6d61be8e65ac0fd45eaf178e1f7a1ec6b582de1f (diff)
downloadrust-b3bd5a471e314841fb1d2d94fdc50ef3c8d8548f.tar.gz
rust-b3bd5a471e314841fb1d2d94fdc50ef3c8d8548f.zip
implement vararg type collection from function params
-rw-r--r--crates/hir-expand/src/name.rs1
-rw-r--r--crates/hir-ty/src/infer.rs19
-rw-r--r--crates/hir-ty/src/tests/patterns.rs12
3 files changed, 31 insertions, 1 deletions
diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs
index 2679a1c3602..259fe1327f8 100644
--- a/crates/hir-expand/src/name.rs
+++ b/crates/hir-expand/src/name.rs
@@ -419,6 +419,7 @@ pub mod known {
         shr,
         sub_assign,
         sub,
+        va_list
     );
 
     // self/Self cannot be used as an identifier
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 0b3c23f5747..112eb5bd84c 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -537,8 +537,20 @@ impl<'a> InferenceContext<'a> {
         let data = self.db.function_data(func);
         let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver)
             .with_impl_trait_mode(ImplTraitLoweringMode::Param);
-        let param_tys =
+        let mut param_tys =
             data.params.iter().map(|(_, type_ref)| ctx.lower_ty(type_ref)).collect::<Vec<_>>();
+        // Check if function contains a va_list, if it does then we append it to the parameter types
+        // that are collected from the function data
+        if data.is_varargs() {
+            let va_list_ty = match self.resolve_va_list() {
+                Some(va_list) => TyBuilder::adt(self.db, va_list)
+                    .fill_with_defaults(self.db, || self.table.new_type_var())
+                    .build(),
+                None => self.err_ty(),
+            };
+
+            param_tys.push(va_list_ty)
+        }
         for (ty, pat) in param_tys.into_iter().zip(self.body.params.iter()) {
             let ty = self.insert_type_vars(ty);
             let ty = self.normalize_associated_types_in(ty);
@@ -983,6 +995,11 @@ impl<'a> InferenceContext<'a> {
         let trait_ = self.resolve_ops_index()?;
         self.db.trait_data(trait_).associated_type_by_name(&name![Output])
     }
+
+    fn resolve_va_list(&self) -> Option<AdtId> {
+        let struct_ = self.resolve_lang_item(name![va_list])?.as_struct()?;
+        Some(struct_.into())
+    }
 }
 
 /// When inferring an expression, we propagate downward whatever type hint we
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index 74de33117ee..9333e269352 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/crates/hir-ty/src/tests/patterns.rs
@@ -1080,3 +1080,15 @@ fn my_fn(#[cfg(feature = "feature")] u8: u8, u32: u32) {}
 "#,
     );
 }
+
+#[test]
+fn var_args() {
+    check_types(
+        r#"
+#[lang = "va_list"]
+pub struct VaListImpl<'f>;
+fn my_fn(foo: ...) {}
+       //^^^ VaListImpl
+"#,
+    );
+}