]> git.lizzy.rs Git - rust.git/commitdiff
sort generic param order in generics_of
authorBastian Kauschke <bastian_kauschke@hotmail.de>
Thu, 19 Mar 2020 19:20:09 +0000 (20:20 +0100)
committerBastian Kauschke <bastian_kauschke@hotmail.de>
Thu, 19 Mar 2020 19:20:09 +0000 (20:20 +0100)
src/librustc_ast_passes/ast_validation.rs
src/librustc_typeck/collect.rs
src/test/ui/const-generics/argument_order.rs [new file with mode: 0644]
src/test/ui/const-generics/argument_order.stderr [new file with mode: 0644]

index a2d83a525cc7876b21ce55f9a5a7ab9be7c8de3e..41209392b081178d806ba050a5d7a1ca6ed2bb9f 100644 (file)
@@ -645,6 +645,8 @@ fn deny_items(&self, trait_items: &[P<AssocItem>], ident_span: Span) {
     }
 }
 
+/// Checks that generic parameters are in the correct order,
+/// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`)
 fn validate_generic_param_order<'a>(
     sess: &Session,
     handler: &rustc_errors::Handler,
index cd63dacdcda0e0a3f07fa4cdd57b05c8fcdaffa0..42d6e945ee2c296f78849656c96465c830790e9f 100644 (file)
@@ -1291,47 +1291,67 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
     // Now create the real type and const parameters.
     let type_start = own_start - has_self as u32 + params.len() as u32;
     let mut i = 0;
-    params.extend(ast_generics.params.iter().filter_map(|param| {
-        let kind = match param.kind {
-            GenericParamKind::Type { ref default, synthetic, .. } => {
-                if !allow_defaults && default.is_some() {
-                    if !tcx.features().default_type_parameter_fallback {
-                        tcx.struct_span_lint_hir(
-                            lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
-                            param.hir_id,
-                            param.span,
-                            |lint| {
-                                lint.build(
-                                    "defaults for type parameters are only allowed in \
-                                            `struct`, `enum`, `type`, or `trait` definitions.",
-                                )
-                                .emit();
-                            },
-                        );
-                    }
-                }
 
-                ty::GenericParamDefKind::Type {
-                    has_default: default.is_some(),
-                    object_lifetime_default: object_lifetime_defaults
-                        .as_ref()
-                        .map_or(rl::Set1::Empty, |o| o[i]),
-                    synthetic,
+    // FIXME(const_generics): a few places in the compiler expect generic params
+    // to be in the order lifetimes, then type params, then const params.
+    //
+    // To prevent internal errors in case a const params are supplied in front of
+    // type parameters we first add all type params, then all const params.
+    params.extend(ast_generics.params.iter().filter_map(|param| {
+        if let GenericParamKind::Type { ref default, synthetic, .. } = param.kind {
+            if !allow_defaults && default.is_some() {
+                if !tcx.features().default_type_parameter_fallback {
+                    tcx.struct_span_lint_hir(
+                        lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
+                        param.hir_id,
+                        param.span,
+                        |lint| {
+                            lint.build(
+                                "defaults for type parameters are only allowed in \
+                                        `struct`, `enum`, `type`, or `trait` definitions.",
+                            )
+                            .emit();
+                        },
+                    );
                 }
             }
-            GenericParamKind::Const { .. } => ty::GenericParamDefKind::Const,
-            _ => return None,
-        };
 
-        let param_def = ty::GenericParamDef {
-            index: type_start + i as u32,
-            name: param.name.ident().name,
-            def_id: tcx.hir().local_def_id(param.hir_id),
-            pure_wrt_drop: param.pure_wrt_drop,
-            kind,
-        };
-        i += 1;
-        Some(param_def)
+            let kind = ty::GenericParamDefKind::Type {
+                has_default: default.is_some(),
+                object_lifetime_default: object_lifetime_defaults
+                    .as_ref()
+                    .map_or(rl::Set1::Empty, |o| o[i]),
+                synthetic,
+            };
+
+            let param_def = ty::GenericParamDef {
+                index: type_start + i as u32,
+                name: param.name.ident().name,
+                def_id: tcx.hir().local_def_id(param.hir_id),
+                pure_wrt_drop: param.pure_wrt_drop,
+                kind,
+            };
+            i += 1;
+            Some(param_def)
+        } else {
+            None
+        }
+    }));
+
+    params.extend(ast_generics.params.iter().filter_map(|param| {
+        if let GenericParamKind::Const { .. } = param.kind {
+            let param_def = ty::GenericParamDef {
+                index: type_start + i as u32,
+                name: param.name.ident().name,
+                def_id: tcx.hir().local_def_id(param.hir_id),
+                pure_wrt_drop: param.pure_wrt_drop,
+                kind: ty::GenericParamDefKind::Const,
+            };
+            i += 1;
+            Some(param_def)
+        } else {
+            None
+        }
     }));
 
     // provide junk type parameter defs - the only place that
diff --git a/src/test/ui/const-generics/argument_order.rs b/src/test/ui/const-generics/argument_order.rs
new file mode 100644 (file)
index 0000000..3446600
--- /dev/null
@@ -0,0 +1,9 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct Bad<const N: usize, T> { //~ ERROR type parameters must be declared prior
+    arr: [u8; { N }],
+    another: T,
+}
+
+fn main() { }
diff --git a/src/test/ui/const-generics/argument_order.stderr b/src/test/ui/const-generics/argument_order.stderr
new file mode 100644 (file)
index 0000000..1e3b364
--- /dev/null
@@ -0,0 +1,16 @@
+error: type parameters must be declared prior to const parameters
+  --> $DIR/argument_order.rs:4:28
+   |
+LL | struct Bad<const N: usize, T> {
+   |           -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `<T, const N: usize>`
+
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/argument_order.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: aborting due to previous error
+