aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_ty/src')
-rw-r--r--crates/ra_hir_ty/src/diagnostics/expr.rs30
-rw-r--r--crates/ra_hir_ty/src/display.rs11
-rw-r--r--crates/ra_hir_ty/src/infer/expr.rs2
-rw-r--r--crates/ra_hir_ty/src/lib.rs19
-rw-r--r--crates/ra_hir_ty/src/lower.rs13
-rw-r--r--crates/ra_hir_ty/src/traits/builtin.rs2
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/mapping.rs7
7 files changed, 65 insertions, 19 deletions
diff --git a/crates/ra_hir_ty/src/diagnostics/expr.rs b/crates/ra_hir_ty/src/diagnostics/expr.rs
index 21ff99a8c..557d01cdc 100644
--- a/crates/ra_hir_ty/src/diagnostics/expr.rs
+++ b/crates/ra_hir_ty/src/diagnostics/expr.rs
@@ -175,6 +175,10 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
175 }; 175 };
176 176
177 let sig = db.callable_item_signature(callee); 177 let sig = db.callable_item_signature(callee);
178 if sig.value.is_varargs {
179 return None;
180 }
181
178 let params = sig.value.params(); 182 let params = sig.value.params();
179 183
180 let mut param_count = params.len(); 184 let mut param_count = params.len();
@@ -512,4 +516,30 @@ impl Foo {
512 "#, 516 "#,
513 ); 517 );
514 } 518 }
519
520 #[test]
521 fn varargs() {
522 check_diagnostics(
523 r#"
524extern "C" {
525 fn fixed(fixed: u8);
526 fn varargs(fixed: u8, ...);
527 fn varargs2(...);
528}
529
530fn f() {
531 unsafe {
532 fixed(0);
533 fixed(0, 1);
534 //^^^^^^^^^^^ Expected 1 argument, found 2
535 varargs(0);
536 varargs(0, 1);
537 varargs2();
538 varargs2(0);
539 varargs2(0, 1);
540 }
541}
542 "#,
543 )
544 }
515} 545}
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index ac68c5661..c860c254c 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -243,10 +243,17 @@ impl HirDisplay for ApplicationTy {
243 write!(f, ")")?; 243 write!(f, ")")?;
244 } 244 }
245 } 245 }
246 TypeCtor::FnPtr { .. } => { 246 TypeCtor::FnPtr { is_varargs, .. } => {
247 let sig = FnSig::from_fn_ptr_substs(&self.parameters); 247 let sig = FnSig::from_fn_ptr_substs(&self.parameters, is_varargs);
248 write!(f, "fn(")?; 248 write!(f, "fn(")?;
249 f.write_joined(sig.params(), ", ")?; 249 f.write_joined(sig.params(), ", ")?;
250 if is_varargs {
251 if sig.params().is_empty() {
252 write!(f, "...")?;
253 } else {
254 write!(f, ", ...")?;
255 }
256 }
250 write!(f, ")")?; 257 write!(f, ")")?;
251 let ret = sig.ret(); 258 let ret = sig.ret();
252 if *ret != Ty::unit() { 259 if *ret != Ty::unit() {
diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs
index bd9a387f5..ab586b018 100644
--- a/crates/ra_hir_ty/src/infer/expr.rs
+++ b/crates/ra_hir_ty/src/infer/expr.rs
@@ -220,7 +220,7 @@ impl<'a> InferenceContext<'a> {
220 }; 220 };
221 sig_tys.push(ret_ty.clone()); 221 sig_tys.push(ret_ty.clone());
222 let sig_ty = Ty::apply( 222 let sig_ty = Ty::apply(
223 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, 223 TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1, is_varargs: false },
224 Substs(sig_tys.clone().into()), 224 Substs(sig_tys.clone().into()),
225 ); 225 );
226 let closure_ty = 226 let closure_ty =
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index d54568e67..c4c24a83b 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -112,7 +112,7 @@ pub enum TypeCtor {
112 /// fn foo() -> i32 { 1 } 112 /// fn foo() -> i32 { 1 }
113 /// let bar: fn() -> i32 = foo; 113 /// let bar: fn() -> i32 = foo;
114 /// ``` 114 /// ```
115 FnPtr { num_args: u16 }, 115 FnPtr { num_args: u16, is_varargs: bool },
116 116
117 /// The never type `!`. 117 /// The never type `!`.
118 Never, 118 Never,
@@ -187,7 +187,7 @@ impl TypeCtor {
187 } 187 }
188 } 188 }
189 } 189 }
190 TypeCtor::FnPtr { num_args } => num_args as usize + 1, 190 TypeCtor::FnPtr { num_args, is_varargs: _ } => num_args as usize + 1,
191 TypeCtor::Tuple { cardinality } => cardinality as usize, 191 TypeCtor::Tuple { cardinality } => cardinality as usize,
192 } 192 }
193 } 193 }
@@ -667,19 +667,20 @@ pub enum TyKind {
667#[derive(Clone, PartialEq, Eq, Debug)] 667#[derive(Clone, PartialEq, Eq, Debug)]
668pub struct FnSig { 668pub struct FnSig {
669 params_and_return: Arc<[Ty]>, 669 params_and_return: Arc<[Ty]>,
670 is_varargs: bool,
670} 671}
671 672
672/// A polymorphic function signature. 673/// A polymorphic function signature.
673pub type PolyFnSig = Binders<FnSig>; 674pub type PolyFnSig = Binders<FnSig>;
674 675
675impl FnSig { 676impl FnSig {
676 pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig { 677 pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> FnSig {
677 params.push(ret); 678 params.push(ret);
678 FnSig { params_and_return: params.into() } 679 FnSig { params_and_return: params.into(), is_varargs }
679 } 680 }
680 681
681 pub fn from_fn_ptr_substs(substs: &Substs) -> FnSig { 682 pub fn from_fn_ptr_substs(substs: &Substs, is_varargs: bool) -> FnSig {
682 FnSig { params_and_return: Arc::clone(&substs.0) } 683 FnSig { params_and_return: Arc::clone(&substs.0), is_varargs }
683 } 684 }
684 685
685 pub fn params(&self) -> &[Ty] { 686 pub fn params(&self) -> &[Ty] {
@@ -724,7 +725,7 @@ impl Ty {
724 } 725 }
725 pub fn fn_ptr(sig: FnSig) -> Self { 726 pub fn fn_ptr(sig: FnSig) -> Self {
726 Ty::apply( 727 Ty::apply(
727 TypeCtor::FnPtr { num_args: sig.params().len() as u16 }, 728 TypeCtor::FnPtr { num_args: sig.params().len() as u16, is_varargs: sig.is_varargs },
728 Substs(sig.params_and_return), 729 Substs(sig.params_and_return),
729 ) 730 )
730 } 731 }
@@ -821,7 +822,9 @@ impl Ty {
821 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> { 822 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> {
822 match self { 823 match self {
823 Ty::Apply(a_ty) => match a_ty.ctor { 824 Ty::Apply(a_ty) => match a_ty.ctor {
824 TypeCtor::FnPtr { .. } => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)), 825 TypeCtor::FnPtr { is_varargs, .. } => {
826 Some(FnSig::from_fn_ptr_substs(&a_ty.parameters, is_varargs))
827 }
825 TypeCtor::FnDef(def) => { 828 TypeCtor::FnDef(def) => {
826 let sig = db.callable_item_signature(def); 829 let sig = db.callable_item_signature(def);
827 Some(sig.subst(&a_ty.parameters)) 830 Some(sig.subst(&a_ty.parameters))
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index 101b8aebe..6f4398e84 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -176,9 +176,12 @@ impl Ty {
176 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) 176 Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
177 } 177 }
178 TypeRef::Placeholder => Ty::Unknown, 178 TypeRef::Placeholder => Ty::Unknown,
179 TypeRef::Fn(params) => { 179 TypeRef::Fn(params, is_varargs) => {
180 let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect()); 180 let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect());
181 Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) 181 Ty::apply(
182 TypeCtor::FnPtr { num_args: sig.len() as u16 - 1, is_varargs: *is_varargs },
183 sig,
184 )
182 } 185 }
183 TypeRef::DynTrait(bounds) => { 186 TypeRef::DynTrait(bounds) => {
184 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0)); 187 let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
@@ -996,7 +999,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
996 let ret = Ty::from_hir(&ctx_ret, &data.ret_type); 999 let ret = Ty::from_hir(&ctx_ret, &data.ret_type);
997 let generics = generics(db.upcast(), def.into()); 1000 let generics = generics(db.upcast(), def.into());
998 let num_binders = generics.len(); 1001 let num_binders = generics.len();
999 Binders::new(num_binders, FnSig::from_params_and_return(params, ret)) 1002 Binders::new(num_binders, FnSig::from_params_and_return(params, ret, data.is_varargs))
1000} 1003}
1001 1004
1002/// Build the declared type of a function. This should not need to look at the 1005/// Build the declared type of a function. This should not need to look at the
@@ -1047,7 +1050,7 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
1047 let params = 1050 let params =
1048 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); 1051 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
1049 let ret = type_for_adt(db, def.into()); 1052 let ret = type_for_adt(db, def.into());
1050 Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) 1053 Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false))
1051} 1054}
1052 1055
1053/// Build the type of a tuple struct constructor. 1056/// Build the type of a tuple struct constructor.
@@ -1071,7 +1074,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
1071 let params = 1074 let params =
1072 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); 1075 fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
1073 let ret = type_for_adt(db, def.parent.into()); 1076 let ret = type_for_adt(db, def.parent.into());
1074 Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value)) 1077 Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false))
1075} 1078}
1076 1079
1077/// Build the type of a tuple enum variant constructor. 1080/// Build the type of a tuple enum variant constructor.
diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs
index 86e22e459..60cc9a9f5 100644
--- a/crates/ra_hir_ty/src/traits/builtin.rs
+++ b/crates/ra_hir_ty/src/traits/builtin.rs
@@ -121,7 +121,7 @@ fn closure_fn_trait_impl_datum(
121 .build(), 121 .build(),
122 ); 122 );
123 let sig_ty = Ty::apply( 123 let sig_ty = Ty::apply(
124 TypeCtor::FnPtr { num_args }, 124 TypeCtor::FnPtr { num_args, is_varargs: false },
125 Substs::builder(num_args as usize + 1) 125 Substs::builder(num_args as usize + 1)
126 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) 126 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
127 .build(), 127 .build(),
diff --git a/crates/ra_hir_ty/src/traits/chalk/mapping.rs b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
index 06453ef82..5ba2ff51b 100644
--- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs
@@ -30,7 +30,7 @@ impl ToChalk for Ty {
30 Ty::Apply(apply_ty) => match apply_ty.ctor { 30 Ty::Apply(apply_ty) => match apply_ty.ctor {
31 TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), 31 TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters),
32 TypeCtor::Array => array_to_chalk(db, apply_ty.parameters), 32 TypeCtor::Array => array_to_chalk(db, apply_ty.parameters),
33 TypeCtor::FnPtr { num_args: _ } => { 33 TypeCtor::FnPtr { num_args: _, is_varargs: _ } => {
34 let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); 34 let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner);
35 chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution }) 35 chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution })
36 .intern(&Interner) 36 .intern(&Interner)
@@ -124,7 +124,10 @@ impl ToChalk for Ty {
124 substitution.shifted_out(&Interner).expect("fn ptr should have no binders"), 124 substitution.shifted_out(&Interner).expect("fn ptr should have no binders"),
125 ); 125 );
126 Ty::Apply(ApplicationTy { 126 Ty::Apply(ApplicationTy {
127 ctor: TypeCtor::FnPtr { num_args: (parameters.len() - 1) as u16 }, 127 ctor: TypeCtor::FnPtr {
128 num_args: (parameters.len() - 1) as u16,
129 is_varargs: false,
130 },
128 parameters, 131 parameters,
129 }) 132 })
130 } 133 }