Add two new diagnostics: one for mismatch in generic arguments count, and another for mismatch in their kind

Also known as E0747 and E0107.

And by the way, rewrite how we lower generic arguments and deduplicate it between paths and method calls. The new version is taken almost straight from rustc.

This commit also changes the binders of `generic_defaults()`, to only include the binders of the arguments up to (and not including) the current argument. This make it easier to handle it in the rewritten lowering of generic args. It's also how rustc does it.
This commit is contained in:
Chayim Refael Friedman 2025-03-30 20:20:24 +03:00
parent 2b4b483af1
commit 99ce53b1d7
22 changed files with 1247 additions and 409 deletions

View file

@ -788,6 +788,7 @@ impl ExprCollector<'_> {
node: ast::GenericArgList,
impl_trait_lower_fn: &mut impl FnMut(ThinVec<TypeBound>) -> TypeRef,
) -> Option<GenericArgs> {
// This needs to be kept in sync with `hir_generic_arg_to_ast()`.
let mut args = Vec::new();
let mut bindings = Vec::new();
for generic_arg in node.generic_args() {
@ -797,6 +798,7 @@ impl ExprCollector<'_> {
args.push(GenericArg::Type(type_ref));
}
ast::GenericArg::AssocTypeArg(assoc_type_arg) => {
// This needs to be kept in sync with `hir_assoc_type_binding_to_ast()`.
if assoc_type_arg.param_list().is_some() {
// We currently ignore associated return type bounds.
continue;
@ -3228,3 +3230,33 @@ enum ArgumentType {
Format(FormatTrait),
Usize,
}
/// This function find the AST fragment that corresponds to an `AssociatedTypeBinding` in the HIR.
pub fn hir_assoc_type_binding_to_ast(
segment_args: &ast::GenericArgList,
binding_idx: u32,
) -> Option<ast::AssocTypeArg> {
segment_args
.generic_args()
.filter_map(|arg| match arg {
ast::GenericArg::AssocTypeArg(it) => Some(it),
_ => None,
})
.filter(|binding| binding.param_list().is_none() && binding.name_ref().is_some())
.nth(binding_idx as usize)
}
/// This function find the AST generic argument from the one in the HIR. Does not support the `Self` argument.
pub fn hir_generic_arg_to_ast(
args: &ast::GenericArgList,
arg_idx: u32,
has_self_arg: bool,
) -> Option<ast::GenericArg> {
args.generic_args()
.filter(|arg| match arg {
ast::GenericArg::AssocTypeArg(_) => false,
ast::GenericArg::LifetimeArg(arg) => arg.lifetime().is_some(),
ast::GenericArg::ConstArg(_) | ast::GenericArg::TypeArg(_) => true,
})
.nth(arg_idx as usize - has_self_arg as usize)
}

View file

@ -152,10 +152,8 @@ pub(super) fn lower_path(
args: iter::once(self_type)
.chain(it.args.iter().cloned())
.collect(),
has_self_type: true,
bindings: it.bindings.clone(),
parenthesized: it.parenthesized,
..it
},
None => GenericArgs {
args: Box::new([self_type]),