diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4aca01d9411c7..56fafacd722be 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 af875c2f9e8a1..78696da0470e7 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 93f3afe1aea6b..c9cccb2b03ac4 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 f2406bd8540b5..644ba5981a63d 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 cec33ba87dea4..b783bbfad16e9 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 ac686e40076eb..efb221b92324e 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 0000000000000..ee98e5eb4a01f --- /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; // 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 0000000000000..0e7acfb673d1d --- /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)] + | ^^^^^^^^^^^^^^ +