Skip to content

Commit a640bea

Browse files
committed
Add WF requirements for projection types
1 parent 9d4f4cb commit a640bea

File tree

5 files changed

+140
-52
lines changed

5 files changed

+140
-52
lines changed

src/ir/could_match.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@ impl<T: Zip> CouldMatch<T> for T {
1717
fn zip_tys(&mut self, a: &Ty, b: &Ty) -> Fallible<()> {
1818
let could_match = match (a, b) {
1919
(&Ty::Apply(ref a), &Ty::Apply(ref b)) => {
20-
let names_could_match = match (a.name, b.name) {
21-
(TypeName::ItemId(item_a), TypeName::ItemId(item_b)) => {
22-
item_a == item_b
23-
}
24-
_ => true,
25-
};
20+
let names_could_match = a.name == b.name;
2621

2722
names_could_match
2823
&& a.parameters

src/ir/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,13 @@ impl Ty {
296296
_ => panic!("{:?} is not a projection", self),
297297
}
298298
}
299+
300+
pub fn is_projection(&self) -> bool {
301+
match *self {
302+
Ty::Projection(..) | Ty::UnselectedProjection(..) => true,
303+
_ => false,
304+
}
305+
}
299306
}
300307

301308
/// for<'a...'z> X -- all binders are instantiated at once,

src/lower/mod.rs

Lines changed: 57 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,34 +1407,42 @@ impl ir::AssociatedTyDatum {
14071407
}
14081408
};
14091409

1410+
// Construct an application from the projection. So if we have `<T as Iterator>::Item`,
1411+
// we would produce `(Iterator::Item)<T>`.
1412+
let app = ir::ApplicationTy {
1413+
name: ir::TypeName::AssociatedType(self.id),
1414+
parameters,
1415+
};
1416+
let app_ty = ir::Ty::Apply(app);
1417+
1418+
let mut clauses = vec![];
1419+
14101420
// forall<T> {
14111421
// ProjectionEq(<T as Foo>::Assoc = (Foo::Assoc)<T>) :-
14121422
// T: Foo
14131423
// }
1414-
let fallback_clause = {
1415-
// Construct an application from the projection. So if we have `<T as Iterator>::Item`,
1416-
// we would produce `(Iterator::Item)<T>`.
1417-
let app = ir::ApplicationTy {
1418-
name: ir::TypeName::AssociatedType(self.id),
1419-
parameters,
1420-
};
1421-
let app_ty = ir::Ty::Apply(app);
1422-
1423-
ir::ProgramClause {
1424-
implication: ir::Binders {
1425-
binders: binders.clone(),
1426-
value: ir::ProgramClauseImplication {
1427-
consequence: ir::ProjectionEq {
1428-
projection: projection.clone(),
1429-
ty: app_ty,
1430-
}.cast(),
1431-
conditions: vec![
1432-
trait_ref.clone().cast(),
1433-
],
1434-
},
1424+
clauses.push(ir::ProgramClause {
1425+
implication: ir::Binders {
1426+
binders: binders.clone(),
1427+
value: ir::ProgramClauseImplication {
1428+
consequence: ir::ProjectionEq {
1429+
projection: projection.clone(),
1430+
ty: app_ty.clone(),
1431+
}.cast(),
1432+
conditions: vec![trait_ref.clone().cast()],
14351433
},
1434+
},
1435+
});
1436+
1437+
clauses.push(ir::ProgramClause {
1438+
implication: ir::Binders {
1439+
binders: binders.clone(),
1440+
value: ir::ProgramClauseImplication {
1441+
consequence: ir::WellFormed::Ty(app_ty).cast(),
1442+
conditions: vec![],
1443+
}
14361444
}
1437-
};
1445+
});
14381446

14391447
// add new type parameter U
14401448
let mut binders = binders;
@@ -1448,22 +1456,21 @@ impl ir::AssociatedTyDatum {
14481456
// ProjectionEq(<T as Foo>::Assoc = U) :-
14491457
// Normalize(<T as Foo>::Assoc -> U)
14501458
// }
1451-
let normalize_clause =
1452-
ir::ProgramClause {
1453-
implication: ir::Binders {
1454-
binders: binders.clone(),
1455-
value: ir::ProgramClauseImplication {
1456-
consequence: ir::ProjectionEq {
1457-
projection: projection.clone(),
1458-
ty,
1459-
}.cast(),
1460-
conditions: vec![normalize.clone().cast()],
1461-
},
1459+
clauses.push(ir::ProgramClause {
1460+
implication: ir::Binders {
1461+
binders: binders.clone(),
1462+
value: ir::ProgramClauseImplication {
1463+
consequence: ir::ProjectionEq {
1464+
projection: projection.clone(),
1465+
ty,
1466+
}.cast(),
1467+
conditions: vec![normalize.clone().cast()],
14621468
},
1463-
};
1469+
},
1470+
});
14641471

14651472

1466-
let well_formed_clause = ir::ProgramClause {
1473+
clauses.push(ir::ProgramClause {
14671474
implication: ir::Binders {
14681475
binders: binders.clone(),
14691476
value: ir::ProgramClauseImplication {
@@ -1474,18 +1481,28 @@ impl ir::AssociatedTyDatum {
14741481
],
14751482
}
14761483
}
1477-
};
1484+
});
14781485

1479-
let from_env_clause = ir::ProgramClause {
1486+
clauses.push(ir::ProgramClause {
14801487
implication: ir::Binders {
1481-
binders,
1488+
binders: binders.clone(),
14821489
value: ir::ProgramClauseImplication {
14831490
consequence: ir::FromEnv::TraitRef(trait_ref).cast(),
1491+
conditions: vec![ir::FromEnv::Normalize(normalize.clone()).cast()],
1492+
},
1493+
}
1494+
});
1495+
1496+
clauses.push(ir::ProgramClause {
1497+
implication: ir::Binders {
1498+
binders: binders,
1499+
value: ir::ProgramClauseImplication {
1500+
consequence: normalize.clone().cast(),
14841501
conditions: vec![ir::FromEnv::Normalize(normalize).cast()],
14851502
},
14861503
}
1487-
};
1504+
});
14881505

1489-
vec![fallback_clause, normalize_clause, well_formed_clause, from_env_clause]
1506+
clauses
14901507
}
14911508
}

src/lower/test.rs

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ fn cyclic_traits_error() {
605605
}
606606

607607
#[test]
608-
fn cyclic_wf_requirement() {
608+
fn cyclic_wf_requirements() {
609609
lowering_success! {
610610
program {
611611
trait Foo where <Self as Foo>::Value: Foo {
@@ -694,3 +694,69 @@ fn implied_bounds_on_ty_decl() {
694694
}
695695
}
696696
}
697+
698+
#[test]
699+
fn wf_requiremements_for_projection() {
700+
lowering_error! {
701+
program {
702+
trait Foo {
703+
type Value;
704+
}
705+
706+
trait Iterator {
707+
type Item;
708+
}
709+
710+
impl<T> Foo for T {
711+
type Value = <T as Iterator>::Item;
712+
}
713+
} error_msg {
714+
"trait impl for \"Foo\" does not meet well-formedness requirements"
715+
}
716+
}
717+
718+
lowering_success! {
719+
program {
720+
trait Foo {
721+
type Value;
722+
}
723+
724+
trait Iterator {
725+
type Item;
726+
}
727+
728+
impl<T> Foo for T where T: Iterator {
729+
type Value = <T as Iterator>::Item;
730+
}
731+
}
732+
}
733+
}
734+
735+
#[test]
736+
fn projection_type_in_header() {
737+
lowering_error! {
738+
program {
739+
trait Foo {
740+
type Value;
741+
}
742+
743+
trait Bar { }
744+
745+
impl<T> Bar for <T as Foo>::Value { }
746+
} error_msg {
747+
"trait impl for \"Bar\" does not meet well-formedness requirements"
748+
}
749+
}
750+
751+
lowering_success! {
752+
program {
753+
trait Foo {
754+
type Value;
755+
}
756+
757+
trait Bar { }
758+
759+
impl<T> Bar for <T as Foo>::Value where T: Foo { }
760+
}
761+
}
762+
}

src/lower/wf.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,26 +176,29 @@ impl WfSolver {
176176
.iter()
177177
.filter_map(compute_assoc_ty_goal);
178178

179+
let mut header_input_types = Vec::new();
180+
trait_ref.fold(&mut header_input_types);
181+
let (header_projection_types, header_other_types): (Vec<_>, Vec<_>) =
182+
header_input_types.into_iter()
183+
.partition(|ty| ty.is_projection());
184+
179185
let goals =
180186
input_types.into_iter()
187+
.chain(header_projection_types.into_iter())
181188
.map(|ty| WellFormed::Ty(ty).cast())
182189
.chain(assoc_ty_goals)
183190
.chain(Some(WellFormed::TraitRef(trait_ref.clone())).cast());
184191

185192
let goal = goals.fold1(|goal, leaf| Goal::And(Box::new(goal), Box::new(leaf)))
186193
.expect("at least one goal");
187-
188-
let mut input_types = Vec::new();
189-
trait_ref.fold(&mut input_types);
190-
191194
let hypotheses =
192195
impl_datum.binders
193196
.value
194197
.where_clauses
195198
.iter()
196199
.cloned()
197200
.map(|wc| wc.into_from_env_clause())
198-
.chain(input_types.into_iter().map(|ty| FromEnv::Ty(ty).cast()))
201+
.chain(header_other_types.into_iter().map(|ty| FromEnv::Ty(ty).cast()))
199202
.collect();
200203

201204
let goal = Goal::Implies(hypotheses, Box::new(goal))

0 commit comments

Comments
 (0)