Skip to content

Commit d232acd

Browse files
committed
Report all errors in check_generic_arg_count
1 parent 2a50487 commit d232acd

File tree

3 files changed

+81
-85
lines changed

3 files changed

+81
-85
lines changed

src/librustc_typeck/astconv.rs

Lines changed: 77 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
287287
position: GenericArgPosition,
288288
has_self: bool,
289289
infer_args: bool,
290-
) -> (bool, Option<Vec<Span>>) {
290+
) -> (bool, Vec<Span>) {
291291
// At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
292292
// that lifetimes will proceed types. So it suffices to check the number of each generic
293293
// arguments in order to validate them with respect to the generic parameters.
@@ -341,104 +341,110 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
341341
}
342342
}
343343

344-
let check_kind_count = |kind, required, permitted, provided, offset| {
345-
debug!(
346-
"check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
347-
kind, required, permitted, provided, offset
348-
);
349-
// We enforce the following: `required` <= `provided` <= `permitted`.
350-
// For kinds without defaults (e.g.., lifetimes), `required == permitted`.
351-
// For other kinds (i.e., types), `permitted` may be greater than `required`.
352-
if required <= provided && provided <= permitted {
353-
return (reported_late_bound_region_err.unwrap_or(false), None);
354-
}
355-
356-
// Unfortunately lifetime and type parameter mismatches are typically styled
357-
// differently in diagnostics, which means we have a few cases to consider here.
358-
let (bound, quantifier) = if required != permitted {
359-
if provided < required {
360-
(required, "at least ")
361-
} else {
362-
// provided > permitted
363-
(permitted, "at most ")
344+
let check_kind_count =
345+
|kind, required, permitted, provided, offset, unexpected_spans: &mut Vec<Span>| {
346+
debug!(
347+
"check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
348+
kind, required, permitted, provided, offset
349+
);
350+
// We enforce the following: `required` <= `provided` <= `permitted`.
351+
// For kinds without defaults (e.g.., lifetimes), `required == permitted`.
352+
// For other kinds (i.e., types), `permitted` may be greater than `required`.
353+
if required <= provided && provided <= permitted {
354+
return false;
364355
}
365-
} else {
366-
(required, "")
367-
};
368356

369-
let mut potential_assoc_types: Option<Vec<Span>> = None;
370-
let (spans, label) = if required == permitted && provided > permitted {
371-
// In the case when the user has provided too many arguments,
372-
// we want to point to the unexpected arguments.
373-
let spans: Vec<Span> = args.args[offset + permitted..offset + provided]
374-
.iter()
375-
.map(|arg| arg.span())
376-
.collect();
377-
potential_assoc_types = Some(spans.clone());
378-
(spans, format!("unexpected {} argument", kind))
379-
} else {
380-
(
381-
vec![span],
382-
format!(
383-
"expected {}{} {} argument{}",
384-
quantifier,
385-
bound,
386-
kind,
387-
pluralize!(bound),
357+
// Unfortunately lifetime and type parameter mismatches are typically styled
358+
// differently in diagnostics, which means we have a few cases to consider here.
359+
let (bound, quantifier) = if required != permitted {
360+
if provided < required {
361+
(required, "at least ")
362+
} else {
363+
// provided > permitted
364+
(permitted, "at most ")
365+
}
366+
} else {
367+
(required, "")
368+
};
369+
370+
let (spans, label) = if required == permitted && provided > permitted {
371+
// In the case when the user has provided too many arguments,
372+
// we want to point to the unexpected arguments.
373+
let spans: Vec<Span> = args.args[offset + permitted..offset + provided]
374+
.iter()
375+
.map(|arg| arg.span())
376+
.collect();
377+
unexpected_spans.extend(spans.clone());
378+
(spans, format!("unexpected {} argument", kind))
379+
} else {
380+
(
381+
vec![span],
382+
format!(
383+
"expected {}{} {} argument{}",
384+
quantifier,
385+
bound,
386+
kind,
387+
pluralize!(bound),
388+
),
389+
)
390+
};
391+
392+
let mut err = tcx.sess.struct_span_err_with_code(
393+
spans.clone(),
394+
&format!(
395+
"wrong number of {} arguments: expected {}{}, found {}",
396+
kind, quantifier, bound, provided,
388397
),
389-
)
390-
};
398+
DiagnosticId::Error("E0107".into()),
399+
);
400+
for span in spans {
401+
err.span_label(span, label.as_str());
402+
}
403+
err.emit();
391404

392-
let mut err = tcx.sess.struct_span_err_with_code(
393-
spans.clone(),
394-
&format!(
395-
"wrong number of {} arguments: expected {}{}, found {}",
396-
kind, quantifier, bound, provided,
397-
),
398-
DiagnosticId::Error("E0107".into()),
399-
);
400-
for span in spans {
401-
err.span_label(span, label.as_str());
402-
}
403-
err.emit();
405+
true
406+
};
404407

405-
(true, potential_assoc_types)
406-
};
408+
let mut arg_count_mismatch = reported_late_bound_region_err.unwrap_or(false);
409+
let mut unexpected_spans = vec![];
407410

408411
if reported_late_bound_region_err.is_none()
409412
&& (!infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes)
410413
{
411-
check_kind_count(
414+
arg_count_mismatch |= check_kind_count(
412415
"lifetime",
413416
param_counts.lifetimes,
414417
param_counts.lifetimes,
415418
arg_counts.lifetimes,
416419
0,
420+
&mut unexpected_spans,
417421
);
418422
}
419423
// FIXME(const_generics:defaults)
420424
if !infer_args || arg_counts.consts > param_counts.consts {
421-
check_kind_count(
425+
arg_count_mismatch |= check_kind_count(
422426
"const",
423427
param_counts.consts,
424428
param_counts.consts,
425429
arg_counts.consts,
426430
arg_counts.lifetimes + arg_counts.types,
431+
&mut unexpected_spans,
427432
);
428433
}
429434
// Note that type errors are currently be emitted *after* const errors.
430435
if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize
431436
{
432-
check_kind_count(
437+
arg_count_mismatch |= check_kind_count(
433438
"type",
434439
param_counts.types - defaults.types - has_self as usize,
435440
param_counts.types - has_self as usize,
436441
arg_counts.types,
437442
arg_counts.lifetimes,
438-
)
439-
} else {
440-
(reported_late_bound_region_err.unwrap_or(false), None)
443+
&mut unexpected_spans,
444+
);
441445
}
446+
447+
(arg_count_mismatch, unexpected_spans)
442448
}
443449

444450
/// Creates the relevant generic argument substitutions
@@ -627,7 +633,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
627633
generic_args: &'a hir::GenericArgs<'_>,
628634
infer_args: bool,
629635
self_ty: Option<Ty<'tcx>>,
630-
) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Option<Vec<Span>>) {
636+
) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Vec<Span>) {
631637
// If the type is parameterized by this region, then replace this
632638
// region with the current anon region binding (in other words,
633639
// whatever & would get replaced with).
@@ -922,7 +928,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
922928
self_ty: Ty<'tcx>,
923929
bounds: &mut Bounds<'tcx>,
924930
speculative: bool,
925-
) -> Option<Vec<Span>> {
931+
) -> Vec<Span> {
926932
let trait_def_id = trait_ref.trait_def_id();
927933

928934
debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
@@ -968,6 +974,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
968974
"instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}",
969975
trait_ref, bounds, poly_trait_ref
970976
);
977+
971978
potential_assoc_types
972979
}
973980

@@ -996,7 +1003,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
9961003
constness: Constness,
9971004
self_ty: Ty<'tcx>,
9981005
bounds: &mut Bounds<'tcx>,
999-
) -> Option<Vec<Span>> {
1006+
) -> Vec<Span> {
10001007
self.instantiate_poly_trait_ref_inner(
10011008
&poly_trait_ref.trait_ref,
10021009
poly_trait_ref.span,
@@ -1085,7 +1092,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10851092
trait_def_id: DefId,
10861093
self_ty: Ty<'tcx>,
10871094
trait_segment: &'a hir::PathSegment<'a>,
1088-
) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Option<Vec<Span>>) {
1095+
) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Vec<Span>) {
10891096
debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment);
10901097

10911098
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
@@ -1436,7 +1443,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
14361443
dummy_self,
14371444
&mut bounds,
14381445
);
1439-
potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten());
1446+
potential_assoc_types.extend(cur_potential_assoc_types.into_iter());
14401447
}
14411448

14421449
// Expand trait aliases recursively and check that only one regular (non-auto) trait

src/test/ui/generic/generic-arg-mismatch-recover.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ struct Bar<'a>(&'a ());
44

55
fn main() {
66
Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments
7-
//~^ ERROR mismatched types
87

98
Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments
109
//~^ ERROR wrong number of type arguments

src/test/ui/generic/generic-arg-mismatch-recover.stderr

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,18 @@ error[E0107]: wrong number of lifetime arguments: expected 1, found 2
44
LL | Foo::<'static, 'static, ()>(&0);
55
| ^^^^^^^ unexpected lifetime argument
66

7-
error[E0308]: mismatched types
8-
--> $DIR/generic-arg-mismatch-recover.rs:6:33
9-
|
10-
LL | Foo::<'static, 'static, ()>(&0);
11-
| ^^ expected `()`, found integer
12-
|
13-
= note: expected reference `&'static ()`
14-
found reference `&{integer}`
15-
167
error[E0107]: wrong number of lifetime arguments: expected 1, found 2
17-
--> $DIR/generic-arg-mismatch-recover.rs:9:20
8+
--> $DIR/generic-arg-mismatch-recover.rs:8:20
189
|
1910
LL | Bar::<'static, 'static, ()>(&());
2011
| ^^^^^^^ unexpected lifetime argument
2112

2213
error[E0107]: wrong number of type arguments: expected 0, found 1
23-
--> $DIR/generic-arg-mismatch-recover.rs:9:29
14+
--> $DIR/generic-arg-mismatch-recover.rs:8:29
2415
|
2516
LL | Bar::<'static, 'static, ()>(&());
2617
| ^^ unexpected type argument
2718

28-
error: aborting due to 4 previous errors
19+
error: aborting due to 3 previous errors
2920

30-
Some errors have detailed explanations: E0107, E0308.
31-
For more information about an error, try `rustc --explain E0107`.
21+
For more information about this error, try `rustc --explain E0107`.

0 commit comments

Comments
 (0)