Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit fa351ee

Browse files
committedMay 28, 2020
Fix ICE with explicit late-bound lifetimes
1 parent 4512721 commit fa351ee

File tree

5 files changed

+241
-131
lines changed

5 files changed

+241
-131
lines changed
 

‎src/librustc_typeck/astconv.rs

Lines changed: 187 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,22 @@ enum ConvertedBindingKind<'a, 'tcx> {
123123
Constraint(&'a [hir::GenericBound<'a>]),
124124
}
125125

126-
#[derive(PartialEq)]
126+
/// New-typed boolean indicating whether explicit late-bound lifetimes
127+
/// are present in a set of generic arguments.
128+
///
129+
/// For example if we have some method `fn f<'a>(&'a self)` implemented
130+
/// for some type `T`, although `f` is generic in the lifetime `'a`, `'a`
131+
/// is late-bound so should not be provided explicitly. Thus, if `f` is
132+
/// instantiated with some generic arguments providing `'a` explicitly,
133+
/// we taint those arguments with `ExplicitLateBound::Yes` so that we
134+
/// can provide an appropriate diagnostic later.
135+
#[derive(Copy, Clone, PartialEq)]
136+
pub enum ExplicitLateBound {
137+
Yes,
138+
No,
139+
}
140+
141+
#[derive(Copy, Clone, PartialEq)]
127142
enum GenericArgPosition {
128143
Type,
129144
Value, // e.g., functions
@@ -132,13 +147,22 @@ enum GenericArgPosition {
132147

133148
/// A marker denoting that the generic arguments that were
134149
/// provided did not match the respective generic parameters.
150+
#[derive(Clone, Default)]
135151
pub struct GenericArgCountMismatch {
136152
/// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
137153
pub reported: Option<ErrorReported>,
138154
/// A list of spans of arguments provided that were not valid.
139155
pub invalid_args: Vec<Span>,
140156
}
141157

158+
/// Decorates the result of a generic argument count mismatch
159+
/// check with whether explicit late bounds were provided.
160+
#[derive(Clone)]
161+
pub struct GenericArgCountResult {
162+
pub explicit_late_bound: ExplicitLateBound,
163+
pub correct: Result<(), GenericArgCountMismatch>,
164+
}
165+
142166
impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
143167
pub fn ast_region_to_region(
144168
&self,
@@ -271,7 +295,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
271295
def: &ty::Generics,
272296
seg: &hir::PathSegment<'_>,
273297
is_method_call: bool,
274-
) -> Result<(), GenericArgCountMismatch> {
298+
) -> GenericArgCountResult {
275299
let empty_args = hir::GenericArgs::none();
276300
let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def);
277301
Self::check_generic_arg_count(
@@ -295,7 +319,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
295319
position: GenericArgPosition,
296320
has_self: bool,
297321
infer_args: bool,
298-
) -> Result<(), GenericArgCountMismatch> {
322+
) -> GenericArgCountResult {
299323
// At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
300324
// that lifetimes will proceed types. So it suffices to check the number of each generic
301325
// arguments in order to validate them with respect to the generic parameters.
@@ -320,112 +344,94 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
320344
AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span);
321345
}
322346

323-
// Prohibit explicit lifetime arguments if late-bound lifetime parameters are present.
324-
let mut explicit_lifetimes = Ok(());
325-
if !infer_lifetimes {
326-
if let Some(span_late) = def.has_late_bound_regions {
327-
let msg = "cannot specify lifetime arguments explicitly \
328-
if late bound lifetime parameters are present";
329-
let note = "the late bound lifetime parameter is introduced here";
330-
let span = args.args[0].span();
331-
if position == GenericArgPosition::Value
332-
&& arg_counts.lifetimes != param_counts.lifetimes
333-
{
334-
explicit_lifetimes = Err(true);
335-
let mut err = tcx.sess.struct_span_err(span, msg);
336-
err.span_note(span_late, note);
337-
err.emit();
338-
} else {
339-
explicit_lifetimes = Err(false);
340-
let mut multispan = MultiSpan::from_span(span);
341-
multispan.push_span_label(span_late, note.to_string());
342-
tcx.struct_span_lint_hir(
343-
LATE_BOUND_LIFETIME_ARGUMENTS,
344-
args.args[0].id(),
345-
multispan,
346-
|lint| lint.build(msg).emit(),
347-
);
348-
}
347+
let explicit_late_bound =
348+
Self::prohibit_explicit_late_bound_lifetimes(tcx, def, args, position);
349+
350+
let check_kind_count = |kind,
351+
required,
352+
permitted,
353+
provided,
354+
offset,
355+
unexpected_spans: &mut Vec<Span>,
356+
silent| {
357+
debug!(
358+
"check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
359+
kind, required, permitted, provided, offset
360+
);
361+
// We enforce the following: `required` <= `provided` <= `permitted`.
362+
// For kinds without defaults (e.g.., lifetimes), `required == permitted`.
363+
// For other kinds (i.e., types), `permitted` may be greater than `required`.
364+
if required <= provided && provided <= permitted {
365+
return Ok(());
349366
}
350-
}
351367

352-
let check_kind_count =
353-
|kind, required, permitted, provided, offset, unexpected_spans: &mut Vec<Span>| {
354-
debug!(
355-
"check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
356-
kind, required, permitted, provided, offset
357-
);
358-
// We enforce the following: `required` <= `provided` <= `permitted`.
359-
// For kinds without defaults (e.g.., lifetimes), `required == permitted`.
360-
// For other kinds (i.e., types), `permitted` may be greater than `required`.
361-
if required <= provided && provided <= permitted {
362-
return Ok(());
363-
}
364-
365-
// Unfortunately lifetime and type parameter mismatches are typically styled
366-
// differently in diagnostics, which means we have a few cases to consider here.
367-
let (bound, quantifier) = if required != permitted {
368-
if provided < required {
369-
(required, "at least ")
370-
} else {
371-
// provided > permitted
372-
(permitted, "at most ")
373-
}
374-
} else {
375-
(required, "")
376-
};
368+
if silent {
369+
return Err(true);
370+
}
377371

378-
let (spans, label) = if required == permitted && provided > permitted {
379-
// In the case when the user has provided too many arguments,
380-
// we want to point to the unexpected arguments.
381-
let spans: Vec<Span> = args.args[offset + permitted..offset + provided]
382-
.iter()
383-
.map(|arg| arg.span())
384-
.collect();
385-
unexpected_spans.extend(spans.clone());
386-
(spans, format!("unexpected {} argument", kind))
372+
// Unfortunately lifetime and type parameter mismatches are typically styled
373+
// differently in diagnostics, which means we have a few cases to consider here.
374+
let (bound, quantifier) = if required != permitted {
375+
if provided < required {
376+
(required, "at least ")
387377
} else {
388-
(
389-
vec![span],
390-
format!(
391-
"expected {}{} {} argument{}",
392-
quantifier,
393-
bound,
394-
kind,
395-
pluralize!(bound),
396-
),
397-
)
398-
};
399-
400-
let mut err = tcx.sess.struct_span_err_with_code(
401-
spans.clone(),
402-
&format!(
403-
"wrong number of {} arguments: expected {}{}, found {}",
404-
kind, quantifier, bound, provided,
405-
),
406-
DiagnosticId::Error("E0107".into()),
407-
);
408-
for span in spans {
409-
err.span_label(span, label.as_str());
378+
// provided > permitted
379+
(permitted, "at most ")
410380
}
411-
err.emit();
381+
} else {
382+
(required, "")
383+
};
412384

413-
Err(true)
385+
let (spans, label) = if required == permitted && provided > permitted {
386+
// In the case when the user has provided too many arguments,
387+
// we want to point to the unexpected arguments.
388+
let spans: Vec<Span> = args.args[offset + permitted..offset + provided]
389+
.iter()
390+
.map(|arg| arg.span())
391+
.collect();
392+
unexpected_spans.extend(spans.clone());
393+
(spans, format!("unexpected {} argument", kind))
394+
} else {
395+
(
396+
vec![span],
397+
format!(
398+
"expected {}{} {} argument{}",
399+
quantifier,
400+
bound,
401+
kind,
402+
pluralize!(bound),
403+
),
404+
)
414405
};
415406

416-
let mut arg_count_correct = explicit_lifetimes;
407+
let mut err = tcx.sess.struct_span_err_with_code(
408+
spans.clone(),
409+
&format!(
410+
"wrong number of {} arguments: expected {}{}, found {}",
411+
kind, quantifier, bound, provided,
412+
),
413+
DiagnosticId::Error("E0107".into()),
414+
);
415+
for span in spans {
416+
err.span_label(span, label.as_str());
417+
}
418+
err.emit();
419+
420+
Err(true)
421+
};
422+
423+
let mut arg_count_correct = Ok(());
417424
let mut unexpected_spans = vec![];
418425

419-
if arg_count_correct.is_ok()
420-
&& (!infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes)
421-
{
426+
if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes {
422427
arg_count_correct = check_kind_count(
423428
"lifetime",
424429
param_counts.lifetimes,
425430
param_counts.lifetimes,
426431
arg_counts.lifetimes,
427432
0,
428433
&mut unexpected_spans,
434+
explicit_late_bound == ExplicitLateBound::Yes,
429435
)
430436
.and(arg_count_correct);
431437
}
@@ -438,6 +444,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
438444
arg_counts.consts,
439445
arg_counts.lifetimes + arg_counts.types,
440446
&mut unexpected_spans,
447+
false,
441448
)
442449
.and(arg_count_correct);
443450
}
@@ -451,14 +458,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
451458
arg_counts.types,
452459
arg_counts.lifetimes,
453460
&mut unexpected_spans,
461+
false,
454462
)
455463
.and(arg_count_correct);
456464
}
457465

458-
arg_count_correct.map_err(|reported_err| GenericArgCountMismatch {
459-
reported: if reported_err { Some(ErrorReported) } else { None },
460-
invalid_args: unexpected_spans,
461-
})
466+
GenericArgCountResult {
467+
explicit_late_bound,
468+
correct: arg_count_correct.map_err(|reported_err| GenericArgCountMismatch {
469+
reported: if reported_err { Some(ErrorReported) } else { None },
470+
invalid_args: unexpected_spans,
471+
}),
472+
}
462473
}
463474

464475
/// Report an error that a generic argument did not match the generic parameter that was
@@ -512,7 +523,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
512523
parent_substs: &[subst::GenericArg<'tcx>],
513524
has_self: bool,
514525
self_ty: Option<Ty<'tcx>>,
515-
arg_count_correct: bool,
526+
arg_count: GenericArgCountResult,
516527
args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool),
517528
mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>,
518529
mut inferred_kind: impl FnMut(
@@ -585,30 +596,40 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
585596
// input. We try to handle both sensibly.
586597
match (args.peek(), params.peek()) {
587598
(Some(&arg), Some(&param)) => {
588-
match (arg, &param.kind) {
589-
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime)
590-
| (GenericArg::Type(_), GenericParamDefKind::Type { .. })
591-
| (GenericArg::Const(_), GenericParamDefKind::Const) => {
599+
match (arg, &param.kind, arg_count.explicit_late_bound) {
600+
(GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
601+
| (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _)
602+
| (GenericArg::Const(_), GenericParamDefKind::Const, _) => {
592603
substs.push(provided_kind(param, arg));
593604
args.next();
594605
params.next();
595606
}
596607
(
597608
GenericArg::Type(_) | GenericArg::Const(_),
598609
GenericParamDefKind::Lifetime,
610+
_,
599611
) => {
600612
// We expected a lifetime argument, but got a type or const
601613
// argument. That means we're inferring the lifetimes.
602614
substs.push(inferred_kind(None, param, infer_args));
603615
force_infer_lt = Some(arg);
604616
params.next();
605617
}
606-
(_, kind) => {
618+
(GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
619+
// We've come across a lifetime when we expected something else in
620+
// the presence of explicit late bounds. This is most likely
621+
// due to the presence of the explicit bound so we're just going to
622+
// ignore it.
623+
args.next();
624+
}
625+
(_, kind, _) => {
607626
// We expected one kind of parameter, but the user provided
608627
// another. This is an error. However, if we already know that
609628
// the arguments don't match up with the parameters, we won't issue
610629
// an additional error, as the user already knows what's wrong.
611-
if arg_count_correct {
630+
if arg_count.correct.is_ok()
631+
&& arg_count.explicit_late_bound == ExplicitLateBound::No
632+
{
612633
Self::generic_arg_mismatch_err(tcx.sess, arg, kind.descr());
613634
}
614635

@@ -624,17 +645,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
624645

625646
(Some(&arg), None) => {
626647
// We should never be able to reach this point with well-formed input.
627-
// There are two situations in which we can encounter this issue.
648+
// There are three situations in which we can encounter this issue.
628649
//
629650
// 1. The number of arguments is incorrect. In this case, an error
630-
// will already have been emitted, and we can ignore it. This case
631-
// also occurs when late-bound lifetime parameters are present, yet
632-
// the lifetime arguments have also been explicitly specified by the
651+
// will already have been emitted, and we can ignore it.
652+
// 2. There are late-bound lifetime parameters present, yet the
653+
// lifetime arguments have also been explicitly specified by the
633654
// user.
634-
// 2. We've inferred some lifetimes, which have been provided later (i.e.
655+
// 3. We've inferred some lifetimes, which have been provided later (i.e.
635656
// after a type or const). We want to throw an error in this case.
636657

637-
if arg_count_correct {
658+
if arg_count.correct.is_ok()
659+
&& arg_count.explicit_late_bound == ExplicitLateBound::No
660+
{
638661
let kind = arg.descr();
639662
assert_eq!(kind, "lifetime");
640663
let provided =
@@ -699,8 +722,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
699722
generic_args: &'a hir::GenericArgs<'_>,
700723
infer_args: bool,
701724
self_ty: Option<Ty<'tcx>>,
702-
) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Result<(), GenericArgCountMismatch>)
703-
{
725+
) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
704726
// If the type is parameterized by this region, then replace this
705727
// region with the current anon region binding (in other words,
706728
// whatever & would get replaced with).
@@ -726,7 +748,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
726748
assert!(self_ty.is_none() && parent_substs.is_empty());
727749
}
728750

729-
let arg_count_correct = Self::check_generic_arg_count(
751+
let arg_count = Self::check_generic_arg_count(
730752
tcx,
731753
span,
732754
&generic_params,
@@ -761,7 +783,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
761783
parent_substs,
762784
self_ty.is_some(),
763785
self_ty,
764-
arg_count_correct.is_ok(),
786+
arg_count.clone(),
765787
// Provide the generic args, and whether types should be inferred.
766788
|did| {
767789
if did == def_id {
@@ -880,7 +902,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
880902
generic_params, self_ty, substs
881903
);
882904

883-
(substs, assoc_bindings, arg_count_correct)
905+
(substs, assoc_bindings, arg_count)
884906
}
885907

886908
crate fn create_substs_for_associated_item(
@@ -1011,14 +1033,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10111033
self_ty: Ty<'tcx>,
10121034
bounds: &mut Bounds<'tcx>,
10131035
speculative: bool,
1014-
) -> Result<(), GenericArgCountMismatch> {
1036+
) -> GenericArgCountResult {
10151037
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
10161038

10171039
debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
10181040

10191041
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
10201042

1021-
let (substs, assoc_bindings, arg_count_correct) = self.create_substs_for_ast_trait_ref(
1043+
let (substs, assoc_bindings, arg_count) = self.create_substs_for_ast_trait_ref(
10221044
trait_ref.path.span,
10231045
trait_def_id,
10241046
self_ty,
@@ -1048,7 +1070,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10481070
trait_ref, bounds, poly_trait_ref
10491071
);
10501072

1051-
arg_count_correct
1073+
arg_count
10521074
}
10531075

10541076
/// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
@@ -1076,7 +1098,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10761098
constness: Constness,
10771099
self_ty: Ty<'tcx>,
10781100
bounds: &mut Bounds<'tcx>,
1079-
) -> Result<(), GenericArgCountMismatch> {
1101+
) -> GenericArgCountResult {
10801102
self.instantiate_poly_trait_ref_inner(
10811103
&poly_trait_ref.trait_ref,
10821104
poly_trait_ref.span,
@@ -1166,8 +1188,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11661188
trait_def_id: DefId,
11671189
self_ty: Ty<'tcx>,
11681190
trait_segment: &'a hir::PathSegment<'a>,
1169-
) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Result<(), GenericArgCountMismatch>)
1170-
{
1191+
) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
11711192
debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment);
11721193

11731194
self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
@@ -1515,9 +1536,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
15151536
let mut potential_assoc_types = Vec::new();
15161537
let dummy_self = self.tcx().types.trait_object_dummy_self;
15171538
for trait_bound in trait_bounds.iter().rev() {
1518-
if let Err(GenericArgCountMismatch {
1519-
invalid_args: cur_potential_assoc_types, ..
1520-
}) = self.instantiate_poly_trait_ref(
1539+
if let GenericArgCountResult {
1540+
correct:
1541+
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
1542+
..
1543+
} = self.instantiate_poly_trait_ref(
15211544
trait_bound,
15221545
Constness::NotConst,
15231546
dummy_self,
@@ -2473,6 +2496,47 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
24732496
err.span_label(span, "associated type not allowed here").emit();
24742497
}
24752498

2499+
/// Prohibits explicit lifetime arguments if late-bound lifetime parameters
2500+
/// are present. This is used both for datatypes and function calls.
2501+
fn prohibit_explicit_late_bound_lifetimes(
2502+
tcx: TyCtxt<'_>,
2503+
def: &ty::Generics,
2504+
args: &hir::GenericArgs<'_>,
2505+
position: GenericArgPosition,
2506+
) -> ExplicitLateBound {
2507+
let param_counts = def.own_counts();
2508+
let arg_counts = args.own_counts();
2509+
let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
2510+
2511+
if infer_lifetimes {
2512+
ExplicitLateBound::No
2513+
} else if let Some(span_late) = def.has_late_bound_regions {
2514+
let msg = "cannot specify lifetime arguments explicitly \
2515+
if late bound lifetime parameters are present";
2516+
let note = "the late bound lifetime parameter is introduced here";
2517+
let span = args.args[0].span();
2518+
if position == GenericArgPosition::Value
2519+
&& arg_counts.lifetimes != param_counts.lifetimes
2520+
{
2521+
let mut err = tcx.sess.struct_span_err(span, msg);
2522+
err.span_note(span_late, note);
2523+
err.emit();
2524+
} else {
2525+
let mut multispan = MultiSpan::from_span(span);
2526+
multispan.push_span_label(span_late, note.to_string());
2527+
tcx.struct_span_lint_hir(
2528+
LATE_BOUND_LIFETIME_ARGUMENTS,
2529+
args.args[0].id(),
2530+
multispan,
2531+
|lint| lint.build(msg).emit(),
2532+
);
2533+
}
2534+
ExplicitLateBound::Yes
2535+
} else {
2536+
ExplicitLateBound::No
2537+
}
2538+
}
2539+
24762540
// FIXME(eddyb, varkor) handle type paths here too, not just value ones.
24772541
pub fn def_ids_for_value_path_segments(
24782542
&self,

‎src/librustc_typeck/check/method/confirm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
312312
parent_substs,
313313
false,
314314
None,
315-
arg_count_correct.is_ok(),
315+
arg_count_correct,
316316
// Provide the generic args, and whether types should be inferred.
317317
|def_id| {
318318
// The last component of the returned tuple here is unimportant.

‎src/librustc_typeck/check/mod.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ mod upvar;
8787
mod wfcheck;
8888
pub mod writeback;
8989

90-
use crate::astconv::{AstConv, GenericArgCountMismatch, PathSeg};
90+
use crate::astconv::{
91+
AstConv, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, PathSeg,
92+
};
9193
use rustc_ast::ast;
9294
use rustc_ast::util::parser::ExprPrecedence;
9395
use rustc_attr as attr;
@@ -5495,11 +5497,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
54955497
// parameter internally, but we don't allow users to specify the
54965498
// parameter's value explicitly, so we have to do some error-
54975499
// checking here.
5498-
if let Err(GenericArgCountMismatch { reported: Some(ErrorReported), .. }) =
5499-
AstConv::check_generic_arg_count_for_call(
5500-
tcx, span, &generics, &seg, false, // `is_method_call`
5501-
)
5502-
{
5500+
if let GenericArgCountResult {
5501+
correct: Err(GenericArgCountMismatch { reported: Some(ErrorReported), .. }),
5502+
..
5503+
} = AstConv::check_generic_arg_count_for_call(
5504+
tcx, span, &generics, &seg, false, // `is_method_call`
5505+
) {
55035506
infer_args_for_err.insert(index);
55045507
self.set_tainted_by_errors(); // See issue #53251.
55055508
}
@@ -5555,14 +5558,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
55555558
// escaping late-bound regions, and nor should the base type scheme.
55565559
let ty = tcx.type_of(def_id);
55575560

5561+
let arg_count = GenericArgCountResult {
5562+
explicit_late_bound: ExplicitLateBound::No,
5563+
correct: if infer_args_for_err.is_empty() {
5564+
Ok(())
5565+
} else {
5566+
Err(GenericArgCountMismatch::default())
5567+
},
5568+
};
5569+
55585570
let substs = self_ctor_substs.unwrap_or_else(|| {
55595571
AstConv::create_substs_for_generic_args(
55605572
tcx,
55615573
def_id,
55625574
&[][..],
55635575
has_self,
55645576
self_ty,
5565-
infer_args_for_err.is_empty(),
5577+
arg_count,
55665578
// Provide the generic args, and whether types should be inferred.
55675579
|def_id| {
55685580
if let Some(&PathSeg(_, index)) =

‎src/test/ui/issues/issue-72278.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// run-pass
2+
3+
#![allow(unused)]
4+
5+
struct S;
6+
7+
impl S {
8+
fn func<'a, U>(&'a self) -> U {
9+
todo!()
10+
}
11+
}
12+
13+
fn dont_crash<'a, U>() -> U {
14+
S.func::<'a, U>()
15+
//~^ WARN cannot specify lifetime arguments explicitly
16+
//~| WARN this was previously accepted
17+
}
18+
19+
fn main() {}

‎src/test/ui/issues/issue-72278.stderr

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
2+
--> $DIR/issue-72278.rs:14:14
3+
|
4+
LL | fn func<'a, U>(&'a self) -> U {
5+
| -- the late bound lifetime parameter is introduced here
6+
...
7+
LL | S.func::<'a, U>()
8+
| ^^
9+
|
10+
= note: `#[warn(late_bound_lifetime_arguments)]` on by default
11+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
12+
= note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
13+
14+
warning: 1 warning emitted
15+

0 commit comments

Comments
 (0)
Please sign in to comment.