]> git.lizzy.rs Git - rust.git/commitdiff
Take const generics into account when monomorphising
authorvarkor <github@varkor.com>
Wed, 20 Feb 2019 01:11:37 +0000 (01:11 +0000)
committervarkor <github@varkor.com>
Tue, 5 Mar 2019 22:08:44 +0000 (22:08 +0000)
Co-Authored-By: Gabriel Smith <yodaldevoid@users.noreply.github.com>
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/monomorphize/partitioning.rs

index 1f20c70dec503099698b908736200a908af10a38..2ce3bf43cfc775d2f0100a5953d692a60dfda3ba 100644 (file)
@@ -466,7 +466,17 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      instance: Instance<'tcx>)
 {
     let type_length = instance.substs.types().flat_map(|ty| ty.walk()).count();
-    debug!(" => type length={}", type_length);
+    let const_length = instance.substs.consts()
+        .filter_map(|ct| {
+            if let ty::LazyConst::Evaluated(ct) = ct {
+                Some(ct.ty.walk())
+            } else {
+                None
+            }
+        })
+        .flatten()
+        .count();
+    debug!(" => type length={}, const length={}", type_length, const_length);
 
     // Rust code can easily create exponentially-long types using only a
     // polynomial recursion depth. Even with the default recursion
@@ -475,7 +485,9 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     //
     // Bail out in these cases to avoid that bad user experience.
     let type_length_limit = *tcx.sess.type_length_limit.get();
-    if type_length > type_length_limit {
+    // We include the const length in the type length, as it's better
+    // to be overly conservative.
+    if type_length + const_length > type_length_limit {
         // The instance name is already known to be too long for rustc. Use
         // `{:.64}` to avoid blasting the user's terminal with thousands of
         // lines of type-name.
@@ -490,7 +502,7 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
         diag.note(&format!(
             "consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate",
-            type_length_limit*2));
+            type_length_limit * 2));
         diag.emit();
         tcx.sess.abort_if_errors();
     }
@@ -759,10 +771,10 @@ fn is_available_upstream_generic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             return false
         }
 
-        // If this instance has no type parameters, it cannot be a shared
+        // If this instance has non-erasable parameters, it cannot be a shared
         // monomorphization. Non-generic instances are already handled above
         // by `is_reachable_non_generic()`
-        if substs.types().next().is_none() {
+        if substs.non_erasable_generics().next().is_none() {
             return false
         }
 
@@ -1113,14 +1125,16 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         continue;
                     }
 
-                    if tcx.generics_of(method.def_id).own_counts().types != 0 {
+                    let counts = tcx.generics_of(method.def_id).own_counts();
+                    if counts.types + counts.consts != 0 {
                         continue;
                     }
 
                     let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| {
                         match param.kind {
                             GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
-                            GenericParamDefKind::Type {..} => {
+                            GenericParamDefKind::Type { .. } |
+                            GenericParamDefKind::Const => {
                                 trait_ref.substs[param.index as usize]
                             }
                         }
index 059af2dbba944710f23d5e815e6c3d451acf35c8..f0d19ec8bf2fa71ca70a7976b3d1c510b3897aca 100644 (file)
@@ -1,8 +1,9 @@
 use crate::monomorphize::Instance;
 use rustc::hir;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
+use rustc::mir::interpret::ConstValue;
 use rustc::session::config::OptLevel;
-use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts, GeneratorSubsts};
+use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, LazyConst, ParamConst};
 use rustc::ty::subst::{SubstsRef, InternalSubsts};
 use syntax::ast;
 use syntax::attr::InlineAttr;
@@ -44,7 +45,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
     fn is_generic_fn(&self) -> bool {
         match *self.as_mono_item() {
             MonoItem::Fn(ref instance) => {
-                instance.substs.types().next().is_some()
+                instance.substs.non_erasable_generics().next().is_some()
             }
             MonoItem::Static(..) |
             MonoItem::GlobalAsm(..) => false,
@@ -267,7 +268,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
             ty::Float(ast::FloatTy::F64) => output.push_str("f64"),
             ty::Adt(adt_def, substs) => {
                 self.push_def_path(adt_def.did, output);
-                self.push_type_params(substs, iter::empty(), output, debug);
+                self.push_generic_params(substs, iter::empty(), output, debug);
             },
             ty::Tuple(component_types) => {
                 output.push('(');
@@ -312,7 +313,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
             ty::Dynamic(ref trait_data, ..) => {
                 if let Some(principal) = trait_data.principal() {
                     self.push_def_path(principal.def_id(), output);
-                    self.push_type_params(
+                    self.push_generic_params(
                         principal.skip_binder().substs,
                         trait_data.projection_bounds(),
                         output,
@@ -373,7 +374,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
                 self.push_def_path(def_id, output);
                 let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
                 let substs = substs.truncate_to(self.tcx, generics);
-                self.push_type_params(substs, iter::empty(), output, debug);
+                self.push_generic_params(substs, iter::empty(), output, debug);
             }
             ty::Error |
             ty::Bound(..) |
@@ -394,6 +395,24 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
         }
     }
 
+    // FIXME(const_generics): handle debug printing.
+    pub fn push_const_name(&self, c: &LazyConst<'tcx>, output: &mut String, debug: bool) {
+        match c {
+            LazyConst::Unevaluated(..) => output.push_str("_: _"),
+            LazyConst::Evaluated(Const { ty, val }) => {
+                match val {
+                    ConstValue::Infer(..) => output.push_str("_"),
+                    ConstValue::Param(ParamConst { name, .. }) => {
+                        write!(output, "{}", name).unwrap();
+                    }
+                    _ => write!(output, "{:?}", c).unwrap(),
+                }
+                output.push_str(": ");
+                self.push_type_name(ty, output, debug);
+            }
+        }
+    }
+
     pub fn push_def_path(&self,
                          def_id: DefId,
                          output: &mut String) {
@@ -421,15 +440,15 @@ pub fn push_def_path(&self,
         output.pop();
     }
 
-    fn push_type_params<I>(&self,
-                            substs: SubstsRef<'tcx>,
-                            projections: I,
-                            output: &mut String,
-                            debug: bool)
-        where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>>
-    {
+    fn push_generic_params<I>(
+        &self,
+        substs: SubstsRef<'tcx>,
+        projections: I,
+        output: &mut String,
+        debug: bool,
+    ) where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>> {
         let mut projections = projections.peekable();
-        if substs.types().next().is_none() && projections.peek().is_none() {
+        if substs.non_erasable_generics().next().is_none() && projections.peek().is_none() {
             return;
         }
 
@@ -449,6 +468,11 @@ fn push_type_params<I>(&self,
             output.push_str(", ");
         }
 
+        for const_parameter in substs.consts() {
+            self.push_const_name(const_parameter, output, debug);
+            output.push_str(", ");
+        }
+
         output.pop();
         output.pop();
 
@@ -460,6 +484,6 @@ pub fn push_instance_as_string(&self,
                                    output: &mut String,
                                    debug: bool) {
         self.push_def_path(instance.def_id(), output);
-        self.push_type_params(instance.substs, iter::empty(), output, debug);
+        self.push_generic_params(instance.substs, iter::empty(), output, debug);
     }
 }
index f342017603ed60501328d73d9b9e04fbab92fce3..f98bc476aafec872d40e0c85e67d20e92b795cb7 100644 (file)
@@ -448,7 +448,7 @@ fn mono_item_visibility(
         return Visibility::Hidden
     }
 
-    let is_generic = instance.substs.types().next().is_some();
+    let is_generic = instance.substs.non_erasable_generics().next().is_some();
 
     // Upstream `DefId` instances get different handling than local ones
     if !def_id.is_local() {