Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cycle when debug-printing opaque types #66594

Merged
merged 2 commits into from Nov 24, 2019
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -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) => {
@@ -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 {
@@ -2124,7 +2128,7 @@ fn explicit_predicates_of(
} else {
// named opaque types
predicates.extend(bounds_predicates);
generics
generics.clone()
This conversation was marked as resolved by Aaron1011

This comment has been minimized.

Copy link
@matthewjasper

matthewjasper Nov 23, 2019

Contributor

Is this cloneing a reference. I can't see why this is now necessary.

}
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.