mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 05:23:24 +00:00
Merge #5378
5378: Thread varargs through rust-analyzer r=flodiebold a=jonas-schievink This adds a varargs flag to various data structures and fills it from the AST. Fixes https://github.com/rust-analyzer/rust-analyzer/issues/5374 cc @flodiebold for the typesystem/chalk changes Co-authored-by: Jonas Schievink <jonas.schievink@ferrous-systems.com>
This commit is contained in:
commit
fc2f761d65
12 changed files with 100 additions and 34 deletions
|
@ -27,6 +27,7 @@ pub struct FunctionData {
|
||||||
/// can be called as a method.
|
/// can be called as a method.
|
||||||
pub has_self_param: bool,
|
pub has_self_param: bool,
|
||||||
pub is_unsafe: bool,
|
pub is_unsafe: bool,
|
||||||
|
pub is_varargs: bool,
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ impl FunctionData {
|
||||||
attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(),
|
attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(),
|
||||||
has_self_param: func.has_self_param,
|
has_self_param: func.has_self_param,
|
||||||
is_unsafe: func.is_unsafe,
|
is_unsafe: func.is_unsafe,
|
||||||
|
is_varargs: func.is_varargs,
|
||||||
visibility: item_tree[func.visibility].clone(),
|
visibility: item_tree[func.visibility].clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -503,6 +503,7 @@ pub struct Function {
|
||||||
pub has_self_param: bool,
|
pub has_self_param: bool,
|
||||||
pub is_unsafe: bool,
|
pub is_unsafe: bool,
|
||||||
pub params: Box<[TypeRef]>,
|
pub params: Box<[TypeRef]>,
|
||||||
|
pub is_varargs: bool,
|
||||||
pub ret_type: TypeRef,
|
pub ret_type: TypeRef,
|
||||||
pub ast_id: FileAstId<ast::FnDef>,
|
pub ast_id: FileAstId<ast::FnDef>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -313,6 +313,14 @@ impl Ctx {
|
||||||
params.push(type_ref);
|
params.push(type_ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut is_varargs = false;
|
||||||
|
if let Some(params) = func.param_list() {
|
||||||
|
if let Some(last) = params.params().last() {
|
||||||
|
is_varargs = last.dotdotdot_token().is_some();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let ret_type = match func.ret_type().and_then(|rt| rt.type_ref()) {
|
let ret_type = match func.ret_type().and_then(|rt| rt.type_ref()) {
|
||||||
Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
|
Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
|
||||||
_ => TypeRef::unit(),
|
_ => TypeRef::unit(),
|
||||||
|
@ -334,6 +342,7 @@ impl Ctx {
|
||||||
has_self_param,
|
has_self_param,
|
||||||
is_unsafe: func.unsafe_token().is_some(),
|
is_unsafe: func.unsafe_token().is_some(),
|
||||||
params: params.into_boxed_slice(),
|
params: params.into_boxed_slice(),
|
||||||
|
is_varargs,
|
||||||
ret_type,
|
ret_type,
|
||||||
ast_id,
|
ast_id,
|
||||||
};
|
};
|
||||||
|
|
|
@ -240,9 +240,9 @@ fn smoke() {
|
||||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_const"))] }, input: None }]) }]
|
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_const"))] }, input: None }]) }]
|
||||||
> Const { name: Some(Name(Text("CONST"))), visibility: RawVisibilityId("pub(self)"), type_ref: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u8"))] }, generic_args: [None] }), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ConstDef>(9) }
|
> Const { name: Some(Name(Text("CONST"))), visibility: RawVisibilityId("pub(self)"), type_ref: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("u8"))] }, generic_args: [None] }), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ConstDef>(9) }
|
||||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_method"))] }, input: None }]) }]
|
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_method"))] }, input: None }]) }]
|
||||||
> Function { name: Name(Text("method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Shared)], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(10) }
|
> Function { name: Name(Text("method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Shared)], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(10) }
|
||||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_dfl_method"))] }, input: None }]) }]
|
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("assoc_dfl_method"))] }, input: None }]) }]
|
||||||
> Function { name: Name(Text("dfl_method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Mut)], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(11) }
|
> Function { name: Name(Text("dfl_method")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: true, is_unsafe: false, params: [Reference(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Self"))] }, generic_args: [None] }), Mut)], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(11) }
|
||||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct0"))] }, input: None }]) }]
|
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct0"))] }, input: None }]) }]
|
||||||
Struct { name: Name(Text("Struct0")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), fields: Unit, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::StructDef>(3), kind: Unit }
|
Struct { name: Name(Text("Struct0")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), fields: Unit, ast_id: FileAstId::<ra_syntax::ast::generated::nodes::StructDef>(3), kind: Unit }
|
||||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct1"))] }, input: None }]) }]
|
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("struct1"))] }, input: None }]) }]
|
||||||
|
@ -275,12 +275,12 @@ fn simple_inner_items() {
|
||||||
|
|
||||||
top-level items:
|
top-level items:
|
||||||
Impl { generic_params: GenericParamsId(0), target_trait: Some(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("D"))] }, generic_args: [None] })), target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Response"))] }, generic_args: [Some(GenericArgs { args: [Type(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("T"))] }, generic_args: [None] }))], has_self_type: false, bindings: [] })] }), is_negative: false, items: [Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) }
|
Impl { generic_params: GenericParamsId(0), target_trait: Some(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("D"))] }, generic_args: [None] })), target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Response"))] }, generic_args: [Some(GenericArgs { args: [Type(Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("T"))] }, generic_args: [None] }))], has_self_type: false, bindings: [] })] }), is_negative: false, items: [Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) }
|
||||||
> Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
> Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
||||||
|
|
||||||
inner items:
|
inner items:
|
||||||
|
|
||||||
for AST FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(2):
|
for AST FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(2):
|
||||||
Function { name: Name(Text("end")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
Function { name: Name(Text("end")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(1), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
||||||
|
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
|
@ -303,9 +303,9 @@ fn extern_attrs() {
|
||||||
|
|
||||||
top-level items:
|
top-level items:
|
||||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }]
|
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }]
|
||||||
Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: true, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: true, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
||||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }]
|
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }, Attr { path: ModPath { kind: Plain, segments: [Name(Text("block_attr"))] }, input: None }]) }]
|
||||||
Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: true, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: true, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
||||||
"##]],
|
"##]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -329,9 +329,9 @@ fn trait_attrs() {
|
||||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("trait_attr"))] }, input: None }]) }]
|
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("trait_attr"))] }, input: None }]) }]
|
||||||
Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::TraitDef>(0) }
|
Trait { name: Name(Text("Tr")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(0), auto: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::TraitDef>(0) }
|
||||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }]
|
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }]
|
||||||
> Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
> Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
||||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }]
|
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }]
|
||||||
> Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
> Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
||||||
"##]],
|
"##]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -355,9 +355,9 @@ fn impl_attrs() {
|
||||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("impl_attr"))] }, input: None }]) }]
|
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("impl_attr"))] }, input: None }]) }]
|
||||||
Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Ty"))] }, generic_args: [None] }), is_negative: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) }
|
Impl { generic_params: GenericParamsId(4294967295), target_trait: None, target_type: Path(Path { type_anchor: None, mod_path: ModPath { kind: Plain, segments: [Name(Text("Ty"))] }, generic_args: [None] }), is_negative: false, items: [Function(Idx::<Function>(0)), Function(Idx::<Function>(1))], ast_id: FileAstId::<ra_syntax::ast::generated::nodes::ImplDef>(0) }
|
||||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }]
|
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_a"))] }, input: None }]) }]
|
||||||
> Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
> Function { name: Name(Text("a")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
||||||
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }]
|
> #[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("attr_b"))] }, input: None }]) }]
|
||||||
> Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
> Function { name: Name(Text("b")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(2) }
|
||||||
"##]],
|
"##]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -408,13 +408,13 @@ fn inner_item_attrs() {
|
||||||
inner attrs: Attrs { entries: None }
|
inner attrs: Attrs { entries: None }
|
||||||
|
|
||||||
top-level items:
|
top-level items:
|
||||||
Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(0) }
|
Function { name: Name(Text("foo")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(0) }
|
||||||
|
|
||||||
inner items:
|
inner items:
|
||||||
|
|
||||||
for AST FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(1):
|
for AST FileAstId::<ra_syntax::ast::generated::nodes::ModuleItem>(1):
|
||||||
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_inner"))] }, input: None }]) }]
|
#[Attrs { entries: Some([Attr { path: ModPath { kind: Plain, segments: [Name(Text("on_inner"))] }, input: None }]) }]
|
||||||
Function { name: Name(Text("inner")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
Function { name: Name(Text("inner")), visibility: RawVisibilityId("pub(self)"), generic_params: GenericParamsId(4294967295), has_self_param: false, is_unsafe: false, params: [], is_varargs: false, ret_type: Tuple([]), ast_id: FileAstId::<ra_syntax::ast::generated::nodes::FnDef>(1) }
|
||||||
|
|
||||||
"##]],
|
"##]],
|
||||||
);
|
);
|
||||||
|
|
|
@ -63,7 +63,7 @@ pub enum TypeRef {
|
||||||
Array(Box<TypeRef> /*, Expr*/),
|
Array(Box<TypeRef> /*, Expr*/),
|
||||||
Slice(Box<TypeRef>),
|
Slice(Box<TypeRef>),
|
||||||
/// A fn pointer. Last element of the vector is the return type.
|
/// A fn pointer. Last element of the vector is the return type.
|
||||||
Fn(Vec<TypeRef>),
|
Fn(Vec<TypeRef>, bool /*varargs*/),
|
||||||
// For
|
// For
|
||||||
ImplTrait(Vec<TypeBound>),
|
ImplTrait(Vec<TypeBound>),
|
||||||
DynTrait(Vec<TypeBound>),
|
DynTrait(Vec<TypeBound>),
|
||||||
|
@ -118,7 +118,12 @@ impl TypeRef {
|
||||||
.and_then(|rt| rt.type_ref())
|
.and_then(|rt| rt.type_ref())
|
||||||
.map(|it| TypeRef::from_ast(ctx, it))
|
.map(|it| TypeRef::from_ast(ctx, it))
|
||||||
.unwrap_or_else(|| TypeRef::Tuple(Vec::new()));
|
.unwrap_or_else(|| TypeRef::Tuple(Vec::new()));
|
||||||
|
let mut is_varargs = false;
|
||||||
let mut params = if let Some(pl) = inner.param_list() {
|
let mut params = if let Some(pl) = inner.param_list() {
|
||||||
|
if let Some(param) = pl.params().last() {
|
||||||
|
is_varargs = param.dotdotdot_token().is_some();
|
||||||
|
}
|
||||||
|
|
||||||
pl.params()
|
pl.params()
|
||||||
.map(|p| p.ascribed_type())
|
.map(|p| p.ascribed_type())
|
||||||
.map(|it| TypeRef::from_ast_opt(&ctx, it))
|
.map(|it| TypeRef::from_ast_opt(&ctx, it))
|
||||||
|
@ -127,7 +132,7 @@ impl TypeRef {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
};
|
};
|
||||||
params.push(ret_ty);
|
params.push(ret_ty);
|
||||||
TypeRef::Fn(params)
|
TypeRef::Fn(params, is_varargs)
|
||||||
}
|
}
|
||||||
// for types are close enough for our purposes to the inner type for now...
|
// for types are close enough for our purposes to the inner type for now...
|
||||||
ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
|
ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
|
||||||
|
@ -158,7 +163,9 @@ impl TypeRef {
|
||||||
fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) {
|
fn go(type_ref: &TypeRef, f: &mut impl FnMut(&TypeRef)) {
|
||||||
f(type_ref);
|
f(type_ref);
|
||||||
match type_ref {
|
match type_ref {
|
||||||
TypeRef::Fn(types) | TypeRef::Tuple(types) => types.iter().for_each(|t| go(t, f)),
|
TypeRef::Fn(types, _) | TypeRef::Tuple(types) => {
|
||||||
|
types.iter().for_each(|t| go(t, f))
|
||||||
|
}
|
||||||
TypeRef::RawPtr(type_ref, _)
|
TypeRef::RawPtr(type_ref, _)
|
||||||
| TypeRef::Reference(type_ref, _)
|
| TypeRef::Reference(type_ref, _)
|
||||||
| TypeRef::Array(type_ref)
|
| TypeRef::Array(type_ref)
|
||||||
|
|
|
@ -175,6 +175,10 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let sig = db.callable_item_signature(callee);
|
let sig = db.callable_item_signature(callee);
|
||||||
|
if sig.value.is_varargs {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let params = sig.value.params();
|
let params = sig.value.params();
|
||||||
|
|
||||||
let mut param_count = params.len();
|
let mut param_count = params.len();
|
||||||
|
@ -512,4 +516,30 @@ impl Foo {
|
||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn varargs() {
|
||||||
|
check_diagnostics(
|
||||||
|
r#"
|
||||||
|
extern "C" {
|
||||||
|
fn fixed(fixed: u8);
|
||||||
|
fn varargs(fixed: u8, ...);
|
||||||
|
fn varargs2(...);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
unsafe {
|
||||||
|
fixed(0);
|
||||||
|
fixed(0, 1);
|
||||||
|
//^^^^^^^^^^^ Expected 1 argument, found 2
|
||||||
|
varargs(0);
|
||||||
|
varargs(0, 1);
|
||||||
|
varargs2();
|
||||||
|
varargs2(0);
|
||||||
|
varargs2(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,10 +243,17 @@ impl HirDisplay for ApplicationTy {
|
||||||
write!(f, ")")?;
|
write!(f, ")")?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeCtor::FnPtr { .. } => {
|
TypeCtor::FnPtr { is_varargs, .. } => {
|
||||||
let sig = FnSig::from_fn_ptr_substs(&self.parameters);
|
let sig = FnSig::from_fn_ptr_substs(&self.parameters, is_varargs);
|
||||||
write!(f, "fn(")?;
|
write!(f, "fn(")?;
|
||||||
f.write_joined(sig.params(), ", ")?;
|
f.write_joined(sig.params(), ", ")?;
|
||||||
|
if is_varargs {
|
||||||
|
if sig.params().is_empty() {
|
||||||
|
write!(f, "...")?;
|
||||||
|
} else {
|
||||||
|
write!(f, ", ...")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
write!(f, ")")?;
|
write!(f, ")")?;
|
||||||
let ret = sig.ret();
|
let ret = sig.ret();
|
||||||
if *ret != Ty::unit() {
|
if *ret != Ty::unit() {
|
||||||
|
|
|
@ -220,7 +220,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
};
|
};
|
||||||
sig_tys.push(ret_ty.clone());
|
sig_tys.push(ret_ty.clone());
|
||||||
let sig_ty = Ty::apply(
|
let sig_ty = Ty::apply(
|
||||||
TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 },
|
TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1, is_varargs: false },
|
||||||
Substs(sig_tys.clone().into()),
|
Substs(sig_tys.clone().into()),
|
||||||
);
|
);
|
||||||
let closure_ty =
|
let closure_ty =
|
||||||
|
|
|
@ -112,7 +112,7 @@ pub enum TypeCtor {
|
||||||
/// fn foo() -> i32 { 1 }
|
/// fn foo() -> i32 { 1 }
|
||||||
/// let bar: fn() -> i32 = foo;
|
/// let bar: fn() -> i32 = foo;
|
||||||
/// ```
|
/// ```
|
||||||
FnPtr { num_args: u16 },
|
FnPtr { num_args: u16, is_varargs: bool },
|
||||||
|
|
||||||
/// The never type `!`.
|
/// The never type `!`.
|
||||||
Never,
|
Never,
|
||||||
|
@ -187,7 +187,7 @@ impl TypeCtor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TypeCtor::FnPtr { num_args } => num_args as usize + 1,
|
TypeCtor::FnPtr { num_args, is_varargs: _ } => num_args as usize + 1,
|
||||||
TypeCtor::Tuple { cardinality } => cardinality as usize,
|
TypeCtor::Tuple { cardinality } => cardinality as usize,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -667,19 +667,20 @@ pub enum TyKind {
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct FnSig {
|
pub struct FnSig {
|
||||||
params_and_return: Arc<[Ty]>,
|
params_and_return: Arc<[Ty]>,
|
||||||
|
is_varargs: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A polymorphic function signature.
|
/// A polymorphic function signature.
|
||||||
pub type PolyFnSig = Binders<FnSig>;
|
pub type PolyFnSig = Binders<FnSig>;
|
||||||
|
|
||||||
impl FnSig {
|
impl FnSig {
|
||||||
pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty) -> FnSig {
|
pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> FnSig {
|
||||||
params.push(ret);
|
params.push(ret);
|
||||||
FnSig { params_and_return: params.into() }
|
FnSig { params_and_return: params.into(), is_varargs }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_fn_ptr_substs(substs: &Substs) -> FnSig {
|
pub fn from_fn_ptr_substs(substs: &Substs, is_varargs: bool) -> FnSig {
|
||||||
FnSig { params_and_return: Arc::clone(&substs.0) }
|
FnSig { params_and_return: Arc::clone(&substs.0), is_varargs }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn params(&self) -> &[Ty] {
|
pub fn params(&self) -> &[Ty] {
|
||||||
|
@ -724,7 +725,7 @@ impl Ty {
|
||||||
}
|
}
|
||||||
pub fn fn_ptr(sig: FnSig) -> Self {
|
pub fn fn_ptr(sig: FnSig) -> Self {
|
||||||
Ty::apply(
|
Ty::apply(
|
||||||
TypeCtor::FnPtr { num_args: sig.params().len() as u16 },
|
TypeCtor::FnPtr { num_args: sig.params().len() as u16, is_varargs: sig.is_varargs },
|
||||||
Substs(sig.params_and_return),
|
Substs(sig.params_and_return),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -821,7 +822,9 @@ impl Ty {
|
||||||
fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> {
|
fn callable_sig(&self, db: &dyn HirDatabase) -> Option<FnSig> {
|
||||||
match self {
|
match self {
|
||||||
Ty::Apply(a_ty) => match a_ty.ctor {
|
Ty::Apply(a_ty) => match a_ty.ctor {
|
||||||
TypeCtor::FnPtr { .. } => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)),
|
TypeCtor::FnPtr { is_varargs, .. } => {
|
||||||
|
Some(FnSig::from_fn_ptr_substs(&a_ty.parameters, is_varargs))
|
||||||
|
}
|
||||||
TypeCtor::FnDef(def) => {
|
TypeCtor::FnDef(def) => {
|
||||||
let sig = db.callable_item_signature(def);
|
let sig = db.callable_item_signature(def);
|
||||||
Some(sig.subst(&a_ty.parameters))
|
Some(sig.subst(&a_ty.parameters))
|
||||||
|
|
|
@ -176,9 +176,12 @@ impl Ty {
|
||||||
Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
|
Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty)
|
||||||
}
|
}
|
||||||
TypeRef::Placeholder => Ty::Unknown,
|
TypeRef::Placeholder => Ty::Unknown,
|
||||||
TypeRef::Fn(params) => {
|
TypeRef::Fn(params, is_varargs) => {
|
||||||
let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect());
|
let sig = Substs(params.iter().map(|tr| Ty::from_hir(ctx, tr)).collect());
|
||||||
Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig)
|
Ty::apply(
|
||||||
|
TypeCtor::FnPtr { num_args: sig.len() as u16 - 1, is_varargs: *is_varargs },
|
||||||
|
sig,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
TypeRef::DynTrait(bounds) => {
|
TypeRef::DynTrait(bounds) => {
|
||||||
let self_ty = Ty::Bound(BoundVar::new(DebruijnIndex::INNERMOST, 0));
|
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 {
|
||||||
let ret = Ty::from_hir(&ctx_ret, &data.ret_type);
|
let ret = Ty::from_hir(&ctx_ret, &data.ret_type);
|
||||||
let generics = generics(db.upcast(), def.into());
|
let generics = generics(db.upcast(), def.into());
|
||||||
let num_binders = generics.len();
|
let num_binders = generics.len();
|
||||||
Binders::new(num_binders, FnSig::from_params_and_return(params, ret))
|
Binders::new(num_binders, FnSig::from_params_and_return(params, ret, data.is_varargs))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build the declared type of a function. This should not need to look at the
|
/// 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
|
||||||
let params =
|
let params =
|
||||||
fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
|
fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
|
||||||
let ret = type_for_adt(db, def.into());
|
let ret = type_for_adt(db, def.into());
|
||||||
Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value))
|
Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build the type of a tuple struct constructor.
|
/// Build the type of a tuple struct constructor.
|
||||||
|
@ -1071,7 +1074,7 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
|
||||||
let params =
|
let params =
|
||||||
fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
|
fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>();
|
||||||
let ret = type_for_adt(db, def.parent.into());
|
let ret = type_for_adt(db, def.parent.into());
|
||||||
Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value))
|
Binders::new(ret.num_binders, FnSig::from_params_and_return(params, ret.value, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build the type of a tuple enum variant constructor.
|
/// Build the type of a tuple enum variant constructor.
|
||||||
|
|
|
@ -121,7 +121,7 @@ fn closure_fn_trait_impl_datum(
|
||||||
.build(),
|
.build(),
|
||||||
);
|
);
|
||||||
let sig_ty = Ty::apply(
|
let sig_ty = Ty::apply(
|
||||||
TypeCtor::FnPtr { num_args },
|
TypeCtor::FnPtr { num_args, is_varargs: false },
|
||||||
Substs::builder(num_args as usize + 1)
|
Substs::builder(num_args as usize + 1)
|
||||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
|
.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
|
||||||
.build(),
|
.build(),
|
||||||
|
|
|
@ -30,7 +30,8 @@ impl ToChalk for Ty {
|
||||||
Ty::Apply(apply_ty) => match apply_ty.ctor {
|
Ty::Apply(apply_ty) => match apply_ty.ctor {
|
||||||
TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters),
|
TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters),
|
||||||
TypeCtor::Array => array_to_chalk(db, apply_ty.parameters),
|
TypeCtor::Array => array_to_chalk(db, apply_ty.parameters),
|
||||||
TypeCtor::FnPtr { num_args: _ } => {
|
TypeCtor::FnPtr { num_args: _, is_varargs: _ } => {
|
||||||
|
// FIXME: handle is_varargs
|
||||||
let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner);
|
let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner);
|
||||||
chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution })
|
chalk_ir::TyData::Function(chalk_ir::Fn { num_binders: 0, substitution })
|
||||||
.intern(&Interner)
|
.intern(&Interner)
|
||||||
|
@ -124,7 +125,10 @@ impl ToChalk for Ty {
|
||||||
substitution.shifted_out(&Interner).expect("fn ptr should have no binders"),
|
substitution.shifted_out(&Interner).expect("fn ptr should have no binders"),
|
||||||
);
|
);
|
||||||
Ty::Apply(ApplicationTy {
|
Ty::Apply(ApplicationTy {
|
||||||
ctor: TypeCtor::FnPtr { num_args: (parameters.len() - 1) as u16 },
|
ctor: TypeCtor::FnPtr {
|
||||||
|
num_args: (parameters.len() - 1) as u16,
|
||||||
|
is_varargs: false,
|
||||||
|
},
|
||||||
parameters,
|
parameters,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue