about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ty/print/pretty.rs103
-rw-r--r--src/librustc_typeck/collect.rs54
2 files changed, 94 insertions, 63 deletions
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index 594550dd967..ee05d57d239 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -49,6 +49,24 @@ macro_rules! define_scoped_cx {
 thread_local! {
     static FORCE_IMPL_FILENAME_LINE: Cell<bool> = Cell::new(false);
     static SHOULD_PREFIX_WITH_CRATE: Cell<bool> = Cell::new(false);
+    static NO_QUERIES: Cell<bool> = Cell::new(false);
+}
+
+/// Avoids running any queries during any prints that occur
+/// during the closure. This may alter the apperance of some
+/// types (e.g. forcing verbose printing for opaque types).
+/// This method is used during some queries (e.g. `predicates_of`
+/// for opaque types), to ensure that any debug printing that
+/// occurs during the query computation does not end up recursively
+/// calling the same query.
+pub fn with_no_queries<F: FnOnce() -> R, R>(f: F) -> R {
+    NO_QUERIES.with(|no_queries| {
+        let old = no_queries.get();
+        no_queries.set(true);
+        let result = f();
+        no_queries.set(old);
+        result
+    })
 }
 
 /// Force us to name impls with just the filename/line number. We
@@ -556,52 +574,61 @@ pub trait PrettyPrinter<'tcx>:
             }
             ty::Opaque(def_id, substs) => {
                 // FIXME(eddyb) print this with `print_def_path`.
-                if self.tcx().sess.verbose() {
+                // We use verbose printing in 'NO_QUERIES' mode, to
+                // avoid needing to call `predicates_of`. This should
+                // only affect certain debug messages (e.g. messages printed
+                // from `rustc::ty` during the computation of `tcx.predicates_of`),
+                // and should have no effect on any compiler output.
+                if self.tcx().sess.verbose() || NO_QUERIES.with(|q| q.get())  {
                     p!(write("Opaque({:?}, {:?})", def_id, substs));
                     return Ok(self);
                 }
 
-                let def_key = self.tcx().def_key(def_id);
-                if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
-                    p!(write("{}", name));
-                    let mut substs = substs.iter();
-                    // FIXME(eddyb) print this with `print_def_path`.
-                    if let Some(first) = substs.next() {
-                        p!(write("::<"));
-                        p!(print(first));
-                        for subst in substs {
-                            p!(write(", "), print(subst));
+                return Ok(with_no_queries(|| {
+
+                    let def_key = self.tcx().def_key(def_id);
+                    if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
+                        p!(write("{}", name));
+                        let mut substs = substs.iter();
+                        // FIXME(eddyb) print this with `print_def_path`.
+                        if let Some(first) = substs.next() {
+                            p!(write("::<"));
+                            p!(print(first));
+                            for subst in substs {
+                                p!(write(", "), print(subst));
+                            }
+                            p!(write(">"));
                         }
-                        p!(write(">"));
+                        return Ok(self);
                     }
-                    return Ok(self);
-                }
-                // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
-                // by looking up the projections associated with the def_id.
-                let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
-
-                let mut first = true;
-                let mut is_sized = false;
-                p!(write("impl"));
-                for predicate in bounds.predicates {
-                    if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
-                        // Don't print +Sized, but rather +?Sized if absent.
-                        if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
-                            is_sized = true;
-                            continue;
-                        }
+                    // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
+                    // by looking up the projections associated with the def_id.
+                    let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
+
+                    let mut first = true;
+                    let mut is_sized = false;
+                    p!(write("impl"));
+                    for predicate in bounds.predicates {
+                        if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() {
+                            // Don't print +Sized, but rather +?Sized if absent.
+                            if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() {
+                                is_sized = true;
+                                continue;
+                            }
 
-                        p!(
-                                write("{}", if first { " " } else { "+" }),
-                                print(trait_ref));
-                        first = false;
+                            p!(
+                                    write("{}", if first { " " } else { "+" }),
+                                    print(trait_ref));
+                            first = false;
+                        }
                     }
-                }
-                if !is_sized {
-                    p!(write("{}?Sized", if first { " " } else { "+" }));
-                } else if first {
-                    p!(write(" Sized"));
-                }
+                    if !is_sized {
+                        p!(write("{}?Sized", if first { " " } else { "+" }));
+                    } else if first {
+                        p!(write(" Sized"));
+                    }
+                    Ok(self)
+                })?);
             }
             ty::Str => p!(write("str")),
             ty::Generator(did, substs, movability) => {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index d9f6d79f218..8dced83b987 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -2056,20 +2056,22 @@ fn explicit_predicates_of(
 
         Node::ImplItem(item) => match item.kind {
             ImplItemKind::OpaqueTy(ref bounds) => {
-                let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                let opaque_ty = tcx.mk_opaque(def_id, substs);
-
-                // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
-                let bounds = AstConv::compute_bounds(
-                    &icx,
-                    opaque_ty,
-                    bounds,
-                    SizedByDefault::Yes,
-                    tcx.def_span(def_id),
-                );
+                ty::print::with_no_queries(|| {
+                    let substs = InternalSubsts::identity_for_item(tcx, def_id);
+                    let opaque_ty = tcx.mk_opaque(def_id, substs);
+
+                    // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
+                    let bounds = AstConv::compute_bounds(
+                        &icx,
+                        opaque_ty,
+                        bounds,
+                        SizedByDefault::Yes,
+                        tcx.def_span(def_id),
+                    );
 
-                predicates.extend(bounds.predicates(tcx, opaque_ty));
-                &item.generics
+                    predicates.extend(bounds.predicates(tcx, opaque_ty));
+                    &item.generics
+                })
             }
             _ => &item.generics,
         },
@@ -2102,19 +2104,21 @@ fn explicit_predicates_of(
                     ref generics,
                     origin: _,
                 }) => {
-                    let substs = InternalSubsts::identity_for_item(tcx, def_id);
-                    let opaque_ty = tcx.mk_opaque(def_id, substs);
-
-                    // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
-                    let bounds = AstConv::compute_bounds(
-                        &icx,
-                        opaque_ty,
-                        bounds,
-                        SizedByDefault::Yes,
-                        tcx.def_span(def_id),
-                    );
+                    let bounds_predicates = ty::print::with_no_queries(|| {
+                        let substs = InternalSubsts::identity_for_item(tcx, def_id);
+                        let opaque_ty = tcx.mk_opaque(def_id, substs);
+
+                        // Collect the bounds, i.e., the `A + B + 'c` in `impl A + B + 'c`.
+                        let bounds = AstConv::compute_bounds(
+                            &icx,
+                            opaque_ty,
+                            bounds,
+                            SizedByDefault::Yes,
+                            tcx.def_span(def_id),
+                        );
 
-                    let bounds_predicates = bounds.predicates(tcx, opaque_ty);
+                        bounds.predicates(tcx, opaque_ty)
+                    });
                     if impl_trait_fn.is_some() {
                         // opaque types
                         return ty::GenericPredicates {