Rollup merge of #77758 - Stupremee:turbofish-help-for-const, r=varkor
suggest turbofish syntax for uninferred const arguments When not providing a const generic value, and it can not be inferred, the following suggestion is suggested: ![image](https://user-images.githubusercontent.com/39732259/95616180-af127b80-0a69-11eb-8877-551c815f9627.png) Resolves #76737 r? ``@varkor``
This commit is contained in:
commit
9b2117d1f6
@ -124,6 +124,11 @@ fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(const_generics): Currently, any uninferred `const` generics arguments
|
||||||
|
// are handled specially, but instead they should be handled in `annotate_method_call`,
|
||||||
|
// which currently doesn't work because this evaluates to `false` for const arguments.
|
||||||
|
// See https://github.com/rust-lang/rust/pull/77758 for more details.
|
||||||
if self.node_ty_contains_target(expr.hir_id).is_some() {
|
if self.node_ty_contains_target(expr.hir_id).is_some() {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Closure(..) => self.found_closure = Some(&expr),
|
ExprKind::Closure(..) => self.found_closure = Some(&expr),
|
||||||
@ -345,11 +350,6 @@ pub fn emit_inference_failure_err(
|
|||||||
) -> DiagnosticBuilder<'tcx> {
|
) -> DiagnosticBuilder<'tcx> {
|
||||||
let arg = self.resolve_vars_if_possible(arg);
|
let arg = self.resolve_vars_if_possible(arg);
|
||||||
let arg_data = self.extract_inference_diagnostics_data(arg, None);
|
let arg_data = self.extract_inference_diagnostics_data(arg, None);
|
||||||
let kind_str = match arg.unpack() {
|
|
||||||
GenericArgKind::Type(_) => "type",
|
|
||||||
GenericArgKind::Const(_) => "the value",
|
|
||||||
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut local_visitor = FindHirNodeVisitor::new(&self, arg, span);
|
let mut local_visitor = FindHirNodeVisitor::new(&self, arg, span);
|
||||||
let ty_to_string = |ty: Ty<'tcx>| -> String {
|
let ty_to_string = |ty: Ty<'tcx>| -> String {
|
||||||
@ -618,6 +618,28 @@ pub fn emit_inference_failure_err(
|
|||||||
.any(|span_label| span_label.label.is_some() && span_label.span == span)
|
.any(|span_label| span_label.label.is_some() && span_label.span == span)
|
||||||
&& local_visitor.found_arg_pattern.is_none()
|
&& local_visitor.found_arg_pattern.is_none()
|
||||||
{
|
{
|
||||||
|
let (kind_str, const_value) = match arg.unpack() {
|
||||||
|
GenericArgKind::Type(_) => ("type", None),
|
||||||
|
GenericArgKind::Const(_) => ("the value", Some(())),
|
||||||
|
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME(const_generics): we would like to handle const arguments
|
||||||
|
// as part of the normal diagnostics flow below, but there appear to
|
||||||
|
// be subtleties in doing so, so for now we special-case const args
|
||||||
|
// here.
|
||||||
|
if let Some(suggestion) = const_value
|
||||||
|
.and_then(|_| arg_data.parent_name.as_ref())
|
||||||
|
.map(|parent| format!("{}::<{}>", parent, arg_data.name))
|
||||||
|
{
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
span,
|
||||||
|
"consider specifying the const argument",
|
||||||
|
suggestion,
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Avoid multiple labels pointing at `span`.
|
// Avoid multiple labels pointing at `span`.
|
||||||
err.span_label(
|
err.span_label(
|
||||||
span,
|
span,
|
||||||
|
@ -3,6 +3,11 @@ error[E0282]: type annotations needed
|
|||||||
|
|
|
|
||||||
LL | foo();
|
LL | foo();
|
||||||
| ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
|
| ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
|
||||||
|
|
|
||||||
|
help: consider specifying the const argument
|
||||||
|
|
|
||||||
|
LL | foo::<X>();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -3,6 +3,11 @@ error[E0282]: type annotations needed
|
|||||||
|
|
|
|
||||||
LL | foo();
|
LL | foo();
|
||||||
| ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
|
| ^^^ cannot infer the value of const parameter `X` declared on the function `foo`
|
||||||
|
|
|
||||||
|
help: consider specifying the const argument
|
||||||
|
|
|
||||||
|
LL | foo::<X>();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -3,6 +3,11 @@ error[E0282]: type annotations needed
|
|||||||
|
|
|
|
||||||
LL | println!("{:?}", take_array_from_mut(&mut arr, i));
|
LL | println!("{:?}", take_array_from_mut(&mut arr, i));
|
||||||
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `take_array_from_mut`
|
| ^^^^^^^^^^^^^^^^^^^ cannot infer the value of const parameter `N` declared on the function `take_array_from_mut`
|
||||||
|
|
|
||||||
|
help: consider specifying the const argument
|
||||||
|
|
|
||||||
|
LL | println!("{:?}", take_array_from_mut::<N>(&mut arr, i));
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -3,6 +3,11 @@ error[E0282]: type annotations needed
|
|||||||
|
|
|
|
||||||
LL | Foo.bar().bar().bar().bar().baz();
|
LL | Foo.bar().bar().bar().bar().baz();
|
||||||
| ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
|
| ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
|
||||||
|
|
|
||||||
|
help: consider specifying the const argument
|
||||||
|
|
|
||||||
|
LL | Foo.bar().bar().bar().bar().baz::<N>();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -3,6 +3,11 @@ error[E0282]: type annotations needed
|
|||||||
|
|
|
|
||||||
LL | Foo.bar().bar().bar().bar().baz();
|
LL | Foo.bar().bar().bar().bar().baz();
|
||||||
| ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
|
| ^^^ cannot infer the value of const parameter `N` declared on the associated function `baz`
|
||||||
|
|
|
||||||
|
help: consider specifying the const argument
|
||||||
|
|
|
||||||
|
LL | Foo.bar().bar().bar().bar().baz::<N>();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/one-param-uninferred.rs:15:23
|
||||||
|
|
|
||||||
|
LL | let _: [u8; 17] = foo();
|
||||||
|
| ^^^ cannot infer the value of const parameter `M` declared on the function `foo`
|
||||||
|
|
|
||||||
|
help: consider specifying the const argument
|
||||||
|
|
|
||||||
|
LL | let _: [u8; 17] = foo::<M>();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0282`.
|
@ -0,0 +1,14 @@
|
|||||||
|
error[E0282]: type annotations needed
|
||||||
|
--> $DIR/one-param-uninferred.rs:15:23
|
||||||
|
|
|
||||||
|
LL | let _: [u8; 17] = foo();
|
||||||
|
| ^^^ cannot infer the value of const parameter `M` declared on the function `foo`
|
||||||
|
|
|
||||||
|
help: consider specifying the const argument
|
||||||
|
|
|
||||||
|
LL | let _: [u8; 17] = foo::<M>();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0282`.
|
17
src/test/ui/const-generics/infer/one-param-uninferred.rs
Normal file
17
src/test/ui/const-generics/infer/one-param-uninferred.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Test that we emit an error if we cannot properly infer a constant.
|
||||||
|
// revisions: full min
|
||||||
|
|
||||||
|
#![cfg_attr(full, feature(const_generics))]
|
||||||
|
#![cfg_attr(full, allow(incomplete_features))]
|
||||||
|
#![cfg_attr(min, feature(min_const_generics))]
|
||||||
|
|
||||||
|
fn foo<const N: usize, const M: usize>() -> [u8; N] {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// FIXME(const_generics): Currently this only suggests one const parameter,
|
||||||
|
// but instead it should suggest to provide all parameters.
|
||||||
|
let _: [u8; 17] = foo();
|
||||||
|
//~^ ERROR type annotations needed
|
||||||
|
}
|
@ -2,7 +2,12 @@ error[E0282]: type annotations needed
|
|||||||
--> $DIR/uninferred-consts.rs:14:9
|
--> $DIR/uninferred-consts.rs:14:9
|
||||||
|
|
|
|
||||||
LL | Foo.foo();
|
LL | Foo.foo();
|
||||||
| ^^^ cannot infer the value of const parameter `N` declared on the associated function `foo`
|
| ^^^ cannot infer the value of const parameter `A` declared on the associated function `foo`
|
||||||
|
|
|
||||||
|
help: consider specifying the const argument
|
||||||
|
|
|
||||||
|
LL | Foo.foo::<A>();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -2,7 +2,12 @@ error[E0282]: type annotations needed
|
|||||||
--> $DIR/uninferred-consts.rs:14:9
|
--> $DIR/uninferred-consts.rs:14:9
|
||||||
|
|
|
|
||||||
LL | Foo.foo();
|
LL | Foo.foo();
|
||||||
| ^^^ cannot infer the value of const parameter `N` declared on the associated function `foo`
|
| ^^^ cannot infer the value of const parameter `A` declared on the associated function `foo`
|
||||||
|
|
|
||||||
|
help: consider specifying the const argument
|
||||||
|
|
|
||||||
|
LL | Foo.foo::<A>();
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
|
// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
|
||||||
struct Foo;
|
struct Foo;
|
||||||
impl Foo {
|
impl Foo {
|
||||||
fn foo<const N: usize>(self) {}
|
fn foo<const A: usize, const B: usize>(self) {}
|
||||||
}
|
}
|
||||||
fn main() {
|
fn main() {
|
||||||
Foo.foo();
|
Foo.foo();
|
||||||
|
Loading…
Reference in New Issue
Block a user