]> git.lizzy.rs Git - rust.git/commitdiff
Pretty print quantified goals and clauses
authorscalexm <alexandre@scalexm.fr>
Wed, 31 Oct 2018 17:55:40 +0000 (18:55 +0100)
committerscalexm <alexandre@scalexm.fr>
Tue, 13 Nov 2018 11:28:43 +0000 (12:28 +0100)
16 files changed:
src/librustc/traits/structural_impls.rs
src/librustc_traits/lowering/environment.rs
src/librustc_traits/lowering/mod.rs
src/test/ui/chalkify/lower_env1.rs
src/test/ui/chalkify/lower_env1.stderr
src/test/ui/chalkify/lower_env2.rs
src/test/ui/chalkify/lower_env2.stderr
src/test/ui/chalkify/lower_env3.stderr
src/test/ui/chalkify/lower_impl.stderr
src/test/ui/chalkify/lower_struct.rs
src/test/ui/chalkify/lower_struct.stderr
src/test/ui/chalkify/lower_trait.stderr
src/test/ui/chalkify/lower_trait_higher_rank.rs
src/test/ui/chalkify/lower_trait_higher_rank.stderr
src/test/ui/chalkify/lower_trait_where_clause.rs
src/test/ui/chalkify/lower_trait_where_clause.stderr

index e83d085971caa32ef52c6b2fbab491d53c5cc58d..66d9c6711bb5804304aa8d9750eb749b44e57a5e 100644 (file)
 use traits::project::Normalized;
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use ty::{self, Lift, TyCtxt};
+use syntax::symbol::InternedString;
 
 use std::fmt;
 use std::rc::Rc;
+use std::collections::{BTreeSet, BTreeMap};
 
 // structural impls for the structs in traits
 
@@ -479,7 +481,12 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
             Holds(wc) => write!(fmt, "{}", wc),
             WellFormed(wf) => write!(fmt, "{}", wf),
             FromEnv(from_env) => write!(fmt, "{}", from_env),
-            Normalize(projection) => write!(fmt, "Normalize({})", projection),
+            Normalize(projection) => write!(
+                fmt,
+                "Normalize({} -> {})",
+                projection.projection_ty,
+                projection.ty
+            ),
         }
     }
 }
@@ -495,6 +502,110 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+/// Collect names for regions / types bound by a quantified goal / clause.
+/// This collector does not try to do anything clever like in ppaux, it's just used
+/// for debug output in tests anyway.
+struct BoundNamesCollector {
+    // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway.
+    regions: BTreeSet<InternedString>,
+
+    // Sort by `BoundVar` index, so usually this should be equivalent to the order given
+    // by the list of type parameters.
+    types: BTreeMap<u32, InternedString>,
+
+    binder_index: ty::DebruijnIndex,
+}
+
+impl BoundNamesCollector {
+    fn new() -> Self {
+        BoundNamesCollector {
+            regions: BTreeSet::new(),
+            types: BTreeMap::new(),
+            binder_index: ty::INNERMOST,
+        }
+    }
+
+    fn is_empty(&self) -> bool {
+        self.regions.is_empty() && self.types.is_empty()
+    }
+
+    fn write_names(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut start = true;
+        for r in &self.regions {
+            if !start {
+                write!(fmt, ", ")?;
+            }
+            start = false;
+            write!(fmt, "{}", r)?;
+        }
+        for (_, t) in &self.types {
+            if !start {
+                write!(fmt, ", ")?;
+            }
+            start = false;
+            write!(fmt, "{}", t)?;
+        }
+        Ok(())
+    }
+}
+
+impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector {
+    fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
+        self.binder_index.shift_in(1);
+        let result = t.super_visit_with(self);
+        self.binder_index.shift_out(1);
+        result
+    }
+
+    fn visit_ty(&mut self, t: ty::Ty<'tcx>) -> bool {
+        use syntax::symbol::Symbol;
+
+        match t.sty {
+            ty::Bound(bound_ty) if bound_ty.index == self.binder_index => {
+                self.types.insert(
+                    bound_ty.var.as_u32(),
+                    match bound_ty.kind {
+                        ty::BoundTyKind::Param(name) => name,
+                        ty::BoundTyKind::Anon => Symbol::intern(
+                            &format!("?{}", bound_ty.var.as_u32())
+                        ).as_interned_str(),
+                    }
+                );
+            }
+
+            _ => (),
+        };
+
+        t.super_visit_with(self)
+    }
+
+    fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
+        use syntax::symbol::Symbol;
+
+        match r {
+            ty::ReLateBound(index, br) if *index == self.binder_index => {
+                match br {
+                    ty::BoundRegion::BrNamed(_, name) => {
+                        self.regions.insert(*name);
+                    }
+
+                    ty::BoundRegion::BrAnon(var) => {
+                        self.regions.insert(Symbol::intern(
+                            &format!("?'{}", var)
+                        ).as_interned_str());
+                    }
+
+                    _ => (),
+                }
+            }
+
+            _ => (),
+        };
+
+        r.super_visit_with(self)
+    }
+}
+
 impl<'tcx> fmt::Display for traits::Goal<'tcx> {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         use traits::GoalKind::*;
@@ -514,8 +625,22 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
             Not(goal) => write!(fmt, "not {{ {} }}", goal),
             DomainGoal(goal) => write!(fmt, "{}", goal),
             Quantified(qkind, goal) => {
-                // FIXME: appropriate binder names
-                write!(fmt, "{}<> {{ {} }}", qkind, goal.skip_binder())
+                let mut collector = BoundNamesCollector::new();
+                goal.skip_binder().visit_with(&mut collector);
+
+                if !collector.is_empty() {
+                    write!(fmt, "{}<", qkind)?;
+                    collector.write_names(fmt)?;
+                    write!(fmt, "> {{ ")?;
+                }
+
+                write!(fmt, "{}", goal.skip_binder())?;
+
+                if !collector.is_empty() {
+                    write!(fmt, " }}")?;
+                }
+
+                Ok(())
             }
             CannotProve => write!(fmt, "CannotProve"),
         }
@@ -546,8 +671,22 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             Implies(clause) => write!(fmt, "{}", clause),
             ForAll(clause) => {
-                // FIXME: appropriate binder names
-                write!(fmt, "forall<> {{ {} }}", clause.skip_binder())
+                let mut collector = BoundNamesCollector::new();
+                clause.skip_binder().visit_with(&mut collector);
+
+                if !collector.is_empty() {
+                    write!(fmt, "forall<")?;
+                    collector.write_names(fmt)?;
+                    write!(fmt, "> {{ ")?;
+                }
+
+                write!(fmt, "{}", clause.skip_binder())?;
+
+                if !collector.is_empty() {
+                    write!(fmt, " }}")?;
+                }
+
+                Ok(())
             }
         }
     }
index c5dc91dec6bfecd6858b812d3f33eac16261d78b..7042c9f515dae74ce2689780881303f92114159a 100644 (file)
@@ -250,8 +250,8 @@ fn visit_clause(&mut self, clause: Clause<'tcx>) {
     // In an fn, we assume that the arguments and all their constituents are
     // well-formed.
     if is_fn {
-        // `skip_binder` because we move late bound regions to the root binder,
-        // restored in the return type
+        // `skip_binder` because we move region parameters to the root binder,
+        // restored in the return type of this query
         let fn_sig = tcx.fn_sig(def_id).skip_binder().subst(tcx, bound_vars);
 
         input_tys.extend(
index fc25faed3def88f8209a2fd319ae25761345b99e..021ec18009a2540de1847d2188afe525dbdf25f9 100644 (file)
@@ -600,14 +600,7 @@ fn process_attrs(&mut self, node_id: ast::NodeId, attrs: &[ast::Attribute]) {
 
                 let mut strings: Vec<_> = clauses
                     .iter()
-                    .map(|clause| {
-                        // Skip the top-level binder for a less verbose output
-                        let program_clause = match clause {
-                            Clause::Implies(program_clause) => program_clause,
-                            Clause::ForAll(program_clause) => program_clause.skip_binder(),
-                        };
-                        program_clause.to_string()
-                    })
+                    .map(|clause| clause.to_string())
                     .collect();
 
                 strings.sort();
index fc20ad0e08b2a40afd3419c964831d965ba29fea..b772db5ca5523f21f3b2400158cc1161886843d5 100644 (file)
@@ -17,7 +17,7 @@ trait Foo { }
 trait Bar where Self: Foo { }
 
 #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
-fn bar<T: Bar>() {
+fn bar<T: Bar + ?Sized>() {
 }
 
 fn main() {
index 3aa04cfeb67d40c4e02e9c24b3a9f32770536674..4aa40bae3193231210f05d596eb19eb7942b2915 100644 (file)
@@ -4,9 +4,9 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
-   = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
-   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo).
+   = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). }
 
 error: program clause dump
   --> $DIR/lower_env1.rs:19:1
@@ -14,10 +14,9 @@ error: program clause dump
 LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
-   = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
-   = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
-   = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
+   = note: forall<Self> { FromEnv(Self: Foo) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { Implemented(Self: Bar) :- FromEnv(Self: Bar). }
+   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
 
 error: aborting due to 2 previous errors
 
index 0b50dbfdf95c6714b8c9c9c87940b86c25543c31..2328db5b4f687cf833f256c2b41fecd7ab90967d 100644 (file)
 trait Foo { }
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
-struct S<'a, T> where T: Foo {
+struct S<'a, T: ?Sized> where T: Foo {
     data: &'a T,
 }
 
 #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
-fn bar<'a, T: Foo>(x: S<T>) {
+fn bar<T: Foo>(_x: S<'_, T>) { // note that we have an implicit `T: Sized` bound
 }
 
 fn main() {
index 3b88ac1f22bea6d24d18c4ab02d7bd26441450dc..aaf6eda641dbb7d52187c3a8b05ad9c56d7bf437 100644 (file)
@@ -4,10 +4,9 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(T: Foo) :- FromEnv(S<'a, T>).
-   = note: FromEnv(T: std::marker::Sized) :- FromEnv(S<'a, T>).
-   = note: TypeOutlives(T : 'a) :- FromEnv(S<'a, T>).
-   = note: WellFormed(S<'a, T>) :- Implemented(T: std::marker::Sized), Implemented(T: Foo), TypeOutlives(T : 'a).
+   = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
+   = note: forall<'a, T> { TypeOutlives(T : 'a) :- FromEnv(S<'a, T>). }
+   = note: forall<'a, T> { WellFormed(S<'a, T>) :- Implemented(T: Foo), TypeOutlives(T : 'a). }
 
 error: program clause dump
   --> $DIR/lower_env2.rs:21:1
@@ -15,11 +14,10 @@ error: program clause dump
 LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(T: Foo) :- FromEnv(S<'a, T>).
-   = note: FromEnv(T: std::marker::Sized) :- FromEnv(S<'a, T>).
-   = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
-   = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
-   = note: TypeOutlives(T : 'a) :- FromEnv(S<'a, T>).
+   = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). }
+   = note: forall<'a, T> { TypeOutlives(T : 'a) :- FromEnv(S<'a, T>). }
+   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
+   = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
 
 error: aborting due to 2 previous errors
 
index ac0f8e34cd437db975fefe0d7e43dd627da38f52..f507deb6fa04c8c12094536f763c05958a1f0211 100644 (file)
@@ -4,7 +4,7 @@ error: program clause dump
 LL |     #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
+   = note: forall<Self> { Implemented(Self: Foo) :- FromEnv(Self: Foo). }
 
 error: program clause dump
   --> $DIR/lower_env3.rs:20:5
@@ -12,9 +12,9 @@ error: program clause dump
 LL |     #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone).
-   = note: Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone).
-   = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
+   = note: forall<Self> { FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone). }
+   = note: forall<Self> { Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone). }
+   = note: forall<Self> { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). }
 
 error: aborting due to 2 previous errors
 
index c497d76f8d4f964e9bcaed31ca1808e1bc4cd194..ed84fe4eb26c52c7f4b7710fd740f2a0e38b7a93 100644 (file)
@@ -4,7 +4,7 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized).
+   = note: forall<T> { Implemented(T: Foo) :- ProjectionEq(<T as std::iter::Iterator>::Item == i32), TypeOutlives(T : 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). }
 
 error: program clause dump
   --> $DIR/lower_impl.rs:23:5
@@ -12,7 +12,7 @@ error: program clause dump
 LL |     #[rustc_dump_program_clauses] //~ ERROR program clause dump
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: Normalize(<T as Bar>::Assoc == std::vec::Vec<T>) :- Implemented(T: Bar).
+   = note: forall<T> { Normalize(<T as Bar>::Assoc -> std::vec::Vec<T>) :- Implemented(T: Bar). }
 
 error: aborting due to 2 previous errors
 
index 9287555a0568410a9262bc41a5e6ec09337781ec..9b4bba67112ea82df67855cdf71adebbea28f23c 100644 (file)
@@ -11,8 +11,8 @@
 #![feature(rustc_attrs)]
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
-struct Foo<T> where Box<T>: Clone {
-    _x: std::marker::PhantomData<T>,
+struct Foo<'a, T> where Box<T>: Clone {
+    _x: std::marker::PhantomData<&'a T>,
 }
 
 fn main() { }
index d6cc9c8e9a401d5c93a8d0459fc2fec5e9c1c623..a12ee52a086f64f8a679c29d6581c58b362eb0d7 100644 (file)
@@ -4,9 +4,10 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(T: std::marker::Sized) :- FromEnv(Foo<T>).
-   = note: FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<T>).
-   = note: WellFormed(Foo<T>) :- Implemented(T: std::marker::Sized), Implemented(std::boxed::Box<T>: std::clone::Clone).
+   = note: forall<'a, T> { FromEnv(T: std::marker::Sized) :- FromEnv(Foo<'a, T>). }
+   = note: forall<'a, T> { FromEnv(std::boxed::Box<T>: std::clone::Clone) :- FromEnv(Foo<'a, T>). }
+   = note: forall<'a, T> { TypeOutlives(T : 'a) :- FromEnv(Foo<'a, T>). }
+   = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- Implemented(T: std::marker::Sized), Implemented(std::boxed::Box<T>: std::clone::Clone), TypeOutlives(T : 'a). }
 
 error: aborting due to previous error
 
index dc2375277e7342d713049d371ae759707c5fdd1f..6a3f7aa63765f20f16a0d23f822d36484c34f7c8 100644 (file)
@@ -4,10 +4,10 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>).
-   = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>).
-   = note: Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>).
-   = note: WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar).
+   = note: forall<Self, S, T> { FromEnv(<Self as Foo<S, T>>::Assoc: Bar) :- FromEnv(Self: Foo<S, T>). }
+   = note: forall<Self, S, T> { FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T>). }
+   = note: forall<Self, S, T> { Implemented(Self: Foo<S, T>) :- FromEnv(Self: Foo<S, T>). }
+   = note: forall<Self, S, T> { WellFormed(Self: Foo<S, T>) :- Implemented(Self: Foo<S, T>), WellFormed(S: std::marker::Sized), WellFormed(<Self as Foo<S, T>>::Assoc: Bar). }
 
 error: program clause dump
   --> $DIR/lower_trait.rs:17:5
@@ -15,9 +15,9 @@ error: program clause dump
 LL |     #[rustc_dump_program_clauses] //~ ERROR program clause dump
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)).
-   = note: ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)).
-   = note: WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>).
+   = note: forall<Self, S, T> { FromEnv(Self: Foo<S, T>) :- FromEnv(Unnormalized(<Self as Foo<S, T>>::Assoc)). }
+   = note: forall<Self, S, T> { ProjectionEq(<Self as Foo<S, T>>::Assoc == Unnormalized(<Self as Foo<S, T>>::Assoc)). }
+   = note: forall<Self, S, T> { WellFormed(Unnormalized(<Self as Foo<S, T>>::Assoc)) :- Implemented(Self: Foo<S, T>). }
 
 error: aborting due to 2 previous errors
 
index 7fc48cfd56ddcc3b0ffda6253f3fd8ce9c0674ad..c0e1d8fc4c828ef54c61957998be39894c682c70 100644 (file)
@@ -11,9 +11,8 @@
 #![feature(rustc_attrs)]
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<F> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
+trait Foo<F: ?Sized> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
 {
-    fn s(_: F) -> F;
 }
 
 fn main() {
index afb2cd4b563329aa8e07f57de163ac70aeb9aa34..6d3e0ec55b276f966be12bbfe4f57427207ff253 100644 (file)
@@ -4,11 +4,10 @@ error: program clause dump
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
-   = note: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
-   = note: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
-   = note: ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
-   = note: WellFormed(Self: Foo<F>) :- Implemented(Self: Foo<F>), WellFormed(F: std::marker::Sized), forall<> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) }.
+   = note: forall<'a, Self, F> { FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>). }
+   = note: forall<'a, Self, F> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>). }
+   = note: forall<Self, F> { Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>). }
+   = note: forall<Self, F> { WellFormed(Self: Foo<F>) :- Implemented(Self: Foo<F>), forall<'a> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<'a> { ProjectionEq(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) }. }
 
 error: aborting due to previous error
 
index 5305591b8434547402ee4ca0e918403cf9b08e01..ac58c0bf2fe37778e477db7d5b954bd8c22d0377 100644 (file)
 
 #![feature(rustc_attrs)]
 
-use std::fmt::{Debug, Display};
 use std::borrow::Borrow;
 
 #[rustc_dump_program_clauses] //~ ERROR program clause dump
-trait Foo<'a, 'b, S, T, U>
+trait Foo<'a, 'b, T, U>
 where
-    S: Debug,
-    T: Borrow<U>,
-    U: ?Sized,
+    T: Borrow<U> + ?Sized,
+    U: ?Sized + 'b,
     'a: 'b,
-    U: 'b,
-    Vec<T>:, // NOTE(#53696) this checks an empty list of bounds.
+    Box<T>:, // NOTE(#53696) this checks an empty list of bounds.
 {
-    fn s(_: S) -> S;
-    fn t(_: T) -> T;
-    fn u(_: U) -> U;
 }
 
 fn main() {
index ad3546da1a25b4e93432af8be214dcce119757c7..f4f3effaaaef78f9a7c9e5f60d0e93012578ce84 100644 (file)
@@ -1,18 +1,15 @@
 error: program clause dump
-  --> $DIR/lower_trait_where_clause.rs:16:1
+  --> $DIR/lower_trait_where_clause.rs:15:1
    |
 LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
-   = note: WellFormed(Self: Foo<'a, 'b, S, T, U>) :- Implemented(Self: Foo<'a, 'b, S, T, U>), WellFormed(S: std::marker::Sized), WellFormed(T: std::marker::Sized), WellFormed(S: std::fmt::Debug), WellFormed(T: std::borrow::Borrow<U>), RegionOutlives('a : 'b), TypeOutlives(U : 'b), WellFormed(std::vec::Vec<T>).
-   = note: WellFormed(std::vec::Vec<T>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
+   = note: forall<'a, 'b, Self, T, U> { FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { Implemented(Self: Foo<'a, 'b, T, U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
+   = note: forall<'a, 'b, Self, T, U> { WellFormed(Self: Foo<'a, 'b, T, U>) :- Implemented(Self: Foo<'a, 'b, T, U>), WellFormed(T: std::borrow::Borrow<U>), TypeOutlives(U : 'b), RegionOutlives('a : 'b), WellFormed(std::boxed::Box<T>). }
+   = note: forall<'a, 'b, Self, T, U> { WellFormed(std::boxed::Box<T>) :- FromEnv(Self: Foo<'a, 'b, T, U>). }
 
 error: aborting due to previous error