Skip to content

Commit 338dc1f

Browse files
committed
Fix diagnostics spans for missing generics in edge cases
1 parent b1c8835 commit 338dc1f

File tree

1 file changed

+29
-28
lines changed

1 file changed

+29
-28
lines changed

compiler/rustc_typeck/src/structured_errors/wrong_number_of_generic_args.rs

+29-28
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,10 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
9494
gen_args: &'a hir::GenericArgs<'a>,
9595
def_id: DefId,
9696
) -> Self {
97-
let angle_brackets = if gen_args.is_empty() {
98-
AngleBrackets::Missing
97+
let angle_brackets = if gen_args.span_ext().is_none() {
98+
if gen_args.is_empty() { AngleBrackets::Missing } else { AngleBrackets::Implied }
9999
} else {
100-
if gen_args.span().is_none() {
101-
AngleBrackets::Implied
102-
} else {
103-
AngleBrackets::Available
104-
}
100+
AngleBrackets::Available
105101
};
106102

107103
Self {
@@ -337,7 +333,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
337333
),
338334
};
339335

340-
if self.gen_args.span().is_some() {
336+
if self.gen_args.span_ext().is_some() {
341337
format!(
342338
"this {} takes {}{} {} argument{} but {} {} supplied",
343339
def_kind,
@@ -579,27 +575,32 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
579575
err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders);
580576
}
581577
AngleBrackets::Available => {
582-
// angle brackets exist, so we just insert missing arguments after the existing
583-
// type or const args
584-
585-
let index_last_provided_arg =
586-
self.get_lifetime_args_offset() + self.num_provided_type_or_const_args() - 1;
587-
if index_last_provided_arg < self.gen_args.args.len() {
588-
let first_arg_span =
589-
self.gen_args.args[index_last_provided_arg].span().shrink_to_hi();
590-
let source_map = self.tcx.sess.source_map();
591-
if let Ok(first_gen_arg) = source_map.span_to_snippet(first_arg_span) {
592-
let sugg = format!("{}, {}", first_gen_arg, suggested_args);
593-
debug!("sugg: {:?}", sugg);
578+
let gen_args_span = self.gen_args.span().unwrap();
579+
let sugg_offset =
580+
self.get_lifetime_args_offset() + self.num_provided_type_or_const_args();
594581

595-
err.span_suggestion_verbose(
596-
first_arg_span,
597-
&msg,
598-
sugg,
599-
Applicability::HasPlaceholders,
600-
);
601-
}
602-
}
582+
let (sugg_span, is_first) = if sugg_offset == 0 {
583+
(gen_args_span.shrink_to_lo(), true)
584+
} else {
585+
let arg_span = self.gen_args.args[sugg_offset - 1].span();
586+
// If we came here then inferred lifetimes's spans can only point
587+
// to either the opening bracket or to the space right after.
588+
// Both of these spans have an `hi` lower than or equal to the span
589+
// of the generics excluding the brackets.
590+
// This allows us to check if `arg_span` is the artificial span of
591+
// an inferred lifetime, in which case the generic we're suggesting to
592+
// add will be the first visible, even if it isn't the actual first generic.
593+
(arg_span.shrink_to_hi(), arg_span.hi() <= gen_args_span.lo())
594+
};
595+
596+
let sugg_prefix = if is_first { "" } else { ", " };
597+
let sugg_suffix =
598+
if is_first && !self.gen_args.bindings.is_empty() { ", " } else { "" };
599+
600+
let sugg = format!("{}{}{}", sugg_prefix, suggested_args, sugg_suffix);
601+
debug!("sugg: {:?}", sugg);
602+
603+
err.span_suggestion_verbose(sugg_span, &msg, sugg, Applicability::HasPlaceholders);
603604
}
604605
}
605606
}

0 commit comments

Comments
 (0)