Checking generic args after late bound region err.

This commit fixes an ICE that occurs when a late bound region error is
emitted and that resulted in the rest of the generic arguments of a
function not being checked.

For example, you could specify a generic type parameter `T` in a function
call `foo<'_, T>()` to a function that doesn't have a generic type
parameter.

Since an error wasn't emitted from the function, compilation
continued to parts of typeck that didn't expect a generic type argument
in a call for a function that didn't have any generic type arguments.
This commit is contained in:
David Wood 2019-05-16 22:00:27 +01:00
parent 7158ed9cbe
commit bff8a86698
No known key found for this signature in database
GPG Key ID: 01760B4F9F53F154
3 changed files with 52 additions and 5 deletions

View File

@ -290,6 +290,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
}
// Prohibit explicit lifetime arguments if late-bound lifetime parameters are present.
let mut reported_late_bound_region_err = None;
if !infer_lifetimes {
if let Some(span_late) = def.has_late_bound_regions {
let msg = "cannot specify lifetime arguments explicitly \
@ -301,13 +302,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
let mut err = tcx.sess.struct_span_err(span, msg);
err.span_note(span_late, note);
err.emit();
return (true, None);
reported_late_bound_region_err = Some(true);
} else {
let mut multispan = MultiSpan::from_span(span);
multispan.push_span_label(span_late, note.to_string());
tcx.lint_hir(lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS,
args.args[0].id(), multispan, msg);
return (false, None);
reported_late_bound_region_err = Some(false);
}
}
}
@ -325,7 +326,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
// For kinds without defaults (i.e., lifetimes), `required == permitted`.
// For other kinds (i.e., types), `permitted` may be greater than `required`.
if required <= provided && provided <= permitted {
return (false, None);
return (reported_late_bound_region_err.unwrap_or(false), None);
}
// Unfortunately lifetime and type parameter mismatches are typically styled
@ -380,7 +381,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
potential_assoc_types)
};
if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes {
if reported_late_bound_region_err.is_none()
&& (!infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes) {
check_kind_count(
"lifetime",
param_counts.lifetimes,
@ -410,7 +412,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
arg_counts.lifetimes,
)
} else {
(false, None)
(reported_late_bound_region_err.unwrap_or(false), None)
}
}

View File

@ -0,0 +1,18 @@
// ignore-tidy-linelength
#![deny(warnings)]
struct Borked {}
impl Borked {
fn a(&self) {}
}
fn run_wild<T>(b: &Borked) {
b.a::<'_, T>();
//~^ ERROR cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
//~^^ ERROR wrong number of type arguments: expected 0, found 1
//~^^^ WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
}
fn main() {}

View File

@ -0,0 +1,27 @@
error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/issue-60622.rs:12:11
|
LL | fn a(&self) {}
| - the late bound lifetime parameter is introduced here
...
LL | b.a::<'_, T>();
| ^^
|
note: lint level defined here
--> $DIR/issue-60622.rs:3:9
|
LL | #![deny(warnings)]
| ^^^^^^^^
= note: #[deny(late_bound_lifetime_arguments)] implied by #[deny(warnings)]
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
error[E0107]: wrong number of type arguments: expected 0, found 1
--> $DIR/issue-60622.rs:12:15
|
LL | b.a::<'_, T>();
| ^ unexpected type argument
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0107`.