Skip to content

Commit ad8a3eb

Browse files
committed
Auto merge of #58140 - eddyb:advent-of-print, r=nikomatsakis
Refactor ppaux out of existence. A long-time coming, this PR reorganizes and rewrites the pretty-printing architecture of rustc, specifically the parts that involve the typesystem (which used to be in `rustc::util::ppaux`). *Note: these commits used to be in #57967 before being split off.* The new API (i.e. the `Printer` and `PrettyPrint` traits) is in `rustc::ty::print`. Design points, roughly: * using associated types in `Printer` to allow building e.g. an AST, not just printing as a side-effect * several overloading points for implementers of `PrettyPrinter`, e.g. how `<...>` is printed * for `fmt::Display` impls, the value to print is lifted to the `ty::tls` `tcx`, and everything after that stays within the `ty::print` API, which requires `'tcx` to match between values and the printer's `tcx`, without going through `fmt::Display` again Most of the behavior is unchanged, except for a few details, which should be clear from the test changes. r? @nikomatsakis Fixes #55464
2 parents 16e7e05 + dbf19c3 commit ad8a3eb

File tree

143 files changed

+3407
-2933
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+3407
-2933
lines changed

src/bootstrap/mk/Makefile.in

-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ check:
4848
$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
4949
check-aux:
5050
$(Q)$(BOOTSTRAP) test \
51-
src/test/pretty \
5251
src/test/run-pass/pretty \
5352
src/test/run-fail/pretty \
5453
src/test/run-pass-valgrind/pretty \

src/bootstrap/test.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -897,12 +897,10 @@ host_test!(Rustdoc {
897897
suite: "rustdoc"
898898
});
899899

900-
test!(Pretty {
900+
host_test!(Pretty {
901901
path: "src/test/pretty",
902902
mode: "pretty",
903-
suite: "pretty",
904-
default: false,
905-
host: true
903+
suite: "pretty"
906904
});
907905
test!(RunPassPretty {
908906
path: "src/test/run-pass/pretty",
@@ -993,11 +991,7 @@ impl Step for Compiletest {
993991
});
994992
}
995993

996-
if suite.ends_with("fulldeps") ||
997-
// FIXME: Does pretty need librustc compiled? Note that there are
998-
// fulldeps test suites with mode = pretty as well.
999-
mode == "pretty"
1000-
{
994+
if suite.ends_with("fulldeps") {
1001995
builder.ensure(compile::Rustc { compiler, target });
1002996
}
1003997

src/librustc/dep_graph/dep_node.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for DefId {
724724
}
725725

726726
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
727-
tcx.item_path_str(*self)
727+
tcx.def_path_str(*self)
728728
}
729729
}
730730

@@ -736,7 +736,7 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for DefIndex {
736736
}
737737

738738
fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
739-
tcx.item_path_str(DefId::local(*self))
739+
tcx.def_path_str(DefId::local(*self))
740740
}
741741
}
742742

src/librustc/hir/def_id.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ impl DefId {
249249
if self.is_local() && self.index == CRATE_DEF_INDEX {
250250
format!("top-level module")
251251
} else {
252-
format!("module `{}`", tcx.item_path_str(*self))
252+
format!("module `{}`", tcx.def_path_str(*self))
253253
}
254254
}
255255
}

src/librustc/hir/map/definitions.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -679,13 +679,13 @@ impl DefPathData {
679679
return name
680680
}
681681
// note that this does not show up in user printouts
682-
CrateRoot => "{{root}}",
682+
CrateRoot => "{{crate}}",
683683
Impl => "{{impl}}",
684-
Misc => "{{?}}",
684+
Misc => "{{misc}}",
685685
ClosureExpr => "{{closure}}",
686686
StructCtor => "{{constructor}}",
687687
AnonConst => "{{constant}}",
688-
ImplTrait => "{{impl-Trait}}",
688+
ImplTrait => "{{opaque}}",
689689
};
690690

691691
Symbol::intern(s).as_interned_str()

src/librustc/hir/map/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1351,7 +1351,8 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String {
13511351
// the user-friendly path, otherwise fall back to stringifying DefPath.
13521352
crate::ty::tls::with_opt(|tcx| {
13531353
if let Some(tcx) = tcx {
1354-
tcx.node_path_str(id)
1354+
let def_id = map.local_def_id(id);
1355+
tcx.def_path_str(def_id)
13551356
} else if let Some(path) = map.def_path_from_id(id) {
13561357
path.data.into_iter().map(|elem| {
13571358
elem.data.to_string()

src/librustc/infer/error_reporting/mod.rs

+114-15
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
223223
self.hir().span_by_hir_id(node),
224224
),
225225
_ => (
226-
format!("the lifetime {} as defined on", fr.bound_region),
226+
format!("the lifetime {} as defined on", region),
227227
cm.def_span(self.hir().span_by_hir_id(node)),
228228
),
229229
},
@@ -444,17 +444,109 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
444444
terr: &TypeError<'tcx>,
445445
sp: Span,
446446
) {
447+
use hir::def_id::CrateNum;
448+
use hir::map::DisambiguatedDefPathData;
449+
use ty::print::Printer;
450+
use ty::subst::Kind;
451+
452+
struct AbsolutePathPrinter<'a, 'gcx, 'tcx> {
453+
tcx: TyCtxt<'a, 'gcx, 'tcx>,
454+
}
455+
456+
struct NonTrivialPath;
457+
458+
impl<'gcx, 'tcx> Printer<'gcx, 'tcx> for AbsolutePathPrinter<'_, 'gcx, 'tcx> {
459+
type Error = NonTrivialPath;
460+
461+
type Path = Vec<String>;
462+
type Region = !;
463+
type Type = !;
464+
type DynExistential = !;
465+
466+
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
467+
self.tcx
468+
}
469+
470+
fn print_region(
471+
self,
472+
_region: ty::Region<'_>,
473+
) -> Result<Self::Region, Self::Error> {
474+
Err(NonTrivialPath)
475+
}
476+
477+
fn print_type(
478+
self,
479+
_ty: Ty<'tcx>,
480+
) -> Result<Self::Type, Self::Error> {
481+
Err(NonTrivialPath)
482+
}
483+
484+
fn print_dyn_existential(
485+
self,
486+
_predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
487+
) -> Result<Self::DynExistential, Self::Error> {
488+
Err(NonTrivialPath)
489+
}
490+
491+
fn path_crate(
492+
self,
493+
cnum: CrateNum,
494+
) -> Result<Self::Path, Self::Error> {
495+
Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
496+
}
497+
fn path_qualified(
498+
self,
499+
_self_ty: Ty<'tcx>,
500+
_trait_ref: Option<ty::TraitRef<'tcx>>,
501+
) -> Result<Self::Path, Self::Error> {
502+
Err(NonTrivialPath)
503+
}
504+
505+
fn path_append_impl(
506+
self,
507+
_print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
508+
_disambiguated_data: &DisambiguatedDefPathData,
509+
_self_ty: Ty<'tcx>,
510+
_trait_ref: Option<ty::TraitRef<'tcx>>,
511+
) -> Result<Self::Path, Self::Error> {
512+
Err(NonTrivialPath)
513+
}
514+
fn path_append(
515+
self,
516+
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
517+
disambiguated_data: &DisambiguatedDefPathData,
518+
) -> Result<Self::Path, Self::Error> {
519+
let mut path = print_prefix(self)?;
520+
path.push(disambiguated_data.data.as_interned_str().to_string());
521+
Ok(path)
522+
}
523+
fn path_generic_args(
524+
self,
525+
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
526+
_args: &[Kind<'tcx>],
527+
) -> Result<Self::Path, Self::Error> {
528+
print_prefix(self)
529+
}
530+
}
531+
447532
let report_path_match = |err: &mut DiagnosticBuilder<'_>, did1: DefId, did2: DefId| {
448533
// Only external crates, if either is from a local
449534
// module we could have false positives
450535
if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
451-
let exp_path = self.tcx.item_path_str(did1);
452-
let found_path = self.tcx.item_path_str(did2);
453-
let exp_abs_path = self.tcx.absolute_item_path_str(did1);
454-
let found_abs_path = self.tcx.absolute_item_path_str(did2);
536+
let abs_path = |def_id| {
537+
AbsolutePathPrinter { tcx: self.tcx }
538+
.print_def_path(def_id, &[])
539+
};
540+
455541
// We compare strings because DefPath can be different
456542
// for imported and non-imported crates
457-
if exp_path == found_path || exp_abs_path == found_abs_path {
543+
let same_path = || -> Result<_, NonTrivialPath> {
544+
Ok(
545+
self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2) ||
546+
abs_path(did1)? == abs_path(did2)?
547+
)
548+
};
549+
if same_path().unwrap_or(false) {
458550
let crate_name = self.tcx.crate_name(did1.krate);
459551
err.span_note(
460552
sp,
@@ -658,7 +750,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
658750
return Some(());
659751
}
660752
if let &ty::Adt(def, _) = &ta.sty {
661-
let path_ = self.tcx.item_path_str(def.did.clone());
753+
let path_ = self.tcx.def_path_str(def.did.clone());
662754
if path_ == other_path {
663755
self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
664756
return Some(());
@@ -683,7 +775,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
683775
}
684776

685777
/// For generic types with parameters with defaults, remove the parameters corresponding to
686-
/// the defaults. This repeats a lot of the logic found in `PrintContext::parameterized`.
778+
/// the defaults. This repeats a lot of the logic found in `ty::print::pretty`.
687779
fn strip_generic_default_params(
688780
&self,
689781
def_id: DefId,
@@ -742,11 +834,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
742834
mutbl: hir::Mutability,
743835
s: &mut DiagnosticStyledString,
744836
) {
745-
let r = &r.to_string();
837+
let mut r = r.to_string();
838+
if r == "'_" {
839+
r.clear();
840+
} else {
841+
r.push(' ');
842+
}
746843
s.push_highlighted(format!(
747-
"&{}{}{}",
844+
"&{}{}",
748845
r,
749-
if r == "" { "" } else { " " },
750846
if mutbl == hir::MutMutable { "mut " } else { "" }
751847
));
752848
s.push_normal(ty.to_string());
@@ -757,8 +853,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
757853
let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);
758854
let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2);
759855
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
760-
let path1 = self.tcx.item_path_str(def1.did.clone());
761-
let path2 = self.tcx.item_path_str(def2.did.clone());
856+
let path1 = self.tcx.def_path_str(def1.did.clone());
857+
let path2 = self.tcx.def_path_str(def2.did.clone());
762858
if def1.did == def2.did {
763859
// Easy case. Replace same types with `_` to shorten the output and highlight
764860
// the differing ones.
@@ -1013,7 +1109,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10131109
if exp_is_struct && &exp_found.expected == ret_ty.skip_binder() {
10141110
let message = format!(
10151111
"did you mean `{}(/* fields */)`?",
1016-
self.tcx.item_path_str(def_id)
1112+
self.tcx.def_path_str(def_id)
10171113
);
10181114
diag.span_label(span, message);
10191115
}
@@ -1425,7 +1521,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
14251521
var_origin: RegionVariableOrigin,
14261522
) -> DiagnosticBuilder<'tcx> {
14271523
let br_string = |br: ty::BoundRegion| {
1428-
let mut s = br.to_string();
1524+
let mut s = match br {
1525+
ty::BrNamed(_, name) => name.to_string(),
1526+
_ => String::new(),
1527+
};
14291528
if !s.is_empty() {
14301529
s.push_str(" ");
14311530
}

src/librustc/infer/error_reporting/need_type_info.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
use crate::hir::def::Namespace;
12
use crate::hir::{self, Local, Pat, Body, HirId};
23
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
34
use crate::infer::InferCtxt;
45
use crate::infer::type_variable::TypeVariableOrigin;
56
use crate::ty::{self, Ty, Infer, TyVar};
7+
use crate::ty::print::Print;
68
use syntax::source_map::CompilerDesugaringKind;
79
use syntax_pos::Span;
810
use errors::DiagnosticBuilder;
@@ -64,18 +66,26 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
6466

6567

6668
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
67-
pub fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
69+
pub fn extract_type_name(
70+
&self,
71+
ty: &'a Ty<'tcx>,
72+
highlight: Option<ty::print::RegionHighlightMode>,
73+
) -> String {
6874
if let ty::Infer(ty::TyVar(ty_vid)) = (*ty).sty {
6975
let ty_vars = self.type_variables.borrow();
7076
if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
7177
*ty_vars.var_origin(ty_vid) {
72-
name.to_string()
73-
} else {
74-
ty.to_string()
78+
return name.to_string();
7579
}
76-
} else {
77-
ty.to_string()
7880
}
81+
82+
let mut s = String::new();
83+
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
84+
if let Some(highlight) = highlight {
85+
printer.region_highlight_mode = highlight;
86+
}
87+
let _ = ty.print(printer);
88+
s
7989
}
8090

8191
pub fn need_type_info_err(&self,
@@ -84,7 +94,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
8494
ty: Ty<'tcx>)
8595
-> DiagnosticBuilder<'gcx> {
8696
let ty = self.resolve_type_vars_if_possible(&ty);
87-
let name = self.extract_type_name(&ty);
97+
let name = self.extract_type_name(&ty, None);
8898

8999
let mut err_span = span;
90100
let mut labels = vec![(

0 commit comments

Comments
 (0)