Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

suggest turbofish syntax for uninferred const arguments #77758

Merged
merged 1 commit into from
Nov 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, '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),
Expand Down Expand Up @@ -345,11 +350,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
) -> 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 {
Expand Down Expand Up @@ -618,6 +618,28 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.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
Stupremee marked this conversation as resolved.
Show resolved Hide resolved
lcnr marked this conversation as resolved.
Show resolved Hide resolved
.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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/const-generics/infer/issue-77092.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/const-generics/infer/method-chain.full.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/const-generics/infer/method-chain.min.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 14 additions & 0 deletions src/test/ui/const-generics/infer/one-param-uninferred.full.stderr
Original file line number Diff line number Diff line change
@@ -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`.
14 changes: 14 additions & 0 deletions src/test/ui/const-generics/infer/one-param-uninferred.min.stderr
Original file line number Diff line number Diff line change
@@ -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 changes: 17 additions & 0 deletions src/test/ui/const-generics/infer/one-param-uninferred.rs
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>();
Stupremee marked this conversation as resolved.
Show resolved Hide resolved
| ^^^^^^^^

error: aborting due to previous error

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/const-generics/infer/uninferred-consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down