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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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() {
|
||||
match expr.kind {
|
||||
ExprKind::Closure(..) => self.found_closure = Some(&expr),
|
||||
@ -345,11 +350,6 @@ pub fn emit_inference_failure_err(
|
||||
) -> DiagnosticBuilder<'tcx> {
|
||||
let arg = self.resolve_vars_if_possible(arg);
|
||||
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 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)
|
||||
&& 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`.
|
||||
err.span_label(
|
||||
span,
|
||||
|
@ -3,6 +3,11 @@ error[E0282]: type annotations needed
|
||||
|
|
||||
LL | 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
|
||||
|
||||
|
@ -3,6 +3,11 @@ error[E0282]: type annotations needed
|
||||
|
|
||||
LL | 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
|
||||
|
||||
|
@ -3,6 +3,11 @@ error[E0282]: type annotations needed
|
||||
|
|
||||
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`
|
||||
|
|
||||
help: consider specifying the const argument
|
||||
|
|
||||
LL | println!("{:?}", take_array_from_mut::<N>(&mut arr, i));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -3,6 +3,11 @@ error[E0282]: type annotations needed
|
||||
|
|
||||
LL | Foo.bar().bar().bar().bar().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
|
||||
|
||||
|
@ -3,6 +3,11 @@ error[E0282]: type annotations needed
|
||||
|
|
||||
LL | Foo.bar().bar().bar().bar().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
|
||||
|
||||
|
@ -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
|
||||
|
|
||||
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
|
||||
|
||||
|
@ -2,7 +2,12 @@ error[E0282]: type annotations needed
|
||||
--> $DIR/uninferred-consts.rs:14:9
|
||||
|
|
||||
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
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
// taken from https://github.com/rust-lang/rust/issues/70507#issuecomment-615268893
|
||||
struct Foo;
|
||||
impl Foo {
|
||||
fn foo<const N: usize>(self) {}
|
||||
fn foo<const A: usize, const B: usize>(self) {}
|
||||
}
|
||||
fn main() {
|
||||
Foo.foo();
|
||||
|
Loading…
Reference in New Issue
Block a user