Skip to content

Commit

Permalink
Make a proper suggestion.
Browse files Browse the repository at this point in the history
  • Loading branch information
cjgillot committed Mar 5, 2023
1 parent bf7e7a5 commit 270fa94
Show file tree
Hide file tree
Showing 14 changed files with 414 additions and 90 deletions.
35 changes: 34 additions & 1 deletion compiler/rustc_hir_analysis/src/astconv/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,40 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
})
.collect();

tcx.sess.struct_span_err(spans, msg).span_note(span_late, note).help(help).emit();
let mut err = tcx.sess.struct_span_err(spans, msg);
err.span_note(span_late, note);

let mut suggestions = vec![];
if let Some(span_ext) = args.span_ext() {
if args.num_lifetime_params() == args.args.len()
&& span_ext.ctxt() == seg.ident.span.ctxt()
{
// We only specify lifetime args, so suggest to remove everything.
suggestions.push((seg.ident.span.shrink_to_hi().to(span_ext), String::new()));
} else {
for [arg, next_arg] in args.args.array_windows() {
if let hir::GenericArg::Lifetime(lifetime) = arg
&& let Some(arg_span) = lifetime.ident.span.find_ancestor_inside(span_ext)
&& let Some(next_span_lo) = next_arg.span().shrink_to_lo().find_ancestor_inside(span_ext)
{
suggestions.push((arg_span.with_hi(next_span_lo.lo()), String::new()));
}
}

if let Some(arg) = args.args.last()
&& let hir::GenericArg::Lifetime(lifetime) = arg
&& let Some(arg_span) = lifetime.ident.span.find_ancestor_inside(span_ext)
{
suggestions.push((arg_span, String::new()));
}
}
}
if !suggestions.is_empty() {
err.multipart_suggestion_verbose(help, suggestions, Applicability::MachineApplicable);
} else {
err.help(help);
}
err.emit();

ExplicitLateBound::Yes
} else {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ This API is completely unstable and subject to change.

#![allow(rustc::potential_query_instability)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_windows)]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(drain_filter)]
Expand Down
48 changes: 40 additions & 8 deletions tests/ui/const-generics/const-arg-in-const-arg.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _: [u8; faz::<'a>(&())];
LL + let _: [u8; faz(&())];
|

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:21:23
Expand All @@ -22,7 +26,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _: [u8; faz::<'b>(&())];
LL + let _: [u8; faz(&())];
|

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:41:24
Expand All @@ -35,7 +43,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _: Foo<{ faz::<'a>(&()) }>;
LL + let _: Foo<{ faz(&()) }>;
|

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:44:24
Expand All @@ -48,7 +60,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _: Foo<{ faz::<'b>(&()) }>;
LL + let _: Foo<{ faz(&()) }>;
|

error: unconstrained generic constant
--> $DIR/const-arg-in-const-arg.rs:13:12
Expand Down Expand Up @@ -109,7 +125,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _ = [0; faz::<'a>(&())];
LL + let _ = [0; faz(&())];
|

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:33:23
Expand All @@ -122,7 +142,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _ = [0; faz::<'b>(&())];
LL + let _ = [0; faz(&())];
|

error: unconstrained generic constant
--> $DIR/const-arg-in-const-arg.rs:47:19
Expand Down Expand Up @@ -151,7 +175,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _ = Foo::<{ faz::<'a>(&()) }>;
LL + let _ = Foo::<{ faz(&()) }>;
|

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:55:27
Expand All @@ -164,7 +192,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _ = Foo::<{ faz::<'b>(&()) }>;
LL + let _ = Foo::<{ faz(&()) }>;
|

error: aborting due to 16 previous errors

48 changes: 40 additions & 8 deletions tests/ui/const-generics/const-arg-in-const-arg.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _: [u8; faz::<'a>(&())];
LL + let _: [u8; faz(&())];
|

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:21:23
Expand All @@ -240,7 +244,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _: [u8; faz::<'b>(&())];
LL + let _: [u8; faz(&())];
|

error[E0747]: unresolved item provided when a constant was expected
--> $DIR/const-arg-in-const-arg.rs:38:24
Expand All @@ -264,7 +272,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _: Foo<{ faz::<'a>(&()) }>;
LL + let _: Foo<{ faz(&()) }>;
|

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:44:24
Expand All @@ -277,7 +289,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _: Foo<{ faz::<'b>(&()) }>;
LL + let _: Foo<{ faz(&()) }>;
|

error: constant expression depends on a generic parameter
--> $DIR/const-arg-in-const-arg.rs:25:17
Expand Down Expand Up @@ -309,7 +325,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _ = [0; faz::<'a>(&())];
LL + let _ = [0; faz(&())];
|

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:33:23
Expand All @@ -322,7 +342,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _ = [0; faz::<'b>(&())];
LL + let _ = [0; faz(&())];
|

error[E0747]: unresolved item provided when a constant was expected
--> $DIR/const-arg-in-const-arg.rs:49:27
Expand All @@ -346,7 +370,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _ = Foo::<{ faz::<'a>(&()) }>;
LL + let _ = Foo::<{ faz(&()) }>;
|

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
--> $DIR/const-arg-in-const-arg.rs:55:27
Expand All @@ -359,7 +387,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | const fn faz<'a>(_: &'a ()) -> usize { 13 }
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - let _ = Foo::<{ faz::<'b>(&()) }>;
LL + let _ = Foo::<{ faz(&()) }>;
|

error: aborting due to 36 previous errors

Expand Down
6 changes: 5 additions & 1 deletion tests/ui/const-generics/issues/issue-83466.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | fn func<'a, U>(self) -> U {
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - S.func::<'a, 10_u32>()
LL + S.func::<10_u32>()
|

error[E0747]: constant provided when a type was expected
--> $DIR/issue-83466.rs:11:18
Expand Down
6 changes: 5 additions & 1 deletion tests/ui/issues/issue-60622.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | fn a(&self) {}
| ^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - b.a::<'_, T>();
LL + b.a::<T>();
|

error[E0107]: method takes 0 generic arguments but 1 generic argument was supplied
--> $DIR/issue-60622.rs:10:7
Expand Down
6 changes: 5 additions & 1 deletion tests/ui/issues/issue-72278.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ note: the late bound lifetime parameter is introduced here
|
LL | fn func<'a, U>(&'a self) -> U {
| ^^
= help: remove the explicit lifetime argument
help: remove the explicit lifetime argument
|
LL - S.func::<'a, U>()
LL + S.func::<U>()
|

error: aborting due to previous error

75 changes: 75 additions & 0 deletions tests/ui/methods/method-call-lifetime-args-fail.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// run-rustfix
#![allow(dead_code)]

struct S;

impl S {
fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {}
fn late_implicit(self, _: &u8, _: &u8) {}
fn early<'a, 'b>(self) -> (&'a u8, &'b u8) { loop {} }
fn late_early<'a, 'b>(self, _: &'a u8) -> &'b u8 { loop {} }
fn late_implicit_early<'b>(self, _: &u8) -> &'b u8 { loop {} }
fn late_implicit_self_early<'b>(&self) -> &'b u8 { loop {} }
fn late_unused_early<'a, 'b>(self) -> &'b u8 { loop {} }
fn life_and_type<'a, T>(self) -> &'a T { loop {} }
}

fn method_call() {
S.early(); // OK
S.early::<'static, 'static>();
//~^ ERROR method takes 2 lifetime arguments but 1 lifetime argument
S.early::<'static, 'static, >();
//~^ ERROR method takes 2 lifetime arguments but 3 lifetime arguments were supplied
let _: &u8 = S.life_and_type::<'static>();
S.life_and_type::<u8>();
S.life_and_type::<'static, u8>();
}

fn ufcs() {
S::late(S, &0, &0); // OK
S::late(S, &0, &0);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late(S, &0, &0);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late(S, &0, &0);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late_early(S, &0); // OK
S::late_early(S, &0);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late_early(S, &0);
//~^ ERROR cannot specify lifetime arguments explicitly

S::late_implicit(S, &0, &0); // OK
S::late_implicit(S, &0, &0);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late_implicit(S, &0, &0);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late_implicit(S, &0, &0);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late_implicit_early(S, &0); // OK
S::late_implicit_early(S, &0);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late_implicit_early(S, &0);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late_implicit_self_early(&S); // OK
S::late_implicit_self_early(&S);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late_implicit_self_early(&S);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late_unused_early(S); // OK
S::late_unused_early(S);
//~^ ERROR cannot specify lifetime arguments explicitly
S::late_unused_early(S);
//~^ ERROR cannot specify lifetime arguments explicitly

S::early(S); // OK
S::early::<'static, 'static>(S);
//~^ ERROR method takes 2 lifetime arguments but 1 lifetime argument
S::early::<'static, 'static, >(S);
//~^ ERROR method takes 2 lifetime arguments but 3 lifetime arguments were supplied
let _: &u8 = S::life_and_type::<'static>(S);
S::life_and_type::<u8>(S);
S::life_and_type::<'static, u8>(S);
}

fn main() {}
3 changes: 3 additions & 0 deletions tests/ui/methods/method-call-lifetime-args-fail.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// run-rustfix
#![allow(dead_code)]

struct S;

impl S {
Expand Down
Loading

0 comments on commit 270fa94

Please sign in to comment.