From 4b132eefb48880a7a3781efe844d13845b070c07 Mon Sep 17 00:00:00 2001 From: kadmin Date: Sat, 22 Aug 2020 03:32:07 +0000 Subject: [PATCH] Initial commit --- compiler/rustc_typeck/src/astconv/generics.rs | 58 ++++++++++++++----- src/test/ui/const-generics/invalid-enum.rs | 17 ++++++ .../ui/const-generics/invalid-enum.stderr | 27 +++++++++ .../const-generics/issues/issue-62878.stderr | 2 + 4 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/const-generics/invalid-enum.rs create mode 100644 src/test/ui/const-generics/invalid-enum.stderr diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 84dab6de958..43c7b30b788 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -367,7 +367,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if position != GenericArgPosition::Type && !args.bindings.is_empty() { - Self::prohibit_assoc_ty_binding(tcx, args.bindings[0].span); + AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span); } let explicit_late_bound = @@ -392,7 +392,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if silent { - return Err(true); + return Err((0i32, None)); } // Unfortunately lifetime and type parameter mismatches are typically styled @@ -441,16 +441,25 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for span in spans { err.span_label(span, label.as_str()); } - err.emit(); - Err(true) + assert_ne!(bound, provided); + Err((bound as i32 - provided as i32, Some(err))) }; + let emit_correct = + |correct: Result<(), (_, Option>)>| match correct { + Ok(()) => Ok(()), + Err((v, None)) => Err(v == 0), + Err((v, Some(mut err))) => { + err.emit(); + Err(v == 0) + } + }; - let mut arg_count_correct = Ok(()); let mut unexpected_spans = vec![]; + let mut lifetime_count_correct = Ok(()); if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes { - arg_count_correct = check_kind_count( + lifetime_count_correct = check_kind_count( "lifetime", param_counts.lifetimes, param_counts.lifetimes, @@ -458,12 +467,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { 0, &mut unexpected_spans, explicit_late_bound == ExplicitLateBound::Yes, - ) - .and(arg_count_correct); + ); } + // FIXME(const_generics:defaults) + let mut const_count_correct = Ok(()); if !infer_args || arg_counts.consts > param_counts.consts { - arg_count_correct = check_kind_count( + const_count_correct = check_kind_count( "const", param_counts.consts, param_counts.consts, @@ -471,13 +481,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { arg_counts.lifetimes + arg_counts.types, &mut unexpected_spans, false, - ) - .and(arg_count_correct); + ); } + // Note that type errors are currently be emitted *after* const errors. + let mut type_count_correct = Ok(()); if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize { - arg_count_correct = check_kind_count( + type_count_correct = check_kind_count( "type", param_counts.types - defaults.types - has_self as usize, param_counts.types - has_self as usize, @@ -485,10 +496,29 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { arg_counts.lifetimes, &mut unexpected_spans, false, - ) - .and(arg_count_correct); + ); } + // 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))) = &mut const_count_correct { + if let Err((t_mismatch, Some(ref mut type_err))) = &mut type_count_correct { + if *c_mismatch == -*t_mismatch && *t_mismatch < 0 { + for i in 0..*c_mismatch as usize { + // let t_span = unexpected_type_spans[i].clone(); + let ident = args.args[arg_counts.lifetimes + i].id(); + type_err.help(&format!( + "For more complex types, surround with braces: `{{ {} }}`", + ident, + )); + } + } + } + } + + let arg_count_correct = emit_correct(lifetime_count_correct) + .and(emit_correct(const_count_correct)) + .and(emit_correct(type_count_correct)); + GenericArgCountResult { explicit_late_bound, correct: arg_count_correct.map_err(|reported_err| GenericArgCountMismatch { diff --git a/src/test/ui/const-generics/invalid-enum.rs b/src/test/ui/const-generics/invalid-enum.rs new file mode 100644 index 00000000000..05c13e8fe0c --- /dev/null +++ b/src/test/ui/const-generics/invalid-enum.rs @@ -0,0 +1,17 @@ +#![feature(const_generics)] +#![allow(incomplete_features)] + +#[derive(PartialEq, Eq)] +enum CompileFlag { + A, + B, +} + +pub fn test() {} + +pub fn main() { + test::(); + //~^ ERROR: expected type, found variant + //~| 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 new file mode 100644 index 00000000000..096e478d4ab --- /dev/null +++ b/src/test/ui/const-generics/invalid-enum.stderr @@ -0,0 +1,27 @@ +error[E0573]: expected type, found variant `CompileFlag::A` + --> $DIR/invalid-enum.rs:13:10 + | +LL | test::(); + | ^^^^^^^^^^^^^^ + | | + | 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 + | +LL | test::(); + | ^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument + +error[E0107]: wrong number of type arguments: expected 0, found 1 + --> $DIR/invalid-enum.rs:13:10 + | +LL | test::(); + | ^^^^^^^^^^^^^^ unexpected type argument + | + = help: For more complex types, surround with braces: `{ HirId { owner: DefId(0:5 ~ invalid_enum[317d]::main[0]), local_id: 1 } }` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0573. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/const-generics/issues/issue-62878.stderr b/src/test/ui/const-generics/issues/issue-62878.stderr index fe0990d8241..702fbfe84de 100644 --- a/src/test/ui/const-generics/issues/issue-62878.stderr +++ b/src/test/ui/const-generics/issues/issue-62878.stderr @@ -24,6 +24,8 @@ error[E0107]: wrong number of type arguments: expected 0, found 1 | LL | foo::<_, {[1]}>(); | ^ unexpected type argument + | + = help: For more complex types, surround with braces: `{ HirId { owner: DefId(0:7 ~ issue_62878[317d]::main[0]), local_id: 1 } }` error[E0308]: mismatched types --> $DIR/issue-62878.rs:7:15