Skip to content

Commit 7e39323

Browse files
scalexmnikomatsakis
authored andcommitted
Add WF checks for struct fields
1 parent a51a25b commit 7e39323

3 files changed

Lines changed: 69 additions & 17 deletions

File tree

src/ir/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ pub struct StructDatum {
196196
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
197197
pub struct StructDatumBound {
198198
pub self_ty: ApplicationTy,
199+
pub fields: Vec<Ty>,
199200
pub where_clauses: Vec<DomainGoal>,
200201
}
201202

@@ -224,9 +225,6 @@ pub struct AssociatedTyDatum {
224225
/// Parameters on this associated type, beginning with those from the trait,
225226
/// but possibly including more.
226227
pub parameter_kinds: Vec<ParameterKind<Identifier>>,
227-
228-
/// Where clauses that must hold for the projection be well-formed.
229-
pub where_clauses: Vec<DomainGoal>,
230228
}
231229

232230
#[derive(Clone, Debug, PartialEq, Eq, Hash)]

src/lower/mod.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ impl LowerProgram for Program {
167167
id: info.id,
168168
name: defn.name.str,
169169
parameter_kinds: parameter_kinds,
170-
where_clauses: vec![] // TODO: where clauses on associated types
171170
});
172171
}
173172
}
@@ -448,9 +447,10 @@ impl LowerStructDefn for StructDefn {
448447
.collect()
449448
};
450449

450+
let fields: Result<_> = self.fields.iter().map(|f| f.ty.lower(env)).collect();
451451
let where_clauses = self.lower_where_clauses(env)?;
452452

453-
Ok(ir::StructDatumBound { self_ty, where_clauses })
453+
Ok(ir::StructDatumBound { self_ty, fields: fields?, where_clauses })
454454
})?;
455455

456456
Ok(ir::StructDatum { binders })
@@ -918,11 +918,13 @@ impl ir::StructDatum {
918918
fn to_program_clauses(&self, program: &ir::Program) -> Vec<ir::ProgramClause> {
919919
// Given:
920920
//
921-
// struct Foo<T: Eq> { ... }
921+
// struct Foo<T: Eq> {
922+
// field: Bar
923+
// }
922924
//
923925
// we generate the following clause:
924926
//
925-
// for<?T> WF(Foo<?T>) :- WF(?T), (?T: Eq), WF(?T: Eq).
927+
// for<?T> WF(Foo<?T>) :- WF(?T), WF(Bar), (?T: Eq), WF(?T: Eq).
926928

927929
let wf = ir::ProgramClause {
928930
implication: self.binders.map_ref(|bound_datum| {
@@ -934,14 +936,20 @@ impl ir::StructDatum {
934936
.parameters
935937
.iter()
936938
.filter_map(|pk| pk.as_ref().ty())
937-
.map(|ty| ir::WellFormed::Ty(ty.clone()).cast());
939+
.cloned()
940+
.map(|ty| ir::WellFormed::Ty(ty).cast());
941+
942+
let fields = bound_datum.fields
943+
.iter()
944+
.cloned()
945+
.map(|ty| ir::WellFormed::Ty(ty).cast());
938946

939947
let where_clauses = bound_datum.where_clauses.iter()
940948
.cloned()
941949
.flat_map(|wc| wc.expanded(program))
942950
.map(|wc| wc.cast());
943951

944-
tys.chain(where_clauses).collect()
952+
tys.chain(fields).chain(where_clauses).collect()
945953
}
946954
}
947955
}),
@@ -985,7 +993,8 @@ impl ir::TraitDatum {
985993
let tys = bound.trait_ref.parameters
986994
.iter()
987995
.filter_map(|pk| pk.as_ref().ty())
988-
.map(|ty| ir::WellFormed::Ty(ty.clone()).cast());
996+
.cloned()
997+
.map(|ty| ir::WellFormed::Ty(ty).cast());
989998

990999
tys.chain(where_clauses.iter().cloned().map(|wc| wc.cast())).collect()
9911000
}
@@ -1056,13 +1065,7 @@ impl ir::AssociatedTyDatum {
10561065
binders: binders.clone(),
10571066
value: ir::ProgramClauseImplication {
10581067
consequence: ir::Normalize { projection: projection.clone(), ty }.cast(),
1059-
conditions: self.where_clauses
1060-
.iter()
1061-
.cloned()
1062-
.flat_map(|wc| wc.expanded(program))
1063-
.map(|wc| wc.cast())
1064-
.chain(Some(trait_ref.clone().cast()))
1065-
.collect()
1068+
conditions: vec![trait_ref.clone().cast()],
10661069
}
10671070
},
10681071
fallback_clause: true,

src/solve/test.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,16 @@ fn elaborate_normalize() {
613613
} yields {
614614
"Unique"
615615
}
616+
617+
goal {
618+
forall<T> {
619+
if (T: Item<Out = i32>) {
620+
T: Item
621+
}
622+
}
623+
} yields {
624+
"Unique"
625+
}
616626
}
617627
}
618628

@@ -690,6 +700,47 @@ fn struct_wf() {
690700
}
691701
}
692702

703+
#[test]
704+
fn struct_with_fields_wf() {
705+
test! {
706+
program {
707+
struct Foo { }
708+
709+
struct Bar {
710+
f: Foo
711+
}
712+
713+
trait Clone { }
714+
struct Dummy<T> where T: Clone { }
715+
impl Clone for Foo { }
716+
717+
struct Baz<T> {
718+
f: Dummy<T>
719+
}
720+
}
721+
722+
goal {
723+
WellFormed(Bar)
724+
} yields {
725+
"Unique"
726+
}
727+
728+
// `Bar` does not implement `Clone` so `Dummy<Bar>` is ill-formed
729+
goal {
730+
WellFormed(Baz<Bar>)
731+
} yields {
732+
"No possible solution"
733+
}
734+
735+
// This time `Foo` does implement `Clone`
736+
goal {
737+
WellFormed(Baz<Foo>)
738+
} yields {
739+
"Unique"
740+
}
741+
}
742+
}
743+
693744
#[test]
694745
fn generic_trait() {
695746
test! {

0 commit comments

Comments
 (0)