improve pretty printing for trait objects
This commit is contained in:
parent
fd9202109b
commit
18e5bbfad6
@ -1,46 +1,60 @@
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
||||
use crate::ty::{PolyTraitRef, TyCtxt};
|
||||
use crate::ty::{Clause, PolyTraitRef, ToPolyTraitRef, ToPredicate, TyCtxt};
|
||||
|
||||
/// Given a PolyTraitRef, get the PolyTraitRefs of the trait's (transitive) supertraits.
|
||||
/// Given a [`PolyTraitRef`], get the [`Clause`]s implied by the trait's definition.
|
||||
///
|
||||
/// This only exists in `rustc_middle` because the more powerful elaborator depends on
|
||||
/// `rustc_infer` for elaborating outlives bounds -- this should only be used for pretty
|
||||
/// printing.
|
||||
pub fn super_predicates_for_pretty_printing<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: PolyTraitRef<'tcx>,
|
||||
) -> impl Iterator<Item = Clause<'tcx>> {
|
||||
let clause = trait_ref.to_predicate(tcx);
|
||||
Elaborator { tcx, visited: FxHashSet::from_iter([clause]), stack: vec![clause] }
|
||||
}
|
||||
|
||||
/// Like [`super_predicates_for_pretty_printing`], except it only returns traits and filters out
|
||||
/// all other [`Clause`]s.
|
||||
pub fn supertraits_for_pretty_printing<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: PolyTraitRef<'tcx>,
|
||||
) -> impl Iterator<Item = PolyTraitRef<'tcx>> {
|
||||
Elaborator { tcx, visited: FxHashSet::from_iter([trait_ref]), stack: vec![trait_ref] }
|
||||
super_predicates_for_pretty_printing(tcx, trait_ref).filter_map(|clause| {
|
||||
clause.as_trait_clause().map(|trait_clause| trait_clause.to_poly_trait_ref())
|
||||
})
|
||||
}
|
||||
|
||||
struct Elaborator<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
visited: FxHashSet<PolyTraitRef<'tcx>>,
|
||||
stack: Vec<PolyTraitRef<'tcx>>,
|
||||
visited: FxHashSet<Clause<'tcx>>,
|
||||
stack: Vec<Clause<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> Elaborator<'tcx> {
|
||||
fn elaborate(&mut self, trait_ref: PolyTraitRef<'tcx>) {
|
||||
let supertrait_refs = self
|
||||
.tcx
|
||||
.super_predicates_of(trait_ref.def_id())
|
||||
.predicates
|
||||
.into_iter()
|
||||
.flat_map(|(pred, _)| pred.subst_supertrait(self.tcx, &trait_ref).as_trait_clause())
|
||||
.map(|t| t.map_bound(|pred| pred.trait_ref))
|
||||
.filter(|supertrait_ref| self.visited.insert(*supertrait_ref));
|
||||
let super_predicates =
|
||||
self.tcx.super_predicates_of(trait_ref.def_id()).predicates.iter().filter_map(
|
||||
|&(pred, _)| {
|
||||
let clause = pred.subst_supertrait(self.tcx, &trait_ref);
|
||||
self.visited.insert(clause).then_some(clause)
|
||||
},
|
||||
);
|
||||
|
||||
self.stack.extend(supertrait_refs);
|
||||
self.stack.extend(super_predicates);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Iterator for Elaborator<'tcx> {
|
||||
type Item = PolyTraitRef<'tcx>;
|
||||
type Item = Clause<'tcx>;
|
||||
|
||||
fn next(&mut self) -> Option<PolyTraitRef<'tcx>> {
|
||||
if let Some(trait_ref) = self.stack.pop() {
|
||||
self.elaborate(trait_ref);
|
||||
Some(trait_ref)
|
||||
fn next(&mut self) -> Option<Clause<'tcx>> {
|
||||
if let Some(clause) = self.stack.pop() {
|
||||
if let Some(trait_clause) = clause.as_trait_clause() {
|
||||
self.elaborate(trait_clause.to_poly_trait_ref());
|
||||
}
|
||||
Some(clause)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar};
|
||||
use crate::query::IntoQueryParam;
|
||||
use crate::query::Providers;
|
||||
use crate::traits::util::supertraits_for_pretty_printing;
|
||||
use crate::traits::util::{super_predicates_for_pretty_printing, supertraits_for_pretty_printing};
|
||||
use crate::ty::GenericArgKind;
|
||||
use crate::ty::{
|
||||
ConstInt, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable,
|
||||
@ -1255,8 +1255,8 @@ fn pretty_print_dyn_existential(
|
||||
// Generate the main trait ref, including associated types.
|
||||
let mut first = true;
|
||||
|
||||
if let Some(principal) = predicates.principal() {
|
||||
self.wrap_binder(&principal, |principal, cx| {
|
||||
if let Some(bound_principal) = predicates.principal() {
|
||||
self.wrap_binder(&bound_principal, |principal, cx| {
|
||||
define_scoped_cx!(cx);
|
||||
p!(print_def_path(principal.def_id, &[]));
|
||||
|
||||
@ -1281,19 +1281,48 @@ fn pretty_print_dyn_existential(
|
||||
// HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`,
|
||||
// in order to place the projections inside the `<...>`.
|
||||
if !resugared {
|
||||
// Use a type that can't appear in defaults of type parameters.
|
||||
let dummy_cx = Ty::new_fresh(cx.tcx(), 0);
|
||||
let principal = principal.with_self_ty(cx.tcx(), dummy_cx);
|
||||
let principal_with_self =
|
||||
principal.with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self);
|
||||
|
||||
let args = cx
|
||||
.tcx()
|
||||
.generics_of(principal.def_id)
|
||||
.own_args_no_defaults(cx.tcx(), principal.args);
|
||||
.generics_of(principal_with_self.def_id)
|
||||
.own_args_no_defaults(cx.tcx(), principal_with_self.args);
|
||||
|
||||
let mut projections: Vec<_> = predicates.projection_bounds().collect();
|
||||
projections.sort_by_cached_key(|proj| {
|
||||
cx.tcx().item_name(proj.item_def_id()).to_string()
|
||||
});
|
||||
let bound_principal_with_self = bound_principal
|
||||
.with_self_ty(cx.tcx(), cx.tcx().types.trait_object_dummy_self);
|
||||
|
||||
let super_projections: Vec<_> =
|
||||
super_predicates_for_pretty_printing(cx.tcx(), bound_principal_with_self)
|
||||
.filter_map(|clause| clause.as_projection_clause())
|
||||
.collect();
|
||||
|
||||
let mut projections: Vec<_> = predicates
|
||||
.projection_bounds()
|
||||
.filter_map(|proj| {
|
||||
// Filter out projections that are implied by the super predicates.
|
||||
let proj_is_implied = super_projections.iter().any(|&super_proj| {
|
||||
let proj = cx.tcx().anonymize_bound_vars(proj);
|
||||
let super_proj = cx.tcx().anonymize_bound_vars(super_proj);
|
||||
assert_eq!(proj.bound_vars(), super_proj.bound_vars());
|
||||
|
||||
let proj = proj.skip_binder();
|
||||
let super_proj = ty::ExistentialProjection::erase_self_ty(
|
||||
cx.tcx(),
|
||||
super_proj.skip_binder(),
|
||||
);
|
||||
|
||||
proj == super_proj
|
||||
});
|
||||
|
||||
// Skip the binder, because we don't want to print the binder in
|
||||
// front of the associated item.
|
||||
(!proj_is_implied).then_some(proj.skip_binder())
|
||||
})
|
||||
.collect();
|
||||
|
||||
projections
|
||||
.sort_by_cached_key(|proj| cx.tcx().item_name(proj.def_id).to_string());
|
||||
|
||||
if !args.is_empty() || !projections.is_empty() {
|
||||
p!(generic_delimiters(|cx| {
|
||||
|
@ -24,34 +24,34 @@ error[E0308]: mismatched types
|
||||
--> $DIR/pretty.rs:20:31
|
||||
|
|
||||
LL | fn dyn_fixed(x: &dyn Fixed) { x }
|
||||
| - ^ expected `()`, found `&dyn Fixed<Assoc = u8>`
|
||||
| - ^ expected `()`, found `&dyn Fixed`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn Fixed<Assoc = u8>`
|
||||
| help: try adding a return type: `-> &dyn Fixed`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found reference `&dyn Fixed<Assoc = u8>`
|
||||
found reference `&dyn Fixed`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pretty.rs:21:50
|
||||
|
|
||||
LL | fn dyn_fixed_multi(x: &dyn Fixed<Assoc = u16>) { x }
|
||||
| - ^ expected `()`, found `&dyn Fixed<Assoc = u16, Assoc = u8>`
|
||||
| - ^ expected `()`, found `&dyn Fixed<Assoc = u16>`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn Fixed<Assoc = u16, Assoc = u8>`
|
||||
| help: try adding a return type: `-> &dyn Fixed<Assoc = u16>`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found reference `&dyn Fixed<Assoc = u16, Assoc = u8>`
|
||||
found reference `&dyn Fixed<Assoc = u16>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pretty.rs:22:38
|
||||
|
|
||||
LL | fn dyn_fixed_sub(x: &dyn FixedSub) { x }
|
||||
| - ^ expected `()`, found `&dyn FixedSub<Assoc = u8>`
|
||||
| - ^ expected `()`, found `&dyn FixedSub`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn FixedSub<Assoc = u8>`
|
||||
| help: try adding a return type: `-> &dyn FixedSub`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found reference `&dyn FixedSub<Assoc = u8>`
|
||||
found reference `&dyn FixedSub`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pretty.rs:24:74
|
||||
@ -59,10 +59,10 @@ error[E0308]: mismatched types
|
||||
LL | fn dyn_super_generic(x: &dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>) { x }
|
||||
| - ^ expected `()`, found `&dyn SuperGeneric<'a, Assoc = &u8>`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn for<'a> SuperGeneric<'a, for<'a> Assoc = &'a u8>`
|
||||
| help: try adding a return type: `-> &dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found reference `&dyn for<'a> SuperGeneric<'a, for<'a> Assoc = &'a u8>`
|
||||
found reference `&dyn for<'a> SuperGeneric<'a, Assoc = &'a u8>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pretty.rs:25:70
|
||||
@ -70,54 +70,54 @@ error[E0308]: mismatched types
|
||||
LL | fn dyn_any_generic(x: &dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>) { x }
|
||||
| - ^ expected `()`, found `&dyn AnyGeneric<'a, Assoc = &u8>`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn for<'a> AnyGeneric<'a, for<'a> Assoc = &'a u8>`
|
||||
| help: try adding a return type: `-> &dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found reference `&dyn for<'a> AnyGeneric<'a, for<'a> Assoc = &'a u8>`
|
||||
found reference `&dyn for<'a> AnyGeneric<'a, Assoc = &'a u8>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pretty.rs:26:60
|
||||
|
|
||||
LL | fn dyn_fixed_generic1(x: &dyn for<'a> FixedGeneric1<'a>) { x }
|
||||
| - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc = &u8>`
|
||||
| - ^ expected `()`, found `&dyn FixedGeneric1<'a>`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &'a u8>`
|
||||
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a>`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found reference `&dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &'a u8>`
|
||||
found reference `&dyn for<'a> FixedGeneric1<'a>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pretty.rs:27:60
|
||||
|
|
||||
LL | fn dyn_fixed_generic2(x: &dyn for<'a> FixedGeneric2<'a>) { x }
|
||||
| - ^ expected `()`, found `&dyn FixedGeneric2<'a, Assoc = &u8>`
|
||||
| - ^ expected `()`, found `&dyn FixedGeneric2<'a>`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric2<'a, for<'a> Assoc = &'a u8>`
|
||||
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric2<'a>`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found reference `&dyn for<'a> FixedGeneric2<'a, for<'a> Assoc = &'a u8>`
|
||||
found reference `&dyn for<'a> FixedGeneric2<'a>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pretty.rs:28:78
|
||||
|
|
||||
LL | fn dyn_fixed_generic_multi(x: &dyn for<'a> FixedGeneric1<'a, Assoc = &u8>) { x }
|
||||
| - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc = ..., Assoc = ...>`
|
||||
| - ^ expected `()`, found `&dyn FixedGeneric1<'a, Assoc = &u8>`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &u8, for<'a> Assoc = &'a u8>`
|
||||
| help: try adding a return type: `-> &dyn for<'a> FixedGeneric1<'a, Assoc = &u8>`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found reference `&dyn for<'a> FixedGeneric1<'a, for<'a> Assoc = &u8, for<'a> Assoc = &'a u8>`
|
||||
found reference `&dyn for<'a> FixedGeneric1<'a, Assoc = &u8>`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/pretty.rs:29:40
|
||||
|
|
||||
LL | fn dyn_fixed_hrtb(x: &dyn FixedHrtb) { x }
|
||||
| - ^ expected `()`, found `&dyn FixedHrtb<Assoc = &u8>`
|
||||
| - ^ expected `()`, found `&dyn FixedHrtb`
|
||||
| |
|
||||
| help: try adding a return type: `-> &dyn FixedHrtb<for<'a> Assoc = &'a u8>`
|
||||
| help: try adding a return type: `-> &dyn FixedHrtb`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found reference `&dyn FixedHrtb<for<'a> Assoc = &'a u8>`
|
||||
found reference `&dyn FixedHrtb`
|
||||
|
||||
error: aborting due to 11 previous errors
|
||||
|
||||
|
@ -9,8 +9,8 @@ trait Callback<T: Foo>: Fn(&Bar<'_, T>, &T::V) {}
|
||||
struct Bar<'a, T> {
|
||||
callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
|
||||
//~^ ERROR the trait bound `Bar<'a, T>: Foo` is not satisfied
|
||||
//~| ERROR the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied
|
||||
//~| ERROR the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time
|
||||
//~| ERROR the trait bound `(dyn Callback<Bar<'a, T>, Output = ()> + 'static): Foo` is not satisfied
|
||||
//~| ERROR the size for values of type `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)` cannot be known at compilation time
|
||||
}
|
||||
|
||||
impl<T: Foo> Bar<'_, Bar<'_, T>> {}
|
||||
|
@ -10,11 +10,11 @@ help: this trait has no implementations, consider adding one
|
||||
LL | trait Foo {
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static): Foo` is not satisfied
|
||||
error[E0277]: the trait bound `(dyn Callback<Bar<'a, T>, Output = ()> + 'static): Foo` is not satisfied
|
||||
--> $DIR/hir-wf-canonicalized.rs:10:15
|
||||
|
|
||||
LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)`
|
||||
|
|
||||
help: this trait has no implementations, consider adding one
|
||||
--> $DIR/hir-wf-canonicalized.rs:3:1
|
||||
@ -22,13 +22,13 @@ help: this trait has no implementations, consider adding one
|
||||
LL | trait Foo {
|
||||
| ^^^^^^^^^
|
||||
|
||||
error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)` cannot be known at compilation time
|
||||
error[E0277]: the size for values of type `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)` cannot be known at compilation time
|
||||
--> $DIR/hir-wf-canonicalized.rs:10:15
|
||||
|
|
||||
LL | callback: Box<dyn Callback<dyn Callback<Bar<'a, T>>>>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `(dyn Callback<Bar<'a, T>, for<'b, 'c, 'd> Output = ()> + 'static)`
|
||||
= help: the trait `Sized` is not implemented for `(dyn Callback<Bar<'a, T>, Output = ()> + 'static)`
|
||||
note: required by an implicit `Sized` bound in `Bar`
|
||||
--> $DIR/hir-wf-canonicalized.rs:9:16
|
||||
|
|
||||
|
Loading…
Reference in New Issue
Block a user