Skip to content

Commit

Permalink
Update w/ comments
Browse files Browse the repository at this point in the history
  • Loading branch information
JulianKnodt committed Feb 16, 2021
1 parent be1ed00 commit b97951b
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 43 deletions.
60 changes: 33 additions & 27 deletions compiler/rustc_typeck/src/astconv/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use crate::astconv::{
use crate::errors::AssocTypeBindingNotAllowed;
use crate::structured_errors::{StructuredDiagnostic, WrongNumberOfGenericArgs};
use rustc_ast::ast::ParamKindOrd;
use rustc_errors::{struct_span_err, Applicability, ErrorReported};
use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefId;
use rustc_hir::GenericArg;
use rustc_middle::ty::{
Expand All @@ -24,8 +25,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
tcx: TyCtxt<'_>,
arg: &GenericArg<'_>,
param: &GenericParamDef,
// DefId of the function
//body_def_id: DefId,
possible_ordering_error: bool,
help: Option<&str>,
) {
Expand All @@ -45,6 +44,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
}

let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut DiagnosticBuilder<'_>| {
let suggestions = vec![
(arg.span().shrink_to_lo(), String::from("{ ")),
(arg.span().shrink_to_hi(), String::from(" }")),
];
err.multipart_suggestion(
"if this generic argument was intended as a const parameter, \
surround it with braces",
suggestions,
Applicability::MaybeIncorrect,
);
};

// Specific suggestion set for diagnostics
match (arg, &param.kind) {
(
Expand All @@ -53,40 +65,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
..
}),
GenericParamDefKind::Const,
) => {
use rustc_hir::def::{DefKind, Res};
match path.res {
Res::Err => {}
Res::Def(DefKind::TyParam, src_def_id) => (|| {
let param_hir_id = match param.def_id.as_local() {
Some(x) => tcx.hir().local_def_id_to_hir_id(x),
None => return,
};
) => match path.res {
Res::Err => {
add_braces_suggestion(arg, &mut err);
err.set_primary_message(
"unresolved item provided when a constant was expected",
);
}
Res::Def(DefKind::TyParam, src_def_id) => {
if let Some(param_local_id) = param.def_id.as_local() {
let param_hir_id = tcx.hir().local_def_id_to_hir_id(param_local_id);
let param_name = tcx.hir().ty_param_name(param_hir_id);
let param_type = tcx.type_of(param.def_id);
if param_type.is_suggestable() {
err.span_suggestion(
tcx.def_span(src_def_id),
&format!("try changing to a const-generic parameter:"),
"consider changing this type paramater to a `const`-generic",
format!("const {}: {}", param_name, param_type),
Applicability::MaybeIncorrect,
);
}
})(),
_ => {
let suggestions = vec![
(arg.span().shrink_to_lo(), String::from("{ ")),
(arg.span().shrink_to_hi(), String::from(" }")),
];
err.multipart_suggestion(
"if this generic argument was intended as a const parameter, \
try surrounding it with braces:",
suggestions,
Applicability::MaybeIncorrect,
);
};
}
}
}
_ => add_braces_suggestion(arg, &mut err),
},
(
GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }),
GenericParamDefKind::Const,
) => add_braces_suggestion(arg, &mut err),
(
GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
GenericParamDefKind::Const { .. },
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/const-generics/const-param-shadowing.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ error[E0747]: type provided when a constant was expected
LL | fn test<const N: usize>() -> Foo<N> {
| ^
|
help: if this generic argument was intended as a const parameter, try surrounding it with braces:
help: if this generic argument was intended as a const parameter, surround it with braces
|
LL | fn test<const N: usize>() -> Foo<{ N }> {
| ^ ^
Expand Down
11 changes: 8 additions & 3 deletions src/test/ui/const-generics/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
#![crate_type="lib"]
#![feature(const_generics)]
#![feature(min_const_generics)]
#![allow(incomplete_features)]

struct A<const N: u8>;
trait Foo {}
impl Foo for A<N> {}
//~^ ERROR type provided when a constant
//~| ERROR cannot find type
//~^ ERROR cannot find type
//~| unresolved item provided when a constant

struct B<const N: u8>;
impl<N> Foo for B<N> {}
//~^ ERROR type provided when a constant

struct C<const C: u8, const N: u8>;
impl<const N: u8> Foo for C<N, T> {}
//~^ ERROR cannot find type
//~| unresolved item provided when a constant
33 changes: 30 additions & 3 deletions src/test/ui/const-generics/diagnostics.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,48 @@ LL | trait Foo {}
LL | impl Foo for A<N> {}
| ^ help: a struct with a similar name exists: `A`

error[E0747]: type provided when a constant was expected
error[E0412]: cannot find type `T` in this scope
--> $DIR/diagnostics.rs:16:32
|
LL | struct A<const N: u8>;
| ---------------------- similarly named struct `A` defined here
...
LL | impl<const N: u8> Foo for C<N, T> {}
| ^ help: a struct with a similar name exists: `A`

error[E0747]: unresolved item provided when a constant was expected
--> $DIR/diagnostics.rs:7:16
|
LL | impl Foo for A<N> {}
| ^
|
help: if this generic argument was intended as a const parameter, surround it with braces
|
LL | impl Foo for A<{ N }> {}
| ^ ^

error[E0747]: type provided when a constant was expected
--> $DIR/diagnostics.rs:12:19
|
LL | impl<N> Foo for B<N> {}
| - ^
| |
| help: try changing to a const-generic parameter:: `const N: u8`
| help: consider changing this type paramater to a `const`-generic: `const N: u8`

error[E0747]: unresolved item provided when a constant was expected
--> $DIR/diagnostics.rs:16:32
|
LL | impl<const N: u8> Foo for C<N, T> {}
| ^
|
= note: type arguments must be provided before constant arguments
= help: reorder the arguments: consts: `<C, N>`
help: if this generic argument was intended as a const parameter, surround it with braces
|
LL | impl<const N: u8> Foo for C<N, { T }> {}
| ^ ^

error: aborting due to 3 previous errors
error: aborting due to 5 previous errors

Some errors have detailed explanations: E0412, E0747.
For more information about an error, try `rustc --explain E0412`.
12 changes: 6 additions & 6 deletions src/test/ui/const-generics/invalid-enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@

#[derive(PartialEq, Eq)]
enum CompileFlag {
A,
B,
A,
B,
}

pub fn test_1<const CF: CompileFlag>() {}
pub fn test_2<T, const CF: CompileFlag>(x: T) {}
pub struct Example<const CF: CompileFlag, T=u32>{
x: T,
x: T,
}

impl<const CF: CompileFlag, T> Example<CF, T> {
Expand All @@ -20,15 +20,15 @@ impl<const CF: CompileFlag, T> Example<CF, T> {
pub fn main() {
test_1::<CompileFlag::A>();
//~^ ERROR: expected type, found variant
//~| ERROR: type provided when a constant was expected
//~| ERROR: unresolved item provided when a constant was expected

test_2::<_, CompileFlag::A>(0);
//~^ ERROR: expected type, found variant
//~| ERROR: type provided when a constant was expected
//~| ERROR: unresolved item provided when a constant was expected

let _: Example<CompileFlag::A, _> = Example { x: 0 };
//~^ ERROR: expected type, found variant
//~| ERROR: type provided when a constant was expected
//~| ERROR: unresolved item provided when a constant was expected

let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
//~^ ERROR: type provided when a constant was expected
Expand Down
26 changes: 23 additions & 3 deletions src/test/ui/const-generics/invalid-enum.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,49 @@ LL | let _: Example<CompileFlag::A, _> = Example { x: 0 };
| not a type
| help: try using the variant's enum: `CompileFlag`

error[E0747]: type provided when a constant was expected
error[E0747]: unresolved item provided when a constant was expected
--> $DIR/invalid-enum.rs:29:18
|
LL | let _: Example<CompileFlag::A, _> = Example { x: 0 };
| ^^^^^^^^^^^^^^
|
help: if this generic argument was intended as a const parameter, surround it with braces
|
LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 };
| ^ ^

error[E0747]: type provided when a constant was expected
--> $DIR/invalid-enum.rs:33:18
|
LL | let _: Example<Example::ASSOC_FLAG, _> = Example { x: 0 };
| ^^^^^^^^^^^^^^^^^^^
|
help: if this generic argument was intended as a const parameter, surround it with braces
|
LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 };
| ^ ^

error[E0747]: type provided when a constant was expected
error[E0747]: unresolved item provided when a constant was expected
--> $DIR/invalid-enum.rs:21:12
|
LL | test_1::<CompileFlag::A>();
| ^^^^^^^^^^^^^^
|
help: if this generic argument was intended as a const parameter, surround it with braces
|
LL | test_1::<{ CompileFlag::A }>();
| ^ ^

error[E0747]: type provided when a constant was expected
error[E0747]: unresolved item provided when a constant was expected
--> $DIR/invalid-enum.rs:25:15
|
LL | test_2::<_, CompileFlag::A>(0);
| ^^^^^^^^^^^^^^
|
help: if this generic argument was intended as a const parameter, surround it with braces
|
LL | test_2::<_, { CompileFlag::A }>(0);
| ^ ^

error: aborting due to 7 previous errors

Expand Down

0 comments on commit b97951b

Please sign in to comment.