about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ty/mod.rs18
-rw-r--r--src/librustc_mir/monomorphize/collector.rs5
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs3
-rw-r--r--src/librustc_typeck/variance/constraints.rs30
-rw-r--r--src/librustc_typeck/variance/solve.rs13
-rw-r--r--src/librustc_typeck/variance/terms.rs2
-rw-r--r--src/test/ui/const-generics/unused-const-param.rs8
-rw-r--r--src/test/ui/const-generics/unused-const-param.stderr6
8 files changed, 47 insertions, 38 deletions
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 4aca01d9411..56fafacd722 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -934,12 +934,10 @@ impl<'a, 'gcx, 'tcx> Generics {
     }
 
     pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
-        for param in &self.params {
-            match param.kind {
-                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => return true,
-                GenericParamDefKind::Lifetime => {}
-            }
+        if self.own_requires_monomorphization() {
+            return true;
         }
+
         if let Some(parent_def_id) = self.parent {
             let parent = tcx.generics_of(parent_def_id);
             parent.requires_monomorphization(tcx)
@@ -948,6 +946,16 @@ impl<'a, 'gcx, 'tcx> Generics {
         }
     }
 
+    pub fn own_requires_monomorphization(&self) -> bool {
+        for param in &self.params {
+            match param.kind {
+                GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => return true,
+                GenericParamDefKind::Lifetime => {}
+            }
+        }
+        false
+    }
+
     pub fn region_param(&'tcx self,
                         param: &EarlyBoundRegion,
                         tcx: TyCtxt<'a, 'gcx, 'tcx>)
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index af875c2f9e8..78696da0470 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -480,6 +480,8 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let type_length_limit = *tcx.sess.type_length_limit.get();
     // We include the const length in the type length, as it's better
     // to be overly conservative.
+    // FIXME(const_generics): we should instead uniformly walk through `substs`,
+    // ignoring lifetimes.
     if type_length + const_length > type_length_limit {
         // The instance name is already known to be too long for rustc.
         // Show only the first and last 32 characters to avoid blasting
@@ -1135,8 +1137,7 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         continue;
                     }
 
-                    let counts = tcx.generics_of(method.def_id).own_counts();
-                    if counts.types + counts.consts != 0 {
+                    if tcx.generics_of(method.def_id).own_requires_monomorphization() {
                         continue;
                     }
 
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 93f3afe1aea..c9cccb2b03a 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -560,8 +560,7 @@ fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: D
 
     // FIXME: when we make this a hard error, this should have its
     // own error code.
-    let counts = tcx.generics_of(def_id).own_counts();
-    let message = if counts.types + counts.consts != 0 {
+    let message = if tcx.generics_of(def_id).own_requires_monomorphization() {
         "#[derive] can't be used on a #[repr(packed)] struct with \
          type or const parameters (error E0133)".to_string()
     } else {
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index f2406bd8540..644ba5981a6 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -4,7 +4,6 @@
 //! We walk the set of items and, for each member, generate new constraints.
 
 use hir::def_id::DefId;
-use rustc::mir::interpret::ConstValue;
 use rustc::ty::subst::{SubstsRef, UnpackedKind};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::hir;
@@ -239,8 +238,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 UnpackedKind::Type(ty) => {
                     self.add_constraints_from_ty(current, ty, variance_i)
                 }
-                UnpackedKind::Const(ct) => {
-                    self.add_constraints_from_const(current, ct, variance_i)
+                UnpackedKind::Const(_) => {
+                    // Consts impose no constraints.
                 }
             }
         }
@@ -275,9 +274,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 self.add_constraints_from_mt(current, &ty::TypeAndMut { ty, mutbl }, variance);
             }
 
-            ty::Array(typ, len) => {
+            ty::Array(typ, _) => {
                 self.add_constraints_from_ty(current, typ, variance);
-                self.add_constraints_from_const(current, len, variance);
             }
 
             ty::Slice(typ) => {
@@ -395,8 +393,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                 UnpackedKind::Type(ty) => {
                     self.add_constraints_from_ty(current, ty, variance_i)
                 }
-                UnpackedKind::Const(ct) => {
-                    self.add_constraints_from_const(current, ct, variance_i)
+                UnpackedKind::Const(_) => {
+                    // Consts impose no constraints.
                 }
             }
         }
@@ -449,24 +447,6 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         }
     }
 
-    fn add_constraints_from_const(
-        &mut self,
-        current: &CurrentItem,
-        ct: &ty::Const<'tcx>,
-        variance: VarianceTermPtr<'a>
-    ) {
-        debug!(
-            "add_constraints_from_const(ct={:?}, variance={:?})",
-            ct,
-            variance
-        );
-
-        self.add_constraints_from_ty(current, ct.ty, variance);
-        if let ConstValue::Param(ref data) = ct.val {
-            self.add_constraint(current, data.index, variance);
-        }
-    }
-
     /// Adds constraints appropriate for a mutability-type pair
     /// appearing in a context with ambient variance `variance`
     fn add_constraints_from_mt(&mut self,
diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs
index cec33ba87de..b783bbfad16 100644
--- a/src/librustc_typeck/variance/solve.rs
+++ b/src/librustc_typeck/variance/solve.rs
@@ -85,12 +85,19 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
         self.terms_cx.inferred_starts.iter().map(|(&id, &InferredIndex(start))| {
             let def_id = tcx.hir().local_def_id_from_hir_id(id);
             let generics = tcx.generics_of(def_id);
+            let count = generics.count();
 
-            let mut variances = solutions[start..start+generics.count()].to_vec();
-
+            let mut variances = solutions[start..(start + count)].to_vec();
             debug!("id={} variances={:?}", id, variances);
 
-            // Functions can have unused type parameters: make those invariant.
+            // Const parameters are always invariant.
+            for (idx, param) in generics.params.iter().enumerate() {
+                if let ty::GenericParamDefKind::Const = param.kind {
+                    variances[idx] = ty::Invariant;
+                }
+            }
+
+            // Functions are permitted to have unused generic parameters: make those invariant.
             if let ty::FnDef(..) = tcx.type_of(def_id).sty {
                 for variance in &mut variances {
                     if *variance == ty::Bivariant {
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index ac686e40076..efb221b9232 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -119,7 +119,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
         // for a particular item are assigned continuous indices.
 
         let arena = self.arena;
-        self.inferred_terms.extend((start..start+count).map(|i| {
+        self.inferred_terms.extend((start..(start + count)).map(|i| {
             &*arena.alloc(InferredTerm(InferredIndex(i)))
         }));
     }
diff --git a/src/test/ui/const-generics/unused-const-param.rs b/src/test/ui/const-generics/unused-const-param.rs
new file mode 100644
index 00000000000..ee98e5eb4a0
--- /dev/null
+++ b/src/test/ui/const-generics/unused-const-param.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct A<const N: usize>; // ok
+
+fn main() {}
diff --git a/src/test/ui/const-generics/unused-const-param.stderr b/src/test/ui/const-generics/unused-const-param.stderr
new file mode 100644
index 00000000000..0e7acfb673d
--- /dev/null
+++ b/src/test/ui/const-generics/unused-const-param.stderr
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/unused-const-param.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+