rustc: uniformize ty::print's error handling by requiring Result.

This commit is contained in:
Eduard-Mihai Burtescu 2019-01-09 16:30:10 +02:00
parent 972af5e808
commit 5616ca857d
6 changed files with 114 additions and 85 deletions

View File

@ -454,9 +454,14 @@ fn check_and_note_conflicting_crates(
struct NonTrivialPath;
impl Printer for AbsolutePathPrinter {
type Path = Result<Vec<String>, NonTrivialPath>;
type Error = NonTrivialPath;
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
type Path = Vec<String>;
fn path_crate(
self: &mut PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
}
fn path_qualified<'tcx>(
@ -465,15 +470,14 @@ fn path_qualified<'tcx>(
_self_ty: Ty<'tcx>,
_trait_ref: Option<ty::TraitRef<'tcx>>,
_ns: Namespace,
) -> Self::Path {
) -> Result<Self::Path, Self::Error> {
Err(NonTrivialPath)
}
fn path_append(
self: &mut PrintCx<'_, '_, '_, Self>,
path: Self::Path,
mut path: Self::Path,
text: &str,
) -> Self::Path {
let mut path = path?;
) -> Result<Self::Path, Self::Error> {
path.push(text.to_string());
Ok(path)
}
@ -484,8 +488,8 @@ fn path_generic_args<'tcx>(
_substs: SubstsRef<'tcx>,
_ns: Namespace,
_projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Self::Path {
path
) -> Result<Self::Path, Self::Error> {
Ok(path)
}
}

View File

@ -109,16 +109,20 @@ pub(crate) fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<T>
pub trait Print<'tcx, P> {
type Output;
type Error;
fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output;
fn print_display(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output {
fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error>;
fn print_display(
&self,
cx: &mut PrintCx<'_, '_, 'tcx, P>,
) -> Result<Self::Output, Self::Error> {
let old_debug = cx.is_debug;
cx.is_debug = false;
let result = self.print(cx);
cx.is_debug = old_debug;
result
}
fn print_debug(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output {
fn print_debug(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
let old_debug = cx.is_debug;
cx.is_debug = true;
let result = self.print(cx);
@ -128,19 +132,19 @@ fn print_debug(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output {
}
pub trait Printer: Sized {
type Error;
type Path;
#[must_use]
fn print_def_path(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
def_id: DefId,
substs: Option<SubstsRef<'tcx>>,
ns: Namespace,
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Self::Path {
) -> Result<Self::Path, Self::Error> {
self.default_print_def_path(def_id, substs, ns, projections)
}
#[must_use]
fn print_impl_path(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
impl_def_id: DefId,
@ -148,27 +152,26 @@ fn print_impl_path(
ns: Namespace,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Self::Path {
) -> Result<Self::Path, Self::Error> {
self.default_print_impl_path(impl_def_id, substs, ns, self_ty, trait_ref)
}
#[must_use]
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path;
#[must_use]
fn path_crate(
self: &mut PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error>;
fn path_qualified(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
impl_prefix: Option<Self::Path>,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
ns: Namespace,
) -> Self::Path;
#[must_use]
) -> Result<Self::Path, Self::Error>;
fn path_append(
self: &mut PrintCx<'_, '_, '_, Self>,
path: Self::Path,
text: &str,
) -> Self::Path;
#[must_use]
) -> Result<Self::Path, Self::Error>;
fn path_generic_args(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
path: Self::Path,
@ -176,7 +179,7 @@ fn path_generic_args(
substs: SubstsRef<'tcx>,
ns: Namespace,
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Self::Path;
) -> Result<Self::Path, Self::Error>;
}
#[must_use]
@ -185,7 +188,7 @@ pub struct PrettyPath {
}
/// Trait for printers that pretty-print using `fmt::Write` to the printer.
pub trait PrettyPrinter: Printer<Path = Result<PrettyPath, fmt::Error>> + fmt::Write {}
pub trait PrettyPrinter: Printer<Error = fmt::Error, Path = PrettyPath> + fmt::Write {}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
// HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always
@ -225,7 +228,7 @@ pub fn default_print_def_path(
substs: Option<SubstsRef<'tcx>>,
ns: Namespace,
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> P::Path {
) -> Result<P::Path, P::Error> {
debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns);
let key = self.tcx.def_key(def_id);
debug!("default_print_def_path: key={:?}", key);
@ -263,12 +266,12 @@ pub fn default_print_def_path(
parent_generics.has_self && parent_generics.parent_count == 0;
if let (Some(substs), true) = (substs, parent_has_own_self) {
let trait_ref = ty::TraitRef::new(parent_def_id, substs);
self.path_qualified(None, trait_ref.self_ty(), Some(trait_ref), ns)
self.path_qualified(None, trait_ref.self_ty(), Some(trait_ref), ns)?
} else {
self.print_def_path(parent_def_id, substs, ns, iter::empty())
self.print_def_path(parent_def_id, substs, ns, iter::empty())?
}
} else {
self.print_def_path(parent_def_id, None, ns, iter::empty())
self.print_def_path(parent_def_id, None, ns, iter::empty())?
};
let path = match key.disambiguated_data.data {
// Skip `::{{constructor}}` on tuple/unit structs.
@ -278,7 +281,7 @@ pub fn default_print_def_path(
self.path_append(
path,
&key.disambiguated_data.data.as_interned_str().as_str(),
)
)?
}
};
@ -287,7 +290,7 @@ pub fn default_print_def_path(
let params = &generics.params[has_own_self as usize..];
self.path_generic_args(path, params, substs, ns, projections)
} else {
path
Ok(path)
}
}
}
@ -300,7 +303,7 @@ fn default_print_impl_path(
ns: Namespace,
self_ty: Ty<'tcx>,
impl_trait_ref: Option<ty::TraitRef<'tcx>>,
) -> P::Path {
) -> Result<P::Path, P::Error> {
debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}",
impl_def_id, self_ty, impl_trait_ref);
@ -323,7 +326,7 @@ fn default_print_impl_path(
// If the impl is not co-located with either self-type or
// trait-type, then fallback to a format that identifies
// the module more clearly.
Some(self.print_def_path(parent_def_id, None, ns, iter::empty()))
Some(self.print_def_path(parent_def_id, None, ns, iter::empty())?)
} else {
// Otherwise, try to give a good form that would be valid language
// syntax. Preferably using associated item notation.
@ -390,7 +393,7 @@ impl<P: PrettyPrinter> PrintCx<'a, 'gcx, 'tcx, P> {
/// If possible, this returns a global path resolving to `def_id` that is visible
/// from at least one local module and returns true. If the crate defining `def_id` is
/// declared with an `extern crate`, the path is guaranteed to use the `extern crate`.
fn try_print_visible_def_path(&mut self, def_id: DefId) -> Option<P::Path> {
fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result<Option<P::Path>, P::Error> {
debug!("try_print_visible_def_path: def_id={:?}", def_id);
// If `def_id` is a direct or injected extern crate, return the
@ -399,7 +402,7 @@ fn try_print_visible_def_path(&mut self, def_id: DefId) -> Option<P::Path> {
let cnum = def_id.krate;
if cnum == LOCAL_CRATE {
return Some(self.path_crate(cnum));
return Ok(Some(self.path_crate(cnum)?));
}
// In local mode, when we encounter a crate other than
@ -421,21 +424,21 @@ fn try_print_visible_def_path(&mut self, def_id: DefId) -> Option<P::Path> {
}) => {
debug!("try_print_visible_def_path: def_id={:?}", def_id);
let path = if !span.is_dummy() {
self.print_def_path(def_id, None, Namespace::TypeNS, iter::empty())
self.print_def_path(def_id, None, Namespace::TypeNS, iter::empty())?
} else {
self.path_crate(cnum)
self.path_crate(cnum)?
};
return Some(path);
return Ok(Some(path));
}
None => {
return Some(self.path_crate(cnum));
return Ok(Some(self.path_crate(cnum)?));
}
_ => {},
}
}
if def_id.is_local() {
return None;
return Ok(None);
}
let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE);
@ -453,8 +456,14 @@ fn try_print_visible_def_path(&mut self, def_id: DefId) -> Option<P::Path> {
cur_def_key = self.tcx.def_key(parent);
}
let visible_parent = visible_parent_map.get(&def_id).cloned()?;
let path = self.try_print_visible_def_path(visible_parent)?;
let visible_parent = match visible_parent_map.get(&def_id).cloned() {
Some(parent) => parent,
None => return Ok(None),
};
let path = match self.try_print_visible_def_path(visible_parent)? {
Some(path) => path,
None => return Ok(None),
};
let actual_parent = self.tcx.parent(def_id);
let data = cur_def_key.disambiguated_data.data;
@ -515,7 +524,7 @@ fn try_print_visible_def_path(&mut self, def_id: DefId) -> Option<P::Path> {
},
};
debug!("try_print_visible_def_path: symbol={:?}", symbol);
Some(self.path_append(path, &symbol))
Ok(Some(self.path_append(path, &symbol)?))
}
pub fn pretty_path_qualified(
@ -524,7 +533,7 @@ pub fn pretty_path_qualified(
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
ns: Namespace,
) -> P::Path {
) -> Result<P::Path, P::Error> {
if let Some(prefix) = impl_prefix {
// HACK(eddyb) going through `path_append` means symbol name
// computation gets to handle its equivalent of `::` correctly.
@ -582,9 +591,7 @@ pub fn pretty_path_generic_args(
substs: SubstsRef<'tcx>,
ns: Namespace,
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> P::Path {
let path = path?;
) -> Result<P::Path, P::Error> {
let mut empty = true;
let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
if empty {
@ -671,7 +678,9 @@ fn write_str(&mut self, s: &str) -> fmt::Result {
}
impl<F: fmt::Write> Printer for FmtPrinter<F> {
type Path = Result<PrettyPath, fmt::Error>;
type Error = fmt::Error;
type Path = PrettyPath;
fn print_def_path(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
@ -679,20 +688,20 @@ fn print_def_path(
substs: Option<SubstsRef<'tcx>>,
ns: Namespace,
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Self::Path {
) -> Result<Self::Path, Self::Error> {
// FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key`
// both here and in `default_print_def_path`.
let generics = substs.map(|_| self.tcx.generics_of(def_id));
if generics.as_ref().and_then(|g| g.parent).is_none() {
if let Some(path) = self.try_print_visible_def_path(def_id) {
if let Some(path) = self.try_print_visible_def_path(def_id)? {
let path = if let (Some(generics), Some(substs)) = (generics, substs) {
let has_own_self = generics.has_self && generics.parent_count == 0;
let params = &generics.params[has_own_self as usize..];
self.path_generic_args(path, params, substs, ns, projections)
self.path_generic_args(path, params, substs, ns, projections)?
} else {
path
};
return path;
return Ok(path);
}
}
@ -712,7 +721,7 @@ fn print_def_path(
// pretty printing some span information. This should
// only occur very early in the compiler pipeline.
let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
let path = self.print_def_path(parent_def_id, None, ns, iter::empty());
let path = self.print_def_path(parent_def_id, None, ns, iter::empty())?;
let span = self.tcx.def_span(def_id);
return self.path_append(path, &format!("<impl at {:?}>", span));
}
@ -721,7 +730,10 @@ fn print_def_path(
self.default_print_def_path(def_id, substs, ns, projections)
}
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
fn path_crate(
self: &mut PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
if cnum == LOCAL_CRATE {
if self.tcx.sess.rust_2018() {
// We add the `crate::` keyword on Rust 2018, only when desired.
@ -742,16 +754,14 @@ fn path_qualified(
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
ns: Namespace,
) -> Self::Path {
) -> Result<Self::Path, Self::Error> {
self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns)
}
fn path_append(
self: &mut PrintCx<'_, '_, '_, Self>,
path: Self::Path,
text: &str,
) -> Self::Path {
let path = path?;
) -> Result<Self::Path, Self::Error> {
// FIXME(eddyb) this shouldn't happen, but is currently
// the case for `extern { ... }` "foreign modules".
if text.is_empty() {
@ -771,7 +781,7 @@ fn path_generic_args(
substs: SubstsRef<'tcx>,
ns: Namespace,
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Self::Path {
) -> Result<Self::Path, Self::Error> {
self.pretty_path_generic_args(path, params, substs, ns, projections)
}
}

View File

@ -193,7 +193,8 @@ impl fmt::Debug for $target {
macro_rules! gen_print_impl {
( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target {
type Output = fmt::Result;
type Output = ();
type Error = fmt::Error;
fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result {
define_scoped_cx!($cx);
if $cx.is_debug $dbg
@ -203,7 +204,8 @@ fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result {
};
( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => {
impl<P: PrettyPrinter> Print<'tcx, P> for $target {
type Output = fmt::Result;
type Output = ();
type Error = fmt::Error;
fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result {
define_scoped_cx!($cx);
if $cx.is_debug $dbg
@ -298,8 +300,8 @@ fn fn_sig(
Ok(())
}
fn in_binder<T>(&mut self, value: &ty::Binder<T>) -> fmt::Result
where T: Print<'tcx, P, Output = fmt::Result> + TypeFoldable<'tcx>
fn in_binder<T>(&mut self, value: &ty::Binder<T>) -> Result<T::Output, fmt::Error>
where T: Print<'tcx, P, Error = fmt::Error> + TypeFoldable<'tcx>
{
fn name_by_region_index(index: usize) -> InternedString {
match index {

View File

@ -404,9 +404,14 @@ fn finish(mut self, hash: u64) -> String {
// symbol names should have their own printing machinery.
impl Printer for SymbolPath {
type Path = Result<PrettyPath, fmt::Error>;
type Error = fmt::Error;
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
type Path = PrettyPath;
fn path_crate(
self: &mut PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
self.printer.write_str(&self.tcx.original_crate_name(cnum).as_str())?;
Ok(PrettyPath { empty: false })
}
@ -416,7 +421,7 @@ fn path_qualified(
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
ns: Namespace,
) -> Self::Path {
) -> Result<Self::Path, Self::Error> {
// HACK(eddyb) avoid `keep_within_component` for the cases
// that print without `<...>` around `self_ty`.
match self_ty.sty {
@ -432,14 +437,17 @@ fn path_qualified(
// HACK(eddyb) make sure to finalize the last component of the
// `impl` prefix, to avoid it fusing with the following text.
let impl_prefix = impl_prefix.map(|prefix| {
let mut prefix = self.path_append(prefix, "")?;
let impl_prefix = match impl_prefix {
Some(prefix) => {
let mut prefix = self.path_append(prefix, "")?;
// HACK(eddyb) also avoid an unnecessary `::`.
prefix.empty = true;
// HACK(eddyb) also avoid an unnecessary `::`.
prefix.empty = true;
Ok(prefix)
});
Some(prefix)
}
None => None,
};
let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true);
let r = self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns);
@ -448,11 +456,9 @@ fn path_qualified(
}
fn path_append(
self: &mut PrintCx<'_, '_, '_, Self>,
path: Self::Path,
mut path: Self::Path,
text: &str,
) -> Self::Path {
let mut path = path?;
) -> Result<Self::Path, Self::Error> {
if self.keep_within_component {
// HACK(eddyb) print the path similarly to how `FmtPrinter` prints it.
if !path.empty {
@ -475,7 +481,7 @@ fn path_generic_args(
substs: SubstsRef<'tcx>,
ns: Namespace,
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Self::Path {
) -> Result<Self::Path, Self::Error> {
let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true);
let r = self.pretty_path_generic_args(path, params, substs, ns, projections);
self.printer.keep_within_component = kept_within_component;

View File

@ -4230,10 +4230,15 @@ pub fn get_path_for_type<F>(tcx: TyCtxt<'_, '_, '_>, def_id: DefId, def_ctor: F)
struct AbsolutePathPrinter;
impl Printer for AbsolutePathPrinter {
type Error = !;
type Path = Vec<String>;
fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
vec![self.tcx.original_crate_name(cnum).to_string()]
fn path_crate(
self: &mut PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
}
fn path_qualified(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
@ -4241,7 +4246,7 @@ fn path_qualified(
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
_ns: Namespace,
) -> Self::Path {
) -> Result<Self::Path, Self::Error> {
let mut path = impl_prefix.unwrap_or(vec![]);
// This shouldn't ever be needed, but just in case:
@ -4251,15 +4256,15 @@ fn path_qualified(
path.push(format!("<{}>", self_ty));
}
path
Ok(path)
}
fn path_append(
self: &mut PrintCx<'_, '_, '_, Self>,
mut path: Self::Path,
text: &str,
) -> Self::Path {
) -> Result<Self::Path, Self::Error> {
path.push(text.to_string());
path
Ok(path)
}
fn path_generic_args(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
@ -4268,13 +4273,14 @@ fn path_generic_args(
_substs: SubstsRef<'tcx>,
_ns: Namespace,
_projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Self::Path {
path
) -> Result<Self::Path, Self::Error> {
Ok(path)
}
}
let names = PrintCx::new(tcx, AbsolutePathPrinter)
.print_def_path(def_id, None, Namespace::TypeNS, iter::empty());
.print_def_path(def_id, None, Namespace::TypeNS, iter::empty())
.unwrap();
hir::Path {
span: DUMMY_SP,

View File

@ -18,6 +18,7 @@
#![feature(const_fn)]
#![feature(drain_filter)]
#![feature(inner_deref)]
#![feature(never_type)]
#![recursion_limit="256"]