Skip to content

Commit a8a8d6b

Browse files
committed
Auto merge of #49435 - tmandry:rule-implied-bound-from-trait, r=nikomatsakis
chalkify: Implement lowering rule Implied-Bound-From-Trait For #49177. TODO: - [x] Implement where clauses besides trait and projection predicates - [x] Is the output of the `lower_trait_higher_rank` test correct? - [ ] Remove `Self::Trait` from the query `tcx.predicates_of(<trait_id>).predicates` - [ ] Consider moving tests to compile-fail to make them more manageable
2 parents 880fbd7 + 7ac35ea commit a8a8d6b

7 files changed

+212
-5
lines changed

src/librustc_traits/lowering.rs

+65-4
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,28 @@ impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> {
9090
}
9191
}
9292

93+
/// Transforms an existing goal into a FromEnv goal.
94+
///
95+
/// Used for lowered where clauses (see rustc guide).
96+
trait IntoFromEnvGoal {
97+
fn into_from_env_goal(self) -> Self;
98+
}
99+
100+
impl<'tcx> IntoFromEnvGoal for DomainGoal<'tcx> {
101+
fn into_from_env_goal(self) -> DomainGoal<'tcx> {
102+
use self::DomainGoal::*;
103+
match self {
104+
Holds(wc_atom) => FromEnv(wc_atom),
105+
WellFormed(..) |
106+
FromEnv(..) |
107+
WellFormedTy(..) |
108+
FromEnvTy(..) |
109+
RegionOutlives(..) |
110+
TypeOutlives(..) => self,
111+
}
112+
}
113+
}
114+
93115
crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
94116
-> Lrc<Vec<Clause<'tcx>>>
95117
{
@@ -107,9 +129,9 @@ crate fn program_clauses_for<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
107129
fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
108130
-> Lrc<Vec<Clause<'tcx>>>
109131
{
110-
// Rule Implemented-From-Env (see rustc guide)
111-
//
112132
// `trait Trait<P1..Pn> where WC { .. } // P0 == Self`
133+
134+
// Rule Implemented-From-Env (see rustc guide)
113135
//
114136
// ```
115137
// forall<Self, P1..Pn> {
@@ -130,11 +152,50 @@ fn program_clauses_for_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefI
130152
let impl_trait = DomainGoal::Holds(WhereClauseAtom::Implemented(trait_pred));
131153

132154
// `Implemented(Self: Trait<P1..Pn>) :- FromEnv(Self: Trait<P1..Pn>)`
133-
let clause = ProgramClause {
155+
let implemented_from_env = ProgramClause {
134156
goal: impl_trait,
135157
hypotheses: vec![from_env],
136158
};
137-
Lrc::new(vec![Clause::ForAll(ty::Binder::dummy(clause))])
159+
let mut clauses = vec![
160+
Clause::ForAll(ty::Binder::dummy(implemented_from_env))
161+
];
162+
163+
// Rule Implied-Bound-From-Trait
164+
//
165+
// For each where clause WC:
166+
// ```
167+
// forall<Self, P1..Pn> {
168+
// FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn)
169+
// }
170+
// ```
171+
172+
// `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`, for each where clause WC
173+
// FIXME: Remove the [1..] slice; this is a hack because the query
174+
// predicates_of currently includes the trait itself (`Self: Trait<P1..Pn>`).
175+
let where_clauses = &tcx.predicates_of(def_id).predicates;
176+
let implied_bound_clauses =
177+
where_clauses[1..].into_iter()
178+
.map(|wc| implied_bound_from_trait(trait_pred, wc));
179+
clauses.extend(implied_bound_clauses);
180+
181+
Lrc::new(clauses)
182+
}
183+
184+
/// For a given `where_clause`, returns a clause `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`.
185+
fn implied_bound_from_trait<'tcx>(
186+
trait_pred: ty::TraitPredicate<'tcx>,
187+
where_clause: &ty::Predicate<'tcx>,
188+
) -> Clause<'tcx> {
189+
// `FromEnv(Self: Trait<P1..Pn>)`
190+
let impl_trait = DomainGoal::FromEnv(WhereClauseAtom::Implemented(trait_pred));
191+
192+
// `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`
193+
Clause::ForAll(
194+
where_clause.lower().map_bound(|goal| ProgramClause {
195+
goal: goal.into_from_env_goal(),
196+
hypotheses: vec![impl_trait.into()],
197+
})
198+
)
138199
}
139200

140201
fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)

src/test/ui/chalkify/lower_trait.rs

+3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#![feature(rustc_attrs)]
1212

1313
#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
14+
//~| ERROR FromEnv
15+
//~| ERROR FromEnv
16+
//~| ERROR FromEnv
1417
trait Foo<S, T, U> {
1518
fn s(S) -> S;
1619
fn t(T) -> T;

src/test/ui/chalkify/lower_trait.stderr

+19-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,23 @@ error: Implemented(Self: Foo<S, T, U>) :- FromEnv(Self: Foo<S, T, U>).
44
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66

7-
error: aborting due to previous error
7+
error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
8+
--> $DIR/lower_trait.rs:13:1
9+
|
10+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
14+
--> $DIR/lower_trait.rs:13:1
15+
|
16+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: FromEnv(U: std::marker::Sized) :- FromEnv(Self: Foo<S, T, U>).
20+
--> $DIR/lower_trait.rs:13:1
21+
|
22+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<S, T, U>) :-
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: aborting due to 4 previous errors
826

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(rustc_attrs)]
12+
13+
#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
14+
//~| ERROR FromEnv
15+
//~| ERROR FromEnv
16+
//~| ERROR FromEnv
17+
trait Foo<F> where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8
18+
{
19+
fn s(F) -> F;
20+
}
21+
22+
fn main() {
23+
println!("hello");
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: Implemented(Self: Foo<F>) :- FromEnv(Self: Foo<F>).
2+
--> $DIR/lower_trait_higher_rank.rs:13:1
3+
|
4+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: FromEnv(F: std::marker::Sized) :- FromEnv(Self: Foo<F>).
8+
--> $DIR/lower_trait_higher_rank.rs:13:1
9+
|
10+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo<F>).
14+
--> $DIR/lower_trait_higher_rank.rs:13:1
15+
|
16+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: FromEnv(<F as std::ops::FnOnce<(&'a (u8, u16),)>>::Output == &'a u8) :- FromEnv(Self: Foo<F>).
20+
--> $DIR/lower_trait_higher_rank.rs:13:1
21+
|
22+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<F>) :-
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: aborting due to 4 previous errors
26+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(rustc_attrs)]
12+
13+
use std::fmt::{Debug, Display};
14+
use std::borrow::Borrow;
15+
16+
#[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
17+
//~| ERROR FromEnv
18+
//~| ERROR FromEnv
19+
//~| ERROR FromEnv
20+
//~| ERROR FromEnv
21+
//~| ERROR RegionOutlives
22+
//~| ERROR TypeOutlives
23+
trait Foo<'a, 'b, S, T, U> where S: Debug, T: Borrow<U>, U: ?Sized, 'a: 'b, U: 'b {
24+
fn s(S) -> S;
25+
fn t(T) -> T;
26+
fn u(U) -> U;
27+
}
28+
29+
fn main() {
30+
println!("hello");
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
error: Implemented(Self: Foo<'a, 'b, S, T, U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
2+
--> $DIR/lower_trait_where_clause.rs:16:1
3+
|
4+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
8+
--> $DIR/lower_trait_where_clause.rs:16:1
9+
|
10+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: FromEnv(T: std::marker::Sized) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
14+
--> $DIR/lower_trait_where_clause.rs:16:1
15+
|
16+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: FromEnv(S: std::fmt::Debug) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
20+
--> $DIR/lower_trait_where_clause.rs:16:1
21+
|
22+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: FromEnv(T: std::borrow::Borrow<U>) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
26+
--> $DIR/lower_trait_where_clause.rs:16:1
27+
|
28+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
31+
error: RegionOutlives('a : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
32+
--> $DIR/lower_trait_where_clause.rs:16:1
33+
|
34+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36+
37+
error: TypeOutlives(U : 'b) :- FromEnv(Self: Foo<'a, 'b, S, T, U>).
38+
--> $DIR/lower_trait_where_clause.rs:16:1
39+
|
40+
LL | #[rustc_dump_program_clauses] //~ ERROR Implemented(Self: Foo<'a, 'b, S, T, U>) :-
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
43+
error: aborting due to 7 previous errors
44+

0 commit comments

Comments
 (0)