]> git.lizzy.rs Git - rust.git/commitdiff
Implement wfcheck for const parameters
authorvarkor <github@varkor.com>
Wed, 20 Feb 2019 01:17:15 +0000 (01:17 +0000)
committervarkor <github@varkor.com>
Tue, 5 Mar 2019 22:13:11 +0000 (22:13 +0000)
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
src/librustc_typeck/check/wfcheck.rs

index 860fa526a1b9133343df385ee4f741bc04b066bd..16cf25f0d4916e183e05384571dcba7063adc075 100644 (file)
@@ -6,6 +6,7 @@
 use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable, ToPredicate};
 use rustc::ty::subst::{Subst, InternalSubsts};
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
+use rustc::mir::interpret::ConstValue;
 use rustc::middle::lang_items;
 use rustc::infer::opaque_types::may_define_existential_type;
 
@@ -436,7 +437,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
     // struct Foo<T = Vec<[u32]>> { .. }
     // Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
     for param in &generics.params {
-        if let GenericParamDefKind::Type {..} = param.kind {
+        if let GenericParamDefKind::Type { .. } = param.kind {
             if is_our_default(&param) {
                 let ty = fcx.tcx.type_of(param.def_id);
                 // ignore dependent defaults -- that is, where the default of one type
@@ -464,7 +465,7 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
                 // All regions are identity.
                 fcx.tcx.mk_param_from_def(param)
             }
-            GenericParamDefKind::Type {..} => {
+            GenericParamDefKind::Type { .. } => {
                 // If the param has a default,
                 if is_our_default(param) {
                     let default_ty = fcx.tcx.type_of(param.def_id);
@@ -477,6 +478,10 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
                 // Mark unwanted params as err.
                 fcx.tcx.types.err.into()
             }
+            GenericParamDefKind::Const => {
+                // FIXME(const_generics:defaults)
+                fcx.tcx.types.err.into()
+            }
         }
     });
     // Now we build the substituted predicates.
@@ -497,6 +502,16 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
             fn visit_region(&mut self, _: ty::Region<'tcx>) -> bool {
                 true
             }
+
+            fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
+                if let ty::LazyConst::Evaluated(ty::Const {
+                    val: ConstValue::Param(param),
+                    ..
+                }) = c {
+                    self.params.insert(param.index);
+                }
+                c.super_visit_with(self)
+            }
         }
         let mut param_count = CountParams::default();
         let has_region = pred.visit_with(&mut param_count);
@@ -617,11 +632,10 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
                         for (subst, param) in substs.iter().zip(&generics.params) {
                             match subst.unpack() {
                                 ty::subst::UnpackedKind::Type(ty) => match ty.sty {
-                                    ty::Param(..) => {},
+                                    ty::Param(..) => {}
                                     // prevent `fn foo() -> Foo<u32>` from being defining
                                     _ => {
-                                        tcx
-                                            .sess
+                                        tcx.sess
                                             .struct_span_err(
                                                 span,
                                                 "non-defining existential type use \
@@ -636,8 +650,9 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
                                                 ),
                                             )
                                             .emit();
-                                    },
-                                }, // match ty
+                                    }
+                                }
+
                                 ty::subst::UnpackedKind::Lifetime(region) => {
                                     let param_span = tcx.def_span(param.def_id);
                                     if let ty::ReStatic = region {
@@ -658,7 +673,31 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
                                     } else {
                                         seen.entry(region).or_default().push(param_span);
                                     }
-                                },
+                                }
+
+                                ty::subst::UnpackedKind::Const(ct) => match ct {
+                                    ty::LazyConst::Evaluated(ty::Const {
+                                        val: ConstValue::Param(_),
+                                        ..
+                                    }) => {}
+                                    _ => {
+                                        tcx.sess
+                                            .struct_span_err(
+                                                span,
+                                                "non-defining existential type use \
+                                                in defining scope",
+                                            )
+                                            .span_note(
+                                                tcx.def_span(param.def_id),
+                                                &format!(
+                                                    "used non-generic const {} for \
+                                                    generic parameter",
+                                                    ty,
+                                                ),
+                                            )
+                                            .emit();
+                                    }
+                                }
                             } // match subst
                         } // for (subst, param)
                         for (_, spans) in seen {
@@ -942,7 +981,9 @@ fn reject_shadowing_parameters(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) {
     let parent = tcx.generics_of(generics.parent.unwrap());
     let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind {
         GenericParamDefKind::Lifetime => None,
-        GenericParamDefKind::Type {..} => Some((param.name, param.def_id)),
+        GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => {
+            Some((param.name, param.def_id))
+        }
     }).collect();
 
     for method_param in &generics.params {