diff options
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/diagnostics/expr.rs | 30 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/display.rs | 11 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer/expr.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lib.rs | 19 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/builtin.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk/mapping.rs | 8 |
7 files changed, 66 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#" | ||
524 | extern "C" { | ||
525 | fn fixed(fixed: u8); | ||
526 | fn varargs(fixed: u8, ...); | ||
527 | fn varargs2(...); | ||
528 | } | ||
529 | |||
530 | fn 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)] |
668 | pub struct FnSig { | 668 | pub 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. |
673 | pub type PolyFnSig = Binders<FnSig>; | 674 | pub type PolyFnSig = Binders<FnSig>; |
674 | 675 | ||
675 | impl FnSig { | 676 | impl 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..3ebb55f77 100644 --- a/crates/ra_hir_ty/src/traits/chalk/mapping.rs +++ b/crates/ra_hir_ty/src/traits/chalk/mapping.rs | |||
@@ -30,7 +30,8 @@ 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 | // FIXME: handle is_varargs | ||
34 | let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); | 35 | let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); |
35 | chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution }) | 36 | chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution }) |
36 | .intern(&Interner) | 37 | .intern(&Interner) |
@@ -124,7 +125,10 @@ impl ToChalk for Ty { | |||
124 | substitution.shifted_out(&Interner).expect("fn ptr should have no binders"), | 125 | substitution.shifted_out(&Interner).expect("fn ptr should have no binders"), |
125 | ); | 126 | ); |
126 | Ty::Apply(ApplicationTy { | 127 | Ty::Apply(ApplicationTy { |
127 | ctor: TypeCtor::FnPtr { num_args: (parameters.len() - 1) as u16 }, | 128 | ctor: TypeCtor::FnPtr { |
129 | num_args: (parameters.len() - 1) as u16, | ||
130 | is_varargs: false, | ||
131 | }, | ||
128 | parameters, | 132 | parameters, |
129 | }) | 133 | }) |
130 | } | 134 | } |