1
Fork 0

Fix diagnostics spans for missing generics in edge cases

This commit is contained in:
Giacomo Stevanato 2021-05-12 13:35:32 +02:00
parent b1c8835a0f
commit 338dc1f18c

View file

@ -94,14 +94,10 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
gen_args: &'a hir::GenericArgs<'a>, gen_args: &'a hir::GenericArgs<'a>,
def_id: DefId, def_id: DefId,
) -> Self { ) -> Self {
let angle_brackets = if gen_args.is_empty() { let angle_brackets = if gen_args.span_ext().is_none() {
AngleBrackets::Missing if gen_args.is_empty() { AngleBrackets::Missing } else { AngleBrackets::Implied }
} else { } else {
if gen_args.span().is_none() { AngleBrackets::Available
AngleBrackets::Implied
} else {
AngleBrackets::Available
}
}; };
Self { Self {
@ -337,7 +333,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
), ),
}; };
if self.gen_args.span().is_some() { if self.gen_args.span_ext().is_some() {
format!( format!(
"this {} takes {}{} {} argument{} but {} {} supplied", "this {} takes {}{} {} argument{} but {} {} supplied",
def_kind, def_kind,
@ -579,27 +575,32 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders); err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders);
} }
AngleBrackets::Available => { AngleBrackets::Available => {
// angle brackets exist, so we just insert missing arguments after the existing let gen_args_span = self.gen_args.span().unwrap();
// type or const args let sugg_offset =
self.get_lifetime_args_offset() + self.num_provided_type_or_const_args();
let index_last_provided_arg = let (sugg_span, is_first) = if sugg_offset == 0 {
self.get_lifetime_args_offset() + self.num_provided_type_or_const_args() - 1; (gen_args_span.shrink_to_lo(), true)
if index_last_provided_arg < self.gen_args.args.len() { } else {
let first_arg_span = let arg_span = self.gen_args.args[sugg_offset - 1].span();
self.gen_args.args[index_last_provided_arg].span().shrink_to_hi(); // If we came here then inferred lifetimes's spans can only point
let source_map = self.tcx.sess.source_map(); // to either the opening bracket or to the space right after.
if let Ok(first_gen_arg) = source_map.span_to_snippet(first_arg_span) { // Both of these spans have an `hi` lower than or equal to the span
let sugg = format!("{}, {}", first_gen_arg, suggested_args); // of the generics excluding the brackets.
debug!("sugg: {:?}", sugg); // This allows us to check if `arg_span` is the artificial span of
// an inferred lifetime, in which case the generic we're suggesting to
// add will be the first visible, even if it isn't the actual first generic.
(arg_span.shrink_to_hi(), arg_span.hi() <= gen_args_span.lo())
};
err.span_suggestion_verbose( let sugg_prefix = if is_first { "" } else { ", " };
first_arg_span, let sugg_suffix =
&msg, if is_first && !self.gen_args.bindings.is_empty() { ", " } else { "" };
sugg,
Applicability::HasPlaceholders, let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix);
); debug!("sugg: {:?}", sugg);
}
} err.span_suggestion_verbose(sugg_span, &msg, sugg, Applicability::HasPlaceholders);
} }
} }
} }