@@ -3,9 +3,10 @@ use std::collections::BTreeMap;
3
3
use chalk_parse:: ast:: * ;
4
4
use lalrpop_intern:: intern;
5
5
6
- use cast:: Cast ;
6
+ use cast:: { Cast , Caster } ;
7
7
use errors:: * ;
8
8
use ir:: { self , Anonymize , ToParameter } ;
9
+ use itertools:: Itertools ;
9
10
use solve:: SolverChoice ;
10
11
11
12
mod test;
@@ -205,7 +206,7 @@ impl LowerProgram for Program {
205
206
impl_data. insert ( item_id, d. lower_impl ( & empty_env) ?) ;
206
207
}
207
208
Item :: Clause ( ref clause) => {
208
- custom_clauses. push ( clause. lower_clause ( & empty_env) ?) ;
209
+ custom_clauses. extend ( clause. lower_clause ( & empty_env) ?) ;
209
210
}
210
211
}
211
212
}
@@ -412,26 +413,31 @@ trait LowerWhereClauseVec<T> {
412
413
413
414
impl LowerWhereClauseVec < ir:: DomainGoal > for [ WhereClause ] {
414
415
fn lower ( & self , env : & Env ) -> Result < Vec < ir:: DomainGoal > > {
415
- self . iter ( ) . map ( |wc| wc. lower ( env) ) . collect ( )
416
+ self . iter ( ) . flat_map ( |wc| wc. lower ( env) . apply_result ( ) ) . collect ( )
416
417
}
417
418
}
418
419
419
420
impl LowerWhereClauseVec < ir:: QuantifiedDomainGoal > for [ QuantifiedWhereClause ] {
420
421
fn lower ( & self , env : & Env ) -> Result < Vec < ir:: QuantifiedDomainGoal > > {
421
- self . iter ( ) . map ( |wc| wc. lower ( env) ) . collect ( )
422
+ self . iter ( )
423
+ . flat_map ( |wc| match wc. lower ( env) {
424
+ Ok ( v) => v. into_iter ( ) . map ( Ok ) . collect ( ) ,
425
+ Err ( e) => vec ! [ Err ( e) ] ,
426
+ } )
427
+ . collect ( )
422
428
}
423
429
}
424
430
425
431
trait LowerWhereClause < T > {
426
- fn lower ( & self , env : & Env ) -> Result < T > ;
432
+ fn lower ( & self , env : & Env ) -> Result < Vec < T > > ;
427
433
}
428
434
429
435
/// Lowers a where-clause in the context of a clause (i.e. in "negative"
430
436
/// position); this is limited to the kinds of where-clauses users can actually
431
437
/// type in Rust and well-formedness checks.
432
438
impl LowerWhereClause < ir:: DomainGoal > for WhereClause {
433
- fn lower ( & self , env : & Env ) -> Result < ir:: DomainGoal > {
434
- Ok ( match self {
439
+ fn lower ( & self , env : & Env ) -> Result < Vec < ir:: DomainGoal > > {
440
+ let goal = match self {
435
441
WhereClause :: Implemented { trait_ref } => {
436
442
ir:: DomainGoal :: Holds ( ir:: WhereClauseAtom :: Implemented ( trait_ref. lower ( env) ?) )
437
443
}
@@ -478,17 +484,18 @@ impl LowerWhereClause<ir::DomainGoal> for WhereClause {
478
484
target : target. lower ( env) ?
479
485
} )
480
486
}
481
- } )
487
+ } ;
488
+ Ok ( vec ! [ goal] )
482
489
}
483
490
}
484
491
485
492
impl LowerWhereClause < ir:: QuantifiedDomainGoal > for QuantifiedWhereClause {
486
- fn lower ( & self , env : & Env ) -> Result < ir:: QuantifiedDomainGoal > {
493
+ fn lower ( & self , env : & Env ) -> Result < Vec < ir:: QuantifiedDomainGoal > > {
487
494
let parameter_kinds = self . parameter_kinds . iter ( ) . map ( |pk| pk. lower ( ) ) ;
488
495
let binders = env. in_binders ( parameter_kinds, |env| {
489
496
Ok ( self . where_clause . lower ( env) ?)
490
497
} ) ?;
491
- Ok ( binders)
498
+ Ok ( binders. into_iter ( ) . collect ( ) )
492
499
}
493
500
}
494
501
@@ -497,7 +504,7 @@ impl LowerWhereClause<ir::QuantifiedDomainGoal> for QuantifiedWhereClause {
497
504
/// can appear, because it includes all the sorts of things that the compiler
498
505
/// must verify.
499
506
impl LowerWhereClause < ir:: LeafGoal > for WhereClause {
500
- fn lower ( & self , env : & Env ) -> Result < ir:: LeafGoal > {
507
+ fn lower ( & self , env : & Env ) -> Result < Vec < ir:: LeafGoal > > {
501
508
Ok ( match * self {
502
509
WhereClause :: Implemented { .. }
503
510
| WhereClause :: ProjectionEq { .. }
@@ -507,17 +514,17 @@ impl LowerWhereClause<ir::LeafGoal> for WhereClause {
507
514
| WhereClause :: TyFromEnv { .. }
508
515
| WhereClause :: TraitRefFromEnv { .. }
509
516
| WhereClause :: Derefs { .. } => {
510
- let g : ir:: DomainGoal = self . lower ( env) ?;
511
- g . cast ( )
517
+ let goals : Vec < ir:: DomainGoal > = self . lower ( env) ?;
518
+ goals . into_iter ( ) . casted ( ) . collect ( )
512
519
}
513
- WhereClause :: UnifyTys { ref a, ref b } => ir:: EqGoal {
520
+ WhereClause :: UnifyTys { ref a, ref b } => vec ! [ ir:: EqGoal {
514
521
a: ir:: ParameterKind :: Ty ( a. lower( env) ?) ,
515
522
b: ir:: ParameterKind :: Ty ( b. lower( env) ?) ,
516
- } . cast ( ) ,
517
- WhereClause :: UnifyLifetimes { ref a, ref b } => ir:: EqGoal {
523
+ } . cast( ) ] ,
524
+ WhereClause :: UnifyLifetimes { ref a, ref b } => vec ! [ ir:: EqGoal {
518
525
a: ir:: ParameterKind :: Lifetime ( a. lower( env) ?) ,
519
526
b: ir:: ParameterKind :: Lifetime ( b. lower( env) ?) ,
520
- } . cast ( ) ,
527
+ } . cast( ) ] ,
521
528
WhereClause :: TraitInScope { trait_name } => {
522
529
let id = match env. lookup ( trait_name) ? {
523
530
NameLookup :: Type ( id) => id,
@@ -528,7 +535,7 @@ impl LowerWhereClause<ir::LeafGoal> for WhereClause {
528
535
bail ! ( ErrorKind :: NotTrait ( trait_name) ) ;
529
536
}
530
537
531
- ir:: DomainGoal :: InScope ( id) . cast ( )
538
+ vec ! [ ir:: DomainGoal :: InScope ( id) . cast( ) ]
532
539
}
533
540
} )
534
541
}
@@ -831,13 +838,14 @@ impl LowerImpl for Impl {
831
838
}
832
839
833
840
trait LowerClause {
834
- fn lower_clause ( & self , env : & Env ) -> Result < ir:: ProgramClause > ;
841
+ fn lower_clause ( & self , env : & Env ) -> Result < Vec < ir:: ProgramClause > > ;
835
842
}
836
843
837
844
impl LowerClause for Clause {
838
- fn lower_clause ( & self , env : & Env ) -> Result < ir:: ProgramClause > {
839
- let implication = env. in_binders ( self . all_parameters ( ) , |env| {
840
- let consequence: ir:: DomainGoal = self . consequence . lower ( env) ?;
845
+ fn lower_clause ( & self , env : & Env ) -> Result < Vec < ir:: ProgramClause > > {
846
+ let implications = env. in_binders ( self . all_parameters ( ) , |env| {
847
+ let consequences: Vec < ir:: DomainGoal > = self . consequence . lower ( env) ?;
848
+
841
849
let mut conditions: Vec < ir:: Goal > = self . conditions
842
850
. iter ( )
843
851
. map ( |g| g. lower ( env) . map ( |g| * g) )
@@ -848,17 +856,27 @@ impl LowerClause for Clause {
848
856
// therefore reverse.
849
857
conditions. reverse ( ) ;
850
858
851
- Ok ( ir:: ProgramClauseImplication {
852
- consequence,
853
- conditions,
854
- } )
859
+ let implications = consequences
860
+ . into_iter ( )
861
+ . map ( |consequence| ir:: ProgramClauseImplication {
862
+ consequence,
863
+ conditions : conditions. clone ( ) ,
864
+ } )
865
+ . collect :: < Vec < _ > > ( ) ;
866
+ Ok ( implications)
855
867
} ) ?;
856
868
857
- if implication. binders . is_empty ( ) {
858
- Ok ( ir:: ProgramClause :: Implies ( implication. value ) )
859
- } else {
860
- Ok ( ir:: ProgramClause :: ForAll ( implication) )
861
- }
869
+ let clauses = implications
870
+ . into_iter ( )
871
+ . map ( |implication : ir:: Binders < ir:: ProgramClauseImplication > | {
872
+ if implication. binders . is_empty ( ) {
873
+ ir:: ProgramClause :: Implies ( implication. value )
874
+ } else {
875
+ ir:: ProgramClause :: ForAll ( implication)
876
+ }
877
+ } )
878
+ . collect ( ) ;
879
+ Ok ( clauses)
862
880
}
863
881
}
864
882
@@ -968,15 +986,22 @@ impl<'k> LowerGoal<Env<'k>> for Goal {
968
986
// `if (FromEnv(T: Trait)) { ... /* this part is untouched */ ... }`.
969
987
let where_clauses: Result < Vec < _ > > =
970
988
wc. into_iter ( )
971
- . map ( |wc| Ok ( wc. lower_clause ( env) ?. into_from_env_clause ( ) ) )
989
+ . flat_map ( |wc| wc. lower_clause ( env) . apply_result ( ) )
990
+ . map ( |result| result. map ( |wc| wc. into_from_env_clause ( ) ) )
972
991
. collect ( ) ;
973
992
Ok ( Box :: new ( ir:: Goal :: Implies ( where_clauses?, g. lower ( env) ?) ) )
974
993
}
975
994
Goal :: And ( g1, g2) => {
976
995
Ok ( Box :: new ( ir:: Goal :: And ( g1. lower ( env) ?, g2. lower ( env) ?) ) )
977
996
}
978
997
Goal :: Not ( g) => Ok ( Box :: new ( ir:: Goal :: Not ( g. lower ( env) ?) ) ) ,
979
- Goal :: Leaf ( wc) => Ok ( Box :: new ( ir:: Goal :: Leaf ( wc. lower ( env) ?) ) ) ,
998
+ Goal :: Leaf ( wc) => {
999
+ // A where clause can lower to multiple leaf goals; wrap these in Goal::And.
1000
+ let leaves = wc. lower ( env) ?. into_iter ( ) . map ( ir:: Goal :: Leaf ) ;
1001
+ let goal = leaves. fold1 ( |goal, leaf| ir:: Goal :: And ( Box :: new ( goal) , Box :: new ( leaf) ) )
1002
+ . expect ( "at least one goal" ) ;
1003
+ Ok ( Box :: new ( goal) )
1004
+ }
980
1005
}
981
1006
}
982
1007
}
@@ -1006,3 +1031,19 @@ impl LowerQuantifiedGoal for Goal {
1006
1031
Ok ( Box :: new ( ir:: Goal :: Quantified ( quantifier_kind, subgoal) ) )
1007
1032
}
1008
1033
}
1034
+
1035
+ /// Lowers Result<Vec<T>> -> Vec<Result<T>>.
1036
+ trait ApplyResult {
1037
+ type Output ;
1038
+ fn apply_result ( self ) -> Self :: Output ;
1039
+ }
1040
+
1041
+ impl < T > ApplyResult for Result < Vec < T > > {
1042
+ type Output = Vec < Result < T > > ;
1043
+ fn apply_result ( self ) -> Self :: Output {
1044
+ match self {
1045
+ Ok ( v) => v. into_iter ( ) . map ( Ok ) . collect ( ) ,
1046
+ Err ( e) => vec ! [ Err ( e) ] ,
1047
+ }
1048
+ }
1049
+ }
0 commit comments