Skip to content

Commit

Permalink
Auto merge of #58140 - eddyb:advent-of-print, r=nikomatsakis
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bors committed Mar 15, 2019
2 parents 16e7e05 + dbf19c3 commit ad8a3eb
Show file tree
Hide file tree
Showing 143 changed files with 3,407 additions and 2,933 deletions.
1 change: 0 additions & 1 deletion src/bootstrap/mk/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ check:
$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
check-aux:
$(Q)$(BOOTSTRAP) test \
src/test/pretty \
src/test/run-pass/pretty \
src/test/run-fail/pretty \
src/test/run-pass-valgrind/pretty \
Expand Down
12 changes: 3 additions & 9 deletions src/bootstrap/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,12 +897,10 @@ host_test!(Rustdoc {
suite: "rustdoc"
});

test!(Pretty {
host_test!(Pretty {
path: "src/test/pretty",
mode: "pretty",
suite: "pretty",
default: false,
host: true
suite: "pretty"
});
test!(RunPassPretty {
path: "src/test/run-pass/pretty",
Expand Down Expand Up @@ -993,11 +991,7 @@ impl Step for Compiletest {
});
}

if suite.ends_with("fulldeps") ||
// FIXME: Does pretty need librustc compiled? Note that there are
// fulldeps test suites with mode = pretty as well.
mode == "pretty"
{
if suite.ends_with("fulldeps") {
builder.ensure(compile::Rustc { compiler, target });
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for DefId {
}

fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String {
tcx.item_path_str(*self)
tcx.def_path_str(*self)
}
}

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

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

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/hir/def_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ impl DefId {
if self.is_local() && self.index == CRATE_DEF_INDEX {
format!("top-level module")
} else {
format!("module `{}`", tcx.item_path_str(*self))
format!("module `{}`", tcx.def_path_str(*self))
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -679,13 +679,13 @@ impl DefPathData {
return name
}
// note that this does not show up in user printouts
CrateRoot => "{{root}}",
CrateRoot => "{{crate}}",
Impl => "{{impl}}",
Misc => "{{?}}",
Misc => "{{misc}}",
ClosureExpr => "{{closure}}",
StructCtor => "{{constructor}}",
AnonConst => "{{constant}}",
ImplTrait => "{{impl-Trait}}",
ImplTrait => "{{opaque}}",
};

Symbol::intern(s).as_interned_str()
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,8 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String {
// the user-friendly path, otherwise fall back to stringifying DefPath.
crate::ty::tls::with_opt(|tcx| {
if let Some(tcx) = tcx {
tcx.node_path_str(id)
let def_id = map.local_def_id(id);
tcx.def_path_str(def_id)
} else if let Some(path) = map.def_path_from_id(id) {
path.data.into_iter().map(|elem| {
elem.data.to_string()
Expand Down
129 changes: 114 additions & 15 deletions src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.hir().span_by_hir_id(node),
),
_ => (
format!("the lifetime {} as defined on", fr.bound_region),
format!("the lifetime {} as defined on", region),
cm.def_span(self.hir().span_by_hir_id(node)),
),
},
Expand Down Expand Up @@ -444,17 +444,109 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
terr: &TypeError<'tcx>,
sp: Span,
) {
use hir::def_id::CrateNum;
use hir::map::DisambiguatedDefPathData;
use ty::print::Printer;
use ty::subst::Kind;

struct AbsolutePathPrinter<'a, 'gcx, 'tcx> {
tcx: TyCtxt<'a, 'gcx, 'tcx>,
}

struct NonTrivialPath;

impl<'gcx, 'tcx> Printer<'gcx, 'tcx> for AbsolutePathPrinter<'_, 'gcx, 'tcx> {
type Error = NonTrivialPath;

type Path = Vec<String>;
type Region = !;
type Type = !;
type DynExistential = !;

fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
self.tcx
}

fn print_region(
self,
_region: ty::Region<'_>,
) -> Result<Self::Region, Self::Error> {
Err(NonTrivialPath)
}

fn print_type(
self,
_ty: Ty<'tcx>,
) -> Result<Self::Type, Self::Error> {
Err(NonTrivialPath)
}

fn print_dyn_existential(
self,
_predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
) -> Result<Self::DynExistential, Self::Error> {
Err(NonTrivialPath)
}

fn path_crate(
self,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
}
fn path_qualified(
self,
_self_ty: Ty<'tcx>,
_trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
Err(NonTrivialPath)
}

fn path_append_impl(
self,
_print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
_disambiguated_data: &DisambiguatedDefPathData,
_self_ty: Ty<'tcx>,
_trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
Err(NonTrivialPath)
}
fn path_append(
self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
disambiguated_data: &DisambiguatedDefPathData,
) -> Result<Self::Path, Self::Error> {
let mut path = print_prefix(self)?;
path.push(disambiguated_data.data.as_interned_str().to_string());
Ok(path)
}
fn path_generic_args(
self,
print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
_args: &[Kind<'tcx>],
) -> Result<Self::Path, Self::Error> {
print_prefix(self)
}
}

let report_path_match = |err: &mut DiagnosticBuilder<'_>, did1: DefId, did2: DefId| {
// Only external crates, if either is from a local
// module we could have false positives
if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
let exp_path = self.tcx.item_path_str(did1);
let found_path = self.tcx.item_path_str(did2);
let exp_abs_path = self.tcx.absolute_item_path_str(did1);
let found_abs_path = self.tcx.absolute_item_path_str(did2);
let abs_path = |def_id| {
AbsolutePathPrinter { tcx: self.tcx }
.print_def_path(def_id, &[])
};

// We compare strings because DefPath can be different
// for imported and non-imported crates
if exp_path == found_path || exp_abs_path == found_abs_path {
let same_path = || -> Result<_, NonTrivialPath> {
Ok(
self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2) ||
abs_path(did1)? == abs_path(did2)?
)
};
if same_path().unwrap_or(false) {
let crate_name = self.tcx.crate_name(did1.krate);
err.span_note(
sp,
Expand Down Expand Up @@ -658,7 +750,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
return Some(());
}
if let &ty::Adt(def, _) = &ta.sty {
let path_ = self.tcx.item_path_str(def.did.clone());
let path_ = self.tcx.def_path_str(def.did.clone());
if path_ == other_path {
self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
return Some(());
Expand All @@ -683,7 +775,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

/// For generic types with parameters with defaults, remove the parameters corresponding to
/// the defaults. This repeats a lot of the logic found in `PrintContext::parameterized`.
/// the defaults. This repeats a lot of the logic found in `ty::print::pretty`.
fn strip_generic_default_params(
&self,
def_id: DefId,
Expand Down Expand Up @@ -742,11 +834,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
mutbl: hir::Mutability,
s: &mut DiagnosticStyledString,
) {
let r = &r.to_string();
let mut r = r.to_string();
if r == "'_" {
r.clear();
} else {
r.push(' ');
}
s.push_highlighted(format!(
"&{}{}{}",
"&{}{}",
r,
if r == "" { "" } else { " " },
if mutbl == hir::MutMutable { "mut " } else { "" }
));
s.push_normal(ty.to_string());
Expand All @@ -757,8 +853,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);
let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2);
let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
let path1 = self.tcx.item_path_str(def1.did.clone());
let path2 = self.tcx.item_path_str(def2.did.clone());
let path1 = self.tcx.def_path_str(def1.did.clone());
let path2 = self.tcx.def_path_str(def2.did.clone());
if def1.did == def2.did {
// Easy case. Replace same types with `_` to shorten the output and highlight
// the differing ones.
Expand Down Expand Up @@ -1013,7 +1109,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
if exp_is_struct && &exp_found.expected == ret_ty.skip_binder() {
let message = format!(
"did you mean `{}(/* fields */)`?",
self.tcx.item_path_str(def_id)
self.tcx.def_path_str(def_id)
);
diag.span_label(span, message);
}
Expand Down Expand Up @@ -1425,7 +1521,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
var_origin: RegionVariableOrigin,
) -> DiagnosticBuilder<'tcx> {
let br_string = |br: ty::BoundRegion| {
let mut s = br.to_string();
let mut s = match br {
ty::BrNamed(_, name) => name.to_string(),
_ => String::new(),
};
if !s.is_empty() {
s.push_str(" ");
}
Expand Down
24 changes: 17 additions & 7 deletions src/librustc/infer/error_reporting/need_type_info.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::hir::def::Namespace;
use crate::hir::{self, Local, Pat, Body, HirId};
use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
use crate::infer::InferCtxt;
use crate::infer::type_variable::TypeVariableOrigin;
use crate::ty::{self, Ty, Infer, TyVar};
use crate::ty::print::Print;
use syntax::source_map::CompilerDesugaringKind;
use syntax_pos::Span;
use errors::DiagnosticBuilder;
Expand Down Expand Up @@ -64,18 +66,26 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {


impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String {
pub fn extract_type_name(
&self,
ty: &'a Ty<'tcx>,
highlight: Option<ty::print::RegionHighlightMode>,
) -> String {
if let ty::Infer(ty::TyVar(ty_vid)) = (*ty).sty {
let ty_vars = self.type_variables.borrow();
if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
*ty_vars.var_origin(ty_vid) {
name.to_string()
} else {
ty.to_string()
return name.to_string();
}
} else {
ty.to_string()
}

let mut s = String::new();
let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
if let Some(highlight) = highlight {
printer.region_highlight_mode = highlight;
}
let _ = ty.print(printer);
s
}

pub fn need_type_info_err(&self,
Expand All @@ -84,7 +94,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
ty: Ty<'tcx>)
-> DiagnosticBuilder<'gcx> {
let ty = self.resolve_type_vars_if_possible(&ty);
let name = self.extract_type_name(&ty);
let name = self.extract_type_name(&ty, None);

let mut err_span = span;
let mut labels = vec![(
Expand Down
Loading

0 comments on commit ad8a3eb

Please sign in to comment.