From f2fa456a8cbf08520d919a547ae66412562c2bf8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 25 Jul 2024 11:02:19 +0200 Subject: [PATCH] Fix incorrect handling of cfg'd varargs --- crates/hir-def/src/data.rs | 13 ++++++++++++- crates/hir-def/src/item_tree.rs | 2 +- crates/hir-def/src/item_tree/lower.rs | 6 +++--- crates/hir-def/src/item_tree/pretty.rs | 2 +- crates/hir-ty/src/infer.rs | 4 +--- crates/hir-ty/src/tests/patterns.rs | 17 +++++++++++++++++ crates/hir/src/display.rs | 8 +------- crates/intern/src/symbol/symbols.rs | 1 + 8 files changed, 37 insertions(+), 16 deletions(-) diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs index a03140e2a9..3f862f69f8 100644 --- a/crates/hir-def/src/data.rs +++ b/crates/hir-def/src/data.rs @@ -73,6 +73,17 @@ impl FunctionData { flags.remove(FnFlags::HAS_SELF_PARAM); } } + if flags.contains(FnFlags::IS_VARARGS) { + if let Some((_, param)) = func.params.iter().enumerate().rev().find(|&(idx, _)| { + item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options) + }) { + if param.type_ref.is_some() { + flags.remove(FnFlags::IS_VARARGS); + } + } else { + flags.remove(FnFlags::IS_VARARGS); + } + } let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let legacy_const_generics_indices = attrs @@ -92,7 +103,7 @@ impl FunctionData { .filter(|&(idx, _)| { item_tree.attrs(db, krate, attr_owner(idx)).is_cfg_enabled(cfg_options) }) - .map(|(_, param)| param.type_ref.clone()) + .filter_map(|(_, param)| param.type_ref.clone()) .collect(), ret_type: func.ret_type.clone(), attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index f6709680d0..28eebb286e 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -741,7 +741,7 @@ pub struct Function { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Param { - pub type_ref: Interned, + pub type_ref: Option>, } bitflags::bitflags! { diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index c9e9719c90..7aac383ab4 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -380,7 +380,7 @@ impl<'a> Ctx<'a> { } }; let type_ref = Interned::new(self_type); - params.push(Param { type_ref }); + params.push(Param { type_ref: Some(type_ref) }); has_self_param = true; } for param in param_list.params() { @@ -388,12 +388,12 @@ impl<'a> Ctx<'a> { let param = match param.dotdotdot_token() { Some(_) => { has_var_args = true; - Param { type_ref: Interned::new(TypeRef::Error) } + Param { type_ref: None } } None => { let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); let ty = Interned::new(type_ref); - Param { type_ref: ty } + Param { type_ref: Some(ty) } } }; params.push(param); diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs index 5eeb8607b9..740759e6e3 100644 --- a/crates/hir-def/src/item_tree/pretty.rs +++ b/crates/hir-def/src/item_tree/pretty.rs @@ -291,7 +291,7 @@ impl Printer<'_> { if idx == 0 && flags.contains(FnFlags::HAS_SELF_PARAM) { w!(this, "self: "); } - if idx != params.len() { + if let Some(type_ref) = type_ref { this.print_type_ref(type_ref); } else { wln!(this, "..."); diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs index 284291bb9a..804bc53905 100644 --- a/crates/hir-ty/src/infer.rs +++ b/crates/hir-ty/src/infer.rs @@ -812,9 +812,7 @@ impl<'a> InferenceContext<'a> { None => self.err_ty(), }; - if let Some(ty) = param_tys.last_mut() { - *ty = va_list_ty; - } + param_tys.push(va_list_ty); } let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.new_type_var())); if let Some(self_param) = self.body.self_param { diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs index 1c1f7055ef..57866acc06 100644 --- a/crates/hir-ty/src/tests/patterns.rs +++ b/crates/hir-ty/src/tests/patterns.rs @@ -1126,6 +1126,23 @@ fn var_args() { pub struct VaListImpl<'f>; fn my_fn(foo: ...) {} //^^^ VaListImpl<'?> +fn my_fn2(bar: u32, foo: ...) {} + //^^^ VaListImpl<'?> +"#, + ); +} + +#[test] +fn var_args_cond() { + check_types( + r#" +#[lang = "va_list"] +pub struct VaListImpl<'f>; +fn my_fn(bar: u32, #[cfg(FALSE)] foo: ..., #[cfg(not(FALSE))] foo: u32) { + foo; + //^^^ u32 + +} "#, ); } diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index a40022c43a..7def828e95 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -99,13 +99,7 @@ impl HirDisplay for Function { } // FIXME: Use resolved `param.ty` once we no longer discard lifetimes - for (type_ref, param) in data - .params - .iter() - .zip(self.assoc_fn_params(db)) - .take(data.params.len() - data.is_varargs() as usize) - .skip(skip_self) - { + for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) { let local = param.as_local(db).map(|it| it.name(db)); if !first { f.write_str(", ")?; diff --git a/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs index d810fac36a..2feca32ff8 100644 --- a/crates/intern/src/symbol/symbols.rs +++ b/crates/intern/src/symbol/symbols.rs @@ -56,6 +56,7 @@ macro_rules! define_symbols { define_symbols! { @WITH_NAME: + dotdotdot = "...", INTEGER_0 = "0", INTEGER_1 = "1", INTEGER_2 = "2",