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
//
// 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.
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();
}
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
}
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]
}
}
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;
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,
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('(');
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,
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(..) |
}
}
+ // 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) {
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;
}
output.push_str(", ");
}
+ for const_parameter in substs.consts() {
+ self.push_const_name(const_parameter, output, debug);
+ output.push_str(", ");
+ }
+
output.pop();
output.pop();
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);
}
}