Skip to content

Commit 7f28b49

Browse files
bors[bot]Jonas Schievink
andauthored
Merge #11043
11043: fix: fix incorrect mismatched argument count diagnostic with `std::arch` functions r=jonas-schievink a=jonas-schievink Adds basic support for `#[rustc_legacy_const_generics]`. Fixes #10009 Full support would involve actually checking call arguments against the right expected types. bors r+ Co-authored-by: Jonas Schievink <[email protected]>
2 parents 6674756 + fcc76e9 commit 7f28b49

File tree

5 files changed

+110
-15
lines changed

5 files changed

+110
-15
lines changed

crates/hir_def/src/data.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub struct FunctionData {
2626
pub attrs: Attrs,
2727
pub visibility: RawVisibility,
2828
pub abi: Option<Interned<str>>,
29+
pub legacy_const_generics_indices: Vec<u32>,
2930
flags: FnFlags,
3031
}
3132

@@ -58,6 +59,14 @@ impl FunctionData {
5859
flags.bits |= FnFlags::IS_IN_EXTERN_BLOCK;
5960
}
6061

62+
let legacy_const_generics_indices = item_tree
63+
.attrs(db, krate, ModItem::from(loc.id.value).into())
64+
.by_key("rustc_legacy_const_generics")
65+
.tt_values()
66+
.next()
67+
.map(|arg| parse_rustc_legacy_const_generics(arg))
68+
.unwrap_or_default();
69+
6170
Arc::new(FunctionData {
6271
name: func.name.clone(),
6372
params: enabled_params
@@ -72,6 +81,7 @@ impl FunctionData {
7281
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
7382
visibility: item_tree[func.visibility].clone(),
7483
abi: func.abi.clone(),
84+
legacy_const_generics_indices,
7585
flags,
7686
})
7787
}
@@ -111,6 +121,28 @@ impl FunctionData {
111121
}
112122
}
113123

124+
fn parse_rustc_legacy_const_generics(tt: &tt::Subtree) -> Vec<u32> {
125+
let mut indices = Vec::new();
126+
for args in tt.token_trees.chunks(2) {
127+
match &args[0] {
128+
tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => match lit.text.parse() {
129+
Ok(index) => indices.push(index),
130+
Err(_) => break,
131+
},
132+
_ => break,
133+
}
134+
135+
if let Some(comma) = args.get(1) {
136+
match comma {
137+
tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.char == ',' => {}
138+
_ => break,
139+
}
140+
}
141+
}
142+
143+
indices
144+
}
145+
114146
#[derive(Debug, Clone, PartialEq, Eq)]
115147
pub struct TypeAliasData {
116148
pub name: Name,

crates/hir_ty/src/diagnostics/expr.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -235,20 +235,33 @@ impl ExprValidator {
235235
return;
236236
}
237237

238-
let params = sig.params();
238+
if sig.legacy_const_generics_indices.is_empty() {
239+
let mut param_count = sig.params().len();
239240

240-
let mut param_count = params.len();
241-
242-
if arg_count != param_count {
243-
if is_method_call {
244-
param_count -= 1;
245-
arg_count -= 1;
241+
if arg_count != param_count {
242+
if is_method_call {
243+
param_count -= 1;
244+
arg_count -= 1;
245+
}
246+
self.diagnostics.push(BodyValidationDiagnostic::MismatchedArgCount {
247+
call_expr: call_id,
248+
expected: param_count,
249+
found: arg_count,
250+
});
251+
}
252+
} else {
253+
// With `#[rustc_legacy_const_generics]` there are basically two parameter counts that
254+
// are allowed.
255+
let count_non_legacy = sig.params().len();
256+
let count_legacy = sig.params().len() + sig.legacy_const_generics_indices.len();
257+
if arg_count != count_non_legacy && arg_count != count_legacy {
258+
self.diagnostics.push(BodyValidationDiagnostic::MismatchedArgCount {
259+
call_expr: call_id,
260+
// Since most users will use the legacy way to call them, report against that.
261+
expected: count_legacy,
262+
found: arg_count,
263+
});
246264
}
247-
self.diagnostics.push(BodyValidationDiagnostic::MismatchedArgCount {
248-
call_expr: call_id,
249-
expected: param_count,
250-
found: arg_count,
251-
});
252265
}
253266
}
254267

crates/hir_ty/src/lib.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ pub fn make_canonical<T: HasInterner<Interner = Interner>>(
175175
pub struct CallableSig {
176176
params_and_return: Arc<[Ty]>,
177177
is_varargs: bool,
178+
legacy_const_generics_indices: Arc<[u32]>,
178179
}
179180

180181
has_interner!(CallableSig);
@@ -185,7 +186,11 @@ pub type PolyFnSig = Binders<CallableSig>;
185186
impl CallableSig {
186187
pub fn from_params_and_return(mut params: Vec<Ty>, ret: Ty, is_varargs: bool) -> CallableSig {
187188
params.push(ret);
188-
CallableSig { params_and_return: params.into(), is_varargs }
189+
CallableSig {
190+
params_and_return: params.into(),
191+
is_varargs,
192+
legacy_const_generics_indices: Arc::new([]),
193+
}
189194
}
190195

191196
pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
@@ -202,9 +207,14 @@ impl CallableSig {
202207
.map(|arg| arg.assert_ty_ref(&Interner).clone())
203208
.collect(),
204209
is_varargs: fn_ptr.sig.variadic,
210+
legacy_const_generics_indices: Arc::new([]),
205211
}
206212
}
207213

214+
pub fn set_legacy_const_generics_indices(&mut self, indices: &[u32]) {
215+
self.legacy_const_generics_indices = indices.into();
216+
}
217+
208218
pub fn to_fn_ptr(&self) -> FnPointer {
209219
FnPointer {
210220
num_binders: 0,
@@ -238,7 +248,11 @@ impl Fold<Interner> for CallableSig {
238248
{
239249
let vec = self.params_and_return.to_vec();
240250
let folded = vec.fold_with(folder, outer_binder)?;
241-
Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
251+
Ok(CallableSig {
252+
params_and_return: folded.into(),
253+
is_varargs: self.is_varargs,
254+
legacy_const_generics_indices: self.legacy_const_generics_indices,
255+
})
242256
}
243257
}
244258

crates/hir_ty/src/lower.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1286,7 +1286,11 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
12861286
.with_type_param_mode(TypeParamLoweringMode::Variable);
12871287
let ret = ctx_ret.lower_ty(&data.ret_type);
12881288
let generics = generics(db.upcast(), def.into());
1289-
make_binders(&generics, CallableSig::from_params_and_return(params, ret, data.is_varargs()))
1289+
let mut sig = CallableSig::from_params_and_return(params, ret, data.is_varargs());
1290+
if !data.legacy_const_generics_indices.is_empty() {
1291+
sig.set_legacy_const_generics_indices(&data.legacy_const_generics_indices);
1292+
}
1293+
make_binders(&generics, sig)
12901294
}
12911295

12921296
/// Build the declared type of a function. This should not need to look at the

crates/ide_diagnostics/src/handlers/mismatched_arg_count.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,38 @@ fn main() {
305305
fixed(0);
306306
varargs(1, 2, 3);
307307
}
308+
}
309+
"#,
310+
)
311+
}
312+
313+
#[test]
314+
fn legacy_const_generics() {
315+
check_diagnostics(
316+
r#"
317+
#[rustc_legacy_const_generics(1, 3)]
318+
fn mixed<const N1: &'static str, const N2: bool>(
319+
a: u8,
320+
b: i8,
321+
) {}
322+
323+
fn f() {
324+
mixed(0, "", -1, true);
325+
mixed::<"", true>(0, -1);
326+
}
327+
328+
#[rustc_legacy_const_generics(1, 3)]
329+
fn b<const N1: u8, const N2: u8>(
330+
a: u8,
331+
b: u8,
332+
) {}
333+
334+
fn g() {
335+
b(0, 1, 2, 3);
336+
b::<1, 3>(0, 2);
337+
338+
b(0, 1, 2);
339+
//^ error: expected 4 arguments, found 3
308340
}
309341
"#,
310342
)

0 commit comments

Comments
 (0)