Skip to content

Commit ca961b3

Browse files
authored
Merge pull request #563 from nathanwhit/opaque-where-clauses
Support where clauses on opaque types
2 parents fb58034 + 1d0f5a0 commit ca961b3

File tree

7 files changed

+95
-14
lines changed

7 files changed

+95
-14
lines changed

chalk-integration/src/lowering.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -594,11 +594,11 @@ impl LowerProgram for Program {
594594
chalk_ir::VariableKind::Ty(TyKind::General),
595595
Atom::from(FIXME_SELF),
596596
)),
597-
|env1| {
598-
let interner = env1.interner();
597+
|env| {
598+
let interner = env.interner();
599599
Ok(opaque_ty
600600
.bounds
601-
.lower(&env1)?
601+
.lower(&env)?
602602
.iter()
603603
.flat_map(|qil| {
604604
// Instantiate the bounds with the innermost bound variable, which represents Self, as the self type.
@@ -614,8 +614,19 @@ impl LowerProgram for Program {
614614
.collect())
615615
},
616616
)?;
617-
618-
Ok(OpaqueTyDatumBound { bounds })
617+
let where_clauses: chalk_ir::Binders<Vec<chalk_ir::Binders<_>>> = env
618+
.in_binders(
619+
Some(chalk_ir::WithKind::new(
620+
chalk_ir::VariableKind::Ty(TyKind::General),
621+
Atom::from(FIXME_SELF),
622+
)),
623+
|env| opaque_ty.where_clauses.lower(env),
624+
)?;
625+
626+
Ok(OpaqueTyDatumBound {
627+
bounds,
628+
where_clauses,
629+
})
619630
})?;
620631

621632
opaque_ty_data.insert(

chalk-parse/src/ast.rs

+1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ pub struct OpaqueTyDefn {
142142
pub variable_kinds: Vec<VariableKind>,
143143
pub identifier: Identifier,
144144
pub bounds: Vec<QuantifiedInlineBound>,
145+
pub where_clauses: Vec<QuantifiedWhereClause>,
145146
}
146147

147148
#[derive(Clone, PartialEq, Eq, Debug)]

chalk-parse/src/parser.lalrpop

+4-2
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,14 @@ AssocTyDefn: AssocTyDefn = {
219219
};
220220

221221
OpaqueTyDefn: OpaqueTyDefn = {
222-
"opaque" "type" <identifier:Id> <p:Angle<VariableKind>> ":" <b:Plus<QuantifiedInlineBound>> "=" <ty:Ty> ";" => {
222+
"opaque" "type" <identifier:Id> <p:Angle<VariableKind>> ":" <b:Plus<QuantifiedInlineBound>>
223+
<w:QuantifiedWhereClauses> "=" <ty:Ty> ";" => {
223224
OpaqueTyDefn {
224225
ty,
225226
variable_kinds: p,
226227
identifier,
227228
bounds: b,
229+
where_clauses: w,
228230
}
229231
}
230232
};
@@ -332,7 +334,7 @@ TyWithoutId: Ty = {
332334
"*" <m: RawMutability> <t:Ty> => Ty::Raw{ mutability: m, ty: Box::new(t) },
333335
"&" <l: Lifetime> "mut" <t:Ty> => Ty::Ref{ mutability: Mutability::Mut, lifetime: l, ty: Box::new(t) },
334336
"&" <l: Lifetime> <t:Ty> => Ty::Ref{ mutability: Mutability::Not, lifetime: l, ty: Box::new(t) },
335-
"[" <t:Ty> "]" => Ty::Slice { ty: Box::new(t) },
337+
"[" <t:Ty> "]" => Ty::Slice { ty: Box::new(t) },
336338
"[" <t:Ty> ";" <len:Const> "]" => Ty::Array { ty: Box::new(t), len },
337339
};
338340

chalk-solve/src/clauses/program_clauses.rs

+17-6
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,14 @@ impl<I: Interner> ToProgramClauses<I> for AssociatedTyValue<I> {
128128
}
129129

130130
impl<I: Interner> ToProgramClauses<I> for OpaqueTyDatum<I> {
131-
/// Given `opaque type T<..>: A + B = HiddenTy;`, we generate:
131+
/// Given `opaque type T<U>: A + B = HiddenTy where U: C;`, we generate:
132132
///
133133
/// ```notrust
134-
/// AliasEq(T<..> = HiddenTy) :- Reveal.
135-
/// AliasEq(T<..> = !T<..>).
136-
/// Implemented(!T<..>: A).
137-
/// Implemented(!T<..>: B).
134+
/// AliasEq(T<U> = HiddenTy) :- Reveal.
135+
/// AliasEq(T<U> = !T<U>).
136+
/// WF(T<U>) :- WF(U: C).
137+
/// Implemented(!T<U>: A).
138+
/// Implemented(!T<U>: B).
138139
/// ```
139140
/// where `!T<..>` is the placeholder for the unnormalized type `T<..>`.
140141
#[instrument(level = "debug", skip(builder))]
@@ -180,7 +181,17 @@ impl<I: Interner> ToProgramClauses<I> for OpaqueTyDatum<I> {
180181
.cast(interner),
181182
));
182183

183-
let substitution = Substitution::from1(interner, alias_placeholder_ty.clone());
184+
// WF(!T<..>) :- WF(WC).
185+
builder.push_binders(&opaque_ty_bound.where_clauses, |builder, where_clauses| {
186+
builder.push_clause(
187+
WellFormed::Ty(alias_placeholder_ty.clone()),
188+
where_clauses
189+
.into_iter()
190+
.map(|wc| wc.into_well_formed_goal(interner)),
191+
);
192+
});
193+
194+
let substitution = Substitution::from1(interner, alias_placeholder_ty);
184195
for bound in opaque_ty_bound.bounds {
185196
// Implemented(!T<..>: Bound).
186197
let bound_with_placeholder_ty = bound.substitute(interner, &substitution);

chalk-solve/src/display/stub.rs

+1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ impl<I: Interner, DB: RustIrDatabase<I>> RustIrDatabase<I> for StubWrapper<'_, D
116116
v.bound.binders,
117117
OpaqueTyDatumBound {
118118
bounds: Binders::new(VariableKinds::empty(self.db.interner()), Vec::new()),
119+
where_clauses: Binders::new(VariableKinds::empty(self.db.interner()), Vec::new()),
119120
},
120121
);
121122
Arc::new(v)

chalk-solve/src/rust_ir.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -643,8 +643,12 @@ pub struct OpaqueTyDatum<I: Interner> {
643643

644644
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner, Visit)]
645645
pub struct OpaqueTyDatumBound<I: Interner> {
646-
/// Trait bounds for the opaque type.
646+
/// Trait bounds for the opaque type. These are bounds that the hidden type must meet.
647647
pub bounds: Binders<Vec<QuantifiedWhereClause<I>>>,
648+
/// Where clauses that inform well-formedness conditions for the opaque type.
649+
/// These are conditions on the generic parameters of the opaque type which must be true
650+
/// for a reference to the opaque type to be well-formed.
651+
pub where_clauses: Binders<Vec<QuantifiedWhereClause<I>>>,
648652
}
649653

650654
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]

tests/test/opaque_types.rs

+51
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,57 @@ fn opaque_reveal() {
4646
}
4747
}
4848

49+
#[test]
50+
fn opaque_where_clause() {
51+
test! {
52+
program {
53+
struct Ty { }
54+
55+
trait Clone { }
56+
trait Trait { }
57+
impl Trait for Ty { }
58+
opaque type T: Clone where T: Trait = Ty;
59+
60+
struct Vec<U> { }
61+
impl<U> Trait for Vec<U> { }
62+
63+
opaque type S<U>: Clone where U: Trait = Vec<U>;
64+
}
65+
66+
goal {
67+
if (T: Trait) {
68+
WellFormed(T)
69+
}
70+
} yields {
71+
"Unique; substitution []"
72+
}
73+
74+
goal {
75+
WellFormed(T)
76+
} yields {
77+
"No possible solution"
78+
}
79+
80+
goal {
81+
forall<U> {
82+
if (U : Trait) {
83+
WellFormed(S<U>)
84+
}
85+
}
86+
} yields {
87+
"Unique; substitution []"
88+
}
89+
90+
goal {
91+
forall<U> {
92+
WellFormed(S<U>)
93+
}
94+
} yields {
95+
"No possible solution"
96+
}
97+
}
98+
}
99+
49100
#[test]
50101
fn opaque_generics_simple() {
51102
test! {

0 commit comments

Comments
 (0)