Skip to content

Commit 691d054

Browse files
varkoryodaldevoid
andcommitted
Take const generics into account when monomorphising
Co-Authored-By: Gabriel Smith <[email protected]>
1 parent 2ce19ae commit 691d054

File tree

3 files changed

+60
-22
lines changed

3 files changed

+60
-22
lines changed

src/librustc_mir/monomorphize/collector.rs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,17 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
466466
instance: Instance<'tcx>)
467467
{
468468
let type_length = instance.substs.types().flat_map(|ty| ty.walk()).count();
469-
debug!(" => type length={}", type_length);
469+
let const_length = instance.substs.consts()
470+
.filter_map(|ct| {
471+
if let ty::LazyConst::Evaluated(ct) = ct {
472+
Some(ct.ty.walk())
473+
} else {
474+
None
475+
}
476+
})
477+
.flatten()
478+
.count();
479+
debug!(" => type length={}, const length={}", type_length, const_length);
470480

471481
// Rust code can easily create exponentially-long types using only a
472482
// polynomial recursion depth. Even with the default recursion
@@ -475,7 +485,9 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
475485
//
476486
// Bail out in these cases to avoid that bad user experience.
477487
let type_length_limit = *tcx.sess.type_length_limit.get();
478-
if type_length > type_length_limit {
488+
// We include the const length in the type length, as it's better
489+
// to be overly conservative.
490+
if type_length + const_length > type_length_limit {
479491
// The instance name is already known to be too long for rustc. Use
480492
// `{:.64}` to avoid blasting the user's terminal with thousands of
481493
// lines of type-name.
@@ -490,7 +502,7 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
490502

491503
diag.note(&format!(
492504
"consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate",
493-
type_length_limit*2));
505+
type_length_limit * 2));
494506
diag.emit();
495507
tcx.sess.abort_if_errors();
496508
}
@@ -759,10 +771,10 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance:
759771
return false
760772
}
761773

762-
// If this instance has no type parameters, it cannot be a shared
774+
// If this instance has non-erasable parameters, it cannot be a shared
763775
// monomorphization. Non-generic instances are already handled above
764776
// by `is_reachable_non_generic()`
765-
if substs.types().next().is_none() {
777+
if substs.non_erasable_generics().next().is_none() {
766778
return false
767779
}
768780

@@ -1113,14 +1125,16 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
11131125
continue;
11141126
}
11151127

1116-
if tcx.generics_of(method.def_id).own_counts().types != 0 {
1128+
let counts = tcx.generics_of(method.def_id).own_counts();
1129+
if counts.types + counts.consts != 0 {
11171130
continue;
11181131
}
11191132

11201133
let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| {
11211134
match param.kind {
11221135
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
1123-
GenericParamDefKind::Type {..} => {
1136+
GenericParamDefKind::Type { .. } |
1137+
GenericParamDefKind::Const => {
11241138
trait_ref.substs[param.index as usize]
11251139
}
11261140
}

src/librustc_mir/monomorphize/item.rs

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use crate::monomorphize::Instance;
22
use rustc::hir;
33
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
4+
use rustc::mir::interpret::ConstValue;
45
use rustc::session::config::OptLevel;
5-
use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts, GeneratorSubsts};
6+
use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, LazyConst, ParamConst};
67
use rustc::ty::subst::{SubstsRef, InternalSubsts};
78
use syntax::ast;
89
use syntax::attr::InlineAttr;
@@ -44,7 +45,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug {
4445
fn is_generic_fn(&self) -> bool {
4546
match *self.as_mono_item() {
4647
MonoItem::Fn(ref instance) => {
47-
instance.substs.types().next().is_some()
48+
instance.substs.non_erasable_generics().next().is_some()
4849
}
4950
MonoItem::Static(..) |
5051
MonoItem::GlobalAsm(..) => false,
@@ -267,7 +268,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
267268
ty::Float(ast::FloatTy::F64) => output.push_str("f64"),
268269
ty::Adt(adt_def, substs) => {
269270
self.push_def_path(adt_def.did, output);
270-
self.push_type_params(substs, iter::empty(), output, debug);
271+
self.push_generic_params(substs, iter::empty(), output, debug);
271272
},
272273
ty::Tuple(component_types) => {
273274
output.push('(');
@@ -312,7 +313,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
312313
ty::Dynamic(ref trait_data, ..) => {
313314
if let Some(principal) = trait_data.principal() {
314315
self.push_def_path(principal.def_id(), output);
315-
self.push_type_params(
316+
self.push_generic_params(
316317
principal.skip_binder().substs,
317318
trait_data.projection_bounds(),
318319
output,
@@ -373,7 +374,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
373374
self.push_def_path(def_id, output);
374375
let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
375376
let substs = substs.truncate_to(self.tcx, generics);
376-
self.push_type_params(substs, iter::empty(), output, debug);
377+
self.push_generic_params(substs, iter::empty(), output, debug);
377378
}
378379
ty::Error |
379380
ty::Bound(..) |
@@ -394,6 +395,24 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
394395
}
395396
}
396397

398+
// FIXME(const_generics): handle debug printing.
399+
pub fn push_const_name(&self, c: &LazyConst<'tcx>, output: &mut String, debug: bool) {
400+
match c {
401+
LazyConst::Unevaluated(..) => output.push_str("_: _"),
402+
LazyConst::Evaluated(Const { ty, val }) => {
403+
match val {
404+
ConstValue::Infer(..) => output.push_str("_"),
405+
ConstValue::Param(ParamConst { name, .. }) => {
406+
write!(output, "{}", name).unwrap();
407+
}
408+
_ => write!(output, "{:?}", c).unwrap(),
409+
}
410+
output.push_str(": ");
411+
self.push_type_name(ty, output, debug);
412+
}
413+
}
414+
}
415+
397416
pub fn push_def_path(&self,
398417
def_id: DefId,
399418
output: &mut String) {
@@ -421,15 +440,15 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
421440
output.pop();
422441
}
423442

424-
fn push_type_params<I>(&self,
425-
substs: SubstsRef<'tcx>,
426-
projections: I,
427-
output: &mut String,
428-
debug: bool)
429-
where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>>
430-
{
443+
fn push_generic_params<I>(
444+
&self,
445+
substs: SubstsRef<'tcx>,
446+
projections: I,
447+
output: &mut String,
448+
debug: bool,
449+
) where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>> {
431450
let mut projections = projections.peekable();
432-
if substs.types().next().is_none() && projections.peek().is_none() {
451+
if substs.non_erasable_generics().next().is_none() && projections.peek().is_none() {
433452
return;
434453
}
435454

@@ -449,6 +468,11 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
449468
output.push_str(", ");
450469
}
451470

471+
for const_parameter in substs.consts() {
472+
self.push_const_name(const_parameter, output, debug);
473+
output.push_str(", ");
474+
}
475+
452476
output.pop();
453477
output.pop();
454478

@@ -460,6 +484,6 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
460484
output: &mut String,
461485
debug: bool) {
462486
self.push_def_path(instance.def_id(), output);
463-
self.push_type_params(instance.substs, iter::empty(), output, debug);
487+
self.push_generic_params(instance.substs, iter::empty(), output, debug);
464488
}
465489
}

src/librustc_mir/monomorphize/partitioning.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ fn mono_item_visibility(
448448
return Visibility::Hidden
449449
}
450450

451-
let is_generic = instance.substs.types().next().is_some();
451+
let is_generic = instance.substs.non_erasable_generics().next().is_some();
452452

453453
// Upstream `DefId` instances get different handling than local ones
454454
if !def_id.is_local() {

0 commit comments

Comments
 (0)