diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index b7336fcd369..eb2207a0d67 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -445,15 +445,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert_ne!(bound, provided); Err((bound as i32 - provided as i32, Some(err))) }; - let emit_correct = - |correct: Result<(), (_, Option>)>| match correct { - Ok(()) => Ok(()), - Err((_, None)) => Err(()), - Err((_, Some(mut err))) => { - err.emit(); - Err(()) - } - }; let mut unexpected_spans = vec![]; @@ -501,31 +492,41 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Emit a help message if it's possible that a type could be surrounded in braces if let Err((c_mismatch, Some(ref mut _const_err))) = const_count_correct { - if let Err((t_mismatch, Some(ref mut type_err))) = type_count_correct { - if c_mismatch == -t_mismatch && t_mismatch < 0 { - for i in 0..c_mismatch as usize { - let arg = &args.args[arg_counts.lifetimes + i]; - match arg { - GenericArg::Type(hir::Ty { - kind: hir::TyKind::Path { .. }, .. - }) => {} - _ => continue, - } - let suggestions = vec![ - (arg.span().shrink_to_lo(), String::from("{ ")), - (arg.span().shrink_to_hi(), String::from(" }")), - ]; - type_err.multipart_suggestion( - "If this generic argument was intended as a const parameter, \ - try surrounding it with braces:", - suggestions, - Applicability::MaybeIncorrect, - ); - } + if let Err((_, Some(ref mut type_err))) = type_count_correct { + let possible_matches = args.args[arg_counts.lifetimes..] + .iter() + .filter(|arg| { + matches!( + arg, + GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }) + ) + }) + .take(c_mismatch.max(0) as usize); + for arg in possible_matches { + let suggestions = vec![ + (arg.span().shrink_to_lo(), String::from("{ ")), + (arg.span().shrink_to_hi(), String::from(" }")), + ]; + type_err.multipart_suggestion( + "If this generic argument was intended as a const parameter, \ + try surrounding it with braces:", + suggestions, + Applicability::MaybeIncorrect, + ); } } } + let emit_correct = + |correct: Result<(), (_, Option>)>| match correct { + Ok(()) => Ok(()), + Err((_, None)) => Err(()), + Err((_, Some(mut err))) => { + err.emit(); + Err(()) + } + }; + let arg_count_correct = emit_correct(lifetime_count_correct) .and(emit_correct(const_count_correct)) .and(emit_correct(type_count_correct)); diff --git a/src/test/ui/const-generics/invalid-enum.rs b/src/test/ui/const-generics/invalid-enum.rs index 05c13e8fe0c..ceb188a0d3d 100644 --- a/src/test/ui/const-generics/invalid-enum.rs +++ b/src/test/ui/const-generics/invalid-enum.rs @@ -7,11 +7,33 @@ enum CompileFlag { B, } -pub fn test() {} +pub fn test_1() {} +pub fn test_2(x: T) {} +pub struct Example{ + x: T, +} + +impl Example { + const ASSOC_FLAG: CompileFlag = CompileFlag::A; +} pub fn main() { - test::(); + test_1::(); //~^ ERROR: expected type, found variant //~| ERROR: wrong number of const arguments //~| ERROR: wrong number of type arguments + + test_2::<_, CompileFlag::A>(0); + //~^ ERROR: expected type, found variant + //~| ERROR: wrong number of const arguments + //~| ERROR: wrong number of type arguments + + let _: Example = Example { x: 0 }; + //~^ ERROR: expected type, found variant + //~| ERROR: wrong number of const arguments + //~| ERROR: wrong number of type arguments + + let _: Example = Example { x: 0 }; + //~^ ERROR: wrong number of const arguments + //~| ERROR: wrong number of type arguments } diff --git a/src/test/ui/const-generics/invalid-enum.stderr b/src/test/ui/const-generics/invalid-enum.stderr index 3291b62ea9f..965abbc9cb7 100644 --- a/src/test/ui/const-generics/invalid-enum.stderr +++ b/src/test/ui/const-generics/invalid-enum.stderr @@ -1,30 +1,99 @@ error[E0573]: expected type, found variant `CompileFlag::A` - --> $DIR/invalid-enum.rs:13:10 + --> $DIR/invalid-enum.rs:21:12 | -LL | test::(); - | ^^^^^^^^^^^^^^ - | | - | not a type - | help: try using the variant's enum: `CompileFlag` +LL | test_1::(); + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `CompileFlag` + +error[E0573]: expected type, found variant `CompileFlag::A` + --> $DIR/invalid-enum.rs:26:15 + | +LL | test_2::<_, CompileFlag::A>(0); + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `CompileFlag` + +error[E0573]: expected type, found variant `CompileFlag::A` + --> $DIR/invalid-enum.rs:31:18 + | +LL | let _: Example = Example { x: 0 }; + | ^^^^^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `CompileFlag` error[E0107]: wrong number of const arguments: expected 1, found 0 - --> $DIR/invalid-enum.rs:13:3 + --> $DIR/invalid-enum.rs:31:10 | -LL | test::(); - | ^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument +LL | let _: Example = Example { x: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument -error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/invalid-enum.rs:13:10 +error[E0107]: wrong number of type arguments: expected at most 1, found 2 + --> $DIR/invalid-enum.rs:31:10 | -LL | test::(); - | ^^^^^^^^^^^^^^ unexpected type argument +LL | let _: Example = Example { x: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected at most 1 type argument | help: If this generic argument was intended as a const parameter, try surrounding it with braces: | -LL | test::<{ CompileFlag::A }>(); - | ^ ^ +LL | let _: Example<{ CompileFlag::A }, _> = Example { x: 0 }; + | ^ ^ -error: aborting due to 3 previous errors +error[E0107]: wrong number of const arguments: expected 1, found 0 + --> $DIR/invalid-enum.rs:36:10 + | +LL | let _: Example = Example { x: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument + +error[E0107]: wrong number of type arguments: expected at most 1, found 2 + --> $DIR/invalid-enum.rs:36:10 + | +LL | let _: Example = Example { x: 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected at most 1 type argument + | +help: If this generic argument was intended as a const parameter, try surrounding it with braces: + | +LL | let _: Example<{ Example::ASSOC_FLAG }, _> = Example { x: 0 }; + | ^ ^ + +error[E0107]: wrong number of const arguments: expected 1, found 0 + --> $DIR/invalid-enum.rs:21:3 + | +LL | test_1::(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/invalid-enum.rs:21:12 + | +LL | test_1::(); + | ^^^^^^^^^^^^^^ unexpected type argument + | +help: If this generic argument was intended as a const parameter, try surrounding it with braces: + | +LL | test_1::<{ CompileFlag::A }>(); + | ^ ^ + +error[E0107]: wrong number of const arguments: expected 1, found 0 + --> $DIR/invalid-enum.rs:26:3 + | +LL | test_2::<_, CompileFlag::A>(0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument + +error[E0107]: wrong number of type arguments: expected 1, found 2 + --> $DIR/invalid-enum.rs:26:15 + | +LL | test_2::<_, CompileFlag::A>(0); + | ^^^^^^^^^^^^^^ unexpected type argument + | +help: If this generic argument was intended as a const parameter, try surrounding it with braces: + | +LL | test_2::<_, { CompileFlag::A }>(0); + | ^ ^ + +error: aborting due to 11 previous errors Some errors have detailed explanations: E0107, E0573. For more information about an error, try `rustc --explain E0107`.