about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkadmin <julianknodt@gmail.com>2020-08-22 03:32:07 +0000
committerkadmin <julianknodt@gmail.com>2020-09-03 16:02:56 +0000
commit4b132eefb48880a7a3781efe844d13845b070c07 (patch)
treeda88ef76cfa33fe859b1a1be912144c60e5f9450
parent08deb863bdebfcbbb71c18acf903eca84f1df4e7 (diff)
downloadrust-4b132eefb48880a7a3781efe844d13845b070c07.tar.gz
rust-4b132eefb48880a7a3781efe844d13845b070c07.zip
Initial commit
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs58
-rw-r--r--src/test/ui/const-generics/invalid-enum.rs17
-rw-r--r--src/test/ui/const-generics/invalid-enum.stderr27
-rw-r--r--src/test/ui/const-generics/issues/issue-62878.stderr2
4 files changed, 90 insertions, 14 deletions
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<rustc_errors::DiagnosticBuilder<'_>>)>| 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<const CF: CompileFlag>() {}
+
+pub fn main() {
+  test::<CompileFlag::A>();
+  //~^ 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::<CompileFlag::A>();
+   |          ^^^^^^^^^^^^^^
+   |          |
+   |          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::<CompileFlag::A>();
+   |   ^^^^^^^^^^^^^^^^^^^^^^ expected 1 const argument
+
+error[E0107]: wrong number of type arguments: expected 0, found 1
+  --> $DIR/invalid-enum.rs:13:10
+   |
+LL |   test::<CompileFlag::A>();
+   |          ^^^^^^^^^^^^^^ 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