Skip to content

Commit f7d5593

Browse files
committed
rustc: rewrite PrintCx::parameterized to be much simpler and more general.
1 parent a5e719f commit f7d5593

File tree

2 files changed

+117
-197
lines changed

2 files changed

+117
-197
lines changed

src/librustc/ty/sty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ impl<'tcx> List<ExistentialPredicate<'tcx>> {
608608

609609
#[inline]
610610
pub fn projection_bounds<'a>(&'a self) ->
611-
impl Iterator<Item=ExistentialProjection<'tcx>> + Clone + 'a {
611+
impl Iterator<Item=ExistentialProjection<'tcx>> + 'a {
612612
self.iter().filter_map(|predicate| {
613613
match *predicate {
614614
ExistentialPredicate::Projection(p) => Some(p),

src/librustc/util/ppaux.rs

Lines changed: 116 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
88
use ty::{Param, Bound, RawPtr, Ref, Never, Tuple};
99
use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
1010
use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer};
11-
use ty::{self, Ty, TypeFoldable, GenericParamCount, GenericParamDefKind};
11+
use ty::{self, Ty, TypeFoldable};
1212
use ty::print::{PrintCx, Print};
1313

1414
use std::cell::Cell;
@@ -314,215 +314,125 @@ impl PrintCx<'a, 'gcx, 'tcx> {
314314
fn parameterized<F: fmt::Write>(
315315
&mut self,
316316
f: &mut F,
317-
did: DefId,
317+
mut def_id: DefId,
318318
substs: &Substs<'tcx>,
319-
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>> + Clone,
319+
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
320320
) -> fmt::Result {
321-
let key = self.tcx.def_key(did);
322-
323-
let verbose = self.is_verbose;
324-
let mut num_supplied_defaults = 0;
325-
let has_self;
326-
let mut own_counts: GenericParamCount = Default::default();
327-
let mut is_value_path = false;
328-
let mut item_name = Some(key.disambiguated_data.data.as_interned_str());
329-
let mut path_def_id = did;
330-
{
331-
// Unfortunately, some kinds of items (e.g., closures) don't have
332-
// generics. So walk back up the find the closest parent that DOES
333-
// have them.
334-
let mut item_def_id = did;
335-
loop {
336-
let key = self.tcx.def_key(item_def_id);
337-
match key.disambiguated_data.data {
338-
DefPathData::AssocTypeInTrait(_) |
339-
DefPathData::AssocTypeInImpl(_) |
340-
DefPathData::AssocExistentialInImpl(_) |
341-
DefPathData::Trait(_) |
342-
DefPathData::TraitAlias(_) |
343-
DefPathData::Impl |
344-
DefPathData::TypeNs(_) => {
345-
break;
346-
}
347-
DefPathData::ValueNs(_) |
348-
DefPathData::EnumVariant(_) => {
349-
is_value_path = true;
350-
break;
351-
}
352-
DefPathData::CrateRoot |
353-
DefPathData::Misc |
354-
DefPathData::Module(_) |
355-
DefPathData::MacroDef(_) |
356-
DefPathData::ClosureExpr |
357-
DefPathData::TypeParam(_) |
358-
DefPathData::LifetimeParam(_) |
359-
DefPathData::Field(_) |
360-
DefPathData::StructCtor |
361-
DefPathData::AnonConst |
362-
DefPathData::ImplTrait |
363-
DefPathData::GlobalMetaData(_) => {
364-
// if we're making a symbol for something, there ought
365-
// to be a value or type-def or something in there
366-
// *somewhere*
367-
item_def_id.index = key.parent.unwrap_or_else(|| {
368-
bug!("finding type for {:?}, encountered def-id {:?} with no \
369-
parent", did, item_def_id);
370-
});
371-
}
372-
}
321+
let mut key = self.tcx.def_key(def_id);
322+
let is_value_ns = match key.disambiguated_data.data {
323+
DefPathData::ValueNs(_) |
324+
DefPathData::EnumVariant(_) => true,
325+
326+
// Skip `StructCtor` so that `Struct::<T>` will be printed,
327+
// instead of the less pretty `Struct<T>::{{constructor}}`.
328+
DefPathData::StructCtor => {
329+
def_id.index = key.parent.unwrap();
330+
key = self.tcx.def_key(def_id);
331+
true
373332
}
374-
let mut generics = self.tcx.generics_of(item_def_id);
375-
let child_own_counts = generics.own_counts();
376-
has_self = generics.has_self;
377-
378-
let mut child_types = 0;
379-
if let Some(def_id) = generics.parent {
380-
// Methods.
381-
assert!(is_value_path);
382-
child_types = child_own_counts.types;
383-
generics = self.tcx.generics_of(def_id);
384-
own_counts = generics.own_counts();
385-
386-
if has_self {
387-
print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
388-
}
389333

390-
path_def_id = def_id;
391-
} else {
392-
item_name = None;
393-
394-
if is_value_path {
395-
// Functions.
396-
assert_eq!(has_self, false);
397-
} else {
398-
// Types and traits.
399-
own_counts = child_own_counts;
400-
}
401-
}
334+
_ => false,
335+
};
402336

403-
if !verbose {
404-
let mut type_params =
405-
generics.params.iter().rev().filter_map(|param| match param.kind {
406-
GenericParamDefKind::Lifetime => None,
407-
GenericParamDefKind::Type { has_default, .. } => {
408-
Some((param.def_id, has_default))
409-
}
410-
}).peekable();
411-
let has_default = {
412-
let has_default = type_params.peek().map(|(_, has_default)| has_default);
413-
*has_default.unwrap_or(&false)
414-
};
415-
if has_default {
416-
let types = substs.types().rev().skip(child_types);
417-
for ((def_id, has_default), actual) in type_params.zip(types) {
418-
if !has_default {
419-
break;
420-
}
421-
if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual {
422-
break;
423-
}
424-
num_supplied_defaults += 1;
425-
}
426-
}
337+
let generics = self.tcx.generics_of(def_id);
338+
339+
if let Some(parent_def_id) = generics.parent {
340+
assert_eq!(parent_def_id, DefId { index: key.parent.unwrap(), ..def_id });
341+
342+
let parent_generics = self.tcx.generics_of(parent_def_id);
343+
let parent_has_own_self =
344+
parent_generics.has_self && parent_generics.parent_count == 0;
345+
if parent_has_own_self {
346+
print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
427347
}
428-
}
429-
print!(f, self, write("{}", self.tcx.item_path_str(path_def_id)))?;
430-
let fn_trait_kind = self.tcx.lang_items().fn_trait_kind(path_def_id);
431-
432-
if !verbose && fn_trait_kind.is_some() {
433-
if let Tuple(ref args) = substs.type_at(1).sty {
434-
let mut projections = projections.clone();
435-
if let (Some(proj), None) = (projections.next(), projections.next()) {
436-
return self.fn_sig(f, args, false, proj.ty);
437-
}
348+
self.parameterized(f, parent_def_id, substs, iter::empty())?;
349+
if parent_has_own_self {
350+
write!(f, ">")?;
438351
}
352+
353+
write!(f, "::{}", key.disambiguated_data.data.as_interned_str())?;
354+
} else {
355+
print!(f, self, write("{}", self.tcx.item_path_str(def_id)))?;
439356
}
440357

441-
let empty = Cell::new(true);
442-
let start_or_continue = |f: &mut F, start: &str, cont: &str| {
443-
if empty.get() {
444-
empty.set(false);
358+
let mut empty = true;
359+
let mut start_or_continue = |f: &mut F, start: &str, cont: &str| {
360+
if empty {
361+
empty = false;
445362
write!(f, "{}", start)
446363
} else {
447364
write!(f, "{}", cont)
448365
}
449366
};
450367

451-
let print_regions = |f: &mut F, start: &str, skip, count| {
452-
// Don't print any regions if they're all erased.
453-
let regions = || substs.regions().skip(skip).take(count);
454-
if regions().all(|r: ty::Region<'_>| *r == ty::ReErased) {
455-
return Ok(());
368+
let start = if is_value_ns { "::<" } else { "<" };
369+
370+
let has_own_self = generics.has_self && generics.parent_count == 0;
371+
let params = &generics.params[has_own_self as usize..];
372+
373+
// Don't print any regions if they're all erased.
374+
let print_regions = params.iter().any(|param| {
375+
match substs[param.index as usize].unpack() {
376+
UnpackedKind::Lifetime(r) => *r != ty::ReErased,
377+
_ => false,
456378
}
379+
});
380+
381+
// Don't print args that are the defaults of their respective parameters.
382+
let num_supplied_defaults = if self.is_verbose {
383+
0
384+
} else {
385+
params.iter().rev().take_while(|param| {
386+
match param.kind {
387+
ty::GenericParamDefKind::Lifetime => false,
388+
ty::GenericParamDefKind::Type { has_default, .. } => {
389+
has_default && substs[param.index as usize] == Kind::from(
390+
self.tcx.type_of(param.def_id).subst(self.tcx, substs)
391+
)
392+
}
393+
}
394+
}).count()
395+
};
457396

458-
for region in regions() {
459-
let region: ty::Region<'_> = region;
460-
start_or_continue(f, start, ", ")?;
461-
if verbose {
462-
write!(f, "{:?}", region)?;
463-
} else {
464-
let s = region.to_string();
465-
if s.is_empty() {
466-
// This happens when the value of the region
467-
// parameter is not easily serialized. This may be
468-
// because the user omitted it in the first place,
469-
// or because it refers to some block in the code,
470-
// etc. I'm not sure how best to serialize this.
471-
write!(f, "'_")?;
397+
for param in &params[..params.len() - num_supplied_defaults] {
398+
match substs[param.index as usize].unpack() {
399+
UnpackedKind::Lifetime(region) => {
400+
if !print_regions {
401+
continue;
402+
}
403+
start_or_continue(f, start, ", ")?;
404+
if self.is_verbose {
405+
write!(f, "{:?}", region)?;
472406
} else {
473-
write!(f, "{}", s)?;
407+
let s = region.to_string();
408+
if s.is_empty() {
409+
// This happens when the value of the region
410+
// parameter is not easily serialized. This may be
411+
// because the user omitted it in the first place,
412+
// or because it refers to some block in the code,
413+
// etc. I'm not sure how best to serialize this.
414+
write!(f, "'_")?;
415+
} else {
416+
write!(f, "{}", s)?;
417+
}
474418
}
475419
}
420+
UnpackedKind::Type(ty) => {
421+
start_or_continue(f, start, ", ")?;
422+
ty.print_display(f, self)?;
423+
}
476424
}
477-
478-
Ok(())
479-
};
480-
481-
print_regions(f, "<", 0, own_counts.lifetimes)?;
482-
483-
let tps = substs.types()
484-
.take(own_counts.types - num_supplied_defaults)
485-
.skip(has_self as usize);
486-
487-
for ty in tps {
488-
start_or_continue(f, "<", ", ")?;
489-
ty.print_display(f, self)?;
490425
}
491426

492427
for projection in projections {
493-
start_or_continue(f, "<", ", ")?;
428+
start_or_continue(f, start, ", ")?;
494429
print!(f, self,
495430
write("{}=",
496431
self.tcx.associated_item(projection.item_def_id).ident),
497432
print_display(projection.ty))?;
498433
}
499434

500-
start_or_continue(f, "", ">")?;
501-
502-
// For values, also print their name and type parameters.
503-
if is_value_path {
504-
empty.set(true);
505-
506-
if has_self {
507-
write!(f, ">")?;
508-
}
509-
510-
if let Some(item_name) = item_name {
511-
write!(f, "::{}", item_name)?;
512-
}
513-
514-
print_regions(f, "::<", own_counts.lifetimes, usize::MAX)?;
515-
516-
// FIXME: consider being smart with defaults here too
517-
for ty in substs.types().skip(own_counts.types) {
518-
start_or_continue(f, "::<", ", ")?;
519-
ty.print_display(f, self)?;
520-
}
521-
522-
start_or_continue(f, "", ">")?;
523-
}
524-
525-
Ok(())
435+
start_or_continue(f, "", ">")
526436
}
527437

528438
fn in_binder<T, F>(&mut self, f: &mut F, value: &ty::Binder<T>) -> fmt::Result
@@ -616,19 +526,34 @@ define_print! {
616526
('tcx) &'tcx ty::List<ty::ExistentialPredicate<'tcx>>, (self, f, cx) {
617527
display {
618528
// Generate the main trait ref, including associated types.
619-
620-
// Use a type that can't appear in defaults of type parameters.
621-
let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
622529
let mut first = true;
623530

624531
if let Some(principal) = self.principal() {
625-
let principal = principal.with_self_ty(cx.tcx, dummy_self);
626-
cx.parameterized(
627-
f,
628-
principal.def_id,
629-
principal.substs,
630-
self.projection_bounds(),
631-
)?;
532+
let mut resugared_principal = false;
533+
534+
// Special-case `Fn(...) -> ...` and resugar it.
535+
if !cx.is_verbose && cx.tcx.lang_items().fn_trait_kind(principal.def_id).is_some() {
536+
if let Tuple(ref args) = principal.substs.type_at(0).sty {
537+
let mut projections = self.projection_bounds();
538+
if let (Some(proj), None) = (projections.next(), projections.next()) {
539+
print!(f, cx, write("{}", cx.tcx.item_path_str(principal.def_id)))?;
540+
cx.fn_sig(f, args, false, proj.ty)?;
541+
resugared_principal = true;
542+
}
543+
}
544+
}
545+
546+
if !resugared_principal {
547+
// Use a type that can't appear in defaults of type parameters.
548+
let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
549+
let principal = principal.with_self_ty(cx.tcx, dummy_self);
550+
cx.parameterized(
551+
f,
552+
principal.def_id,
553+
principal.substs,
554+
self.projection_bounds(),
555+
)?;
556+
}
632557
first = false;
633558
}
634559

@@ -1393,12 +1318,7 @@ define_print! {
13931318
define_print! {
13941319
('tcx) ty::ProjectionTy<'tcx>, (self, f, cx) {
13951320
display {
1396-
// FIXME(tschottdorf): use something like
1397-
// parameterized(f, self.substs, self.item_def_id, &[])
1398-
// (which currently ICEs).
1399-
let trait_ref = self.trait_ref(cx.tcx);
1400-
let item_name = cx.tcx.associated_item(self.item_def_id).ident;
1401-
print!(f, cx, print_debug(trait_ref), write("::{}", item_name))
1321+
cx.parameterized(f, self.item_def_id, self.substs, iter::empty())
14021322
}
14031323
}
14041324
}

0 commit comments

Comments
 (0)