|
| 1 | +use chalk_integration::db::ChalkDatabase; |
| 2 | +use chalk_integration::query::LoweringDatabase; |
| 3 | +use chalk_ir::interner::ChalkIr; |
| 4 | +use chalk_ir::AssocTypeId; |
| 5 | +use chalk_ir::Goal; |
| 6 | +use chalk_ir::ImplId; |
| 7 | +use chalk_ir::InEnvironment; |
| 8 | +use chalk_ir::OpaqueTyId; |
| 9 | +use chalk_ir::Parameter; |
| 10 | +use chalk_ir::ProgramClause; |
| 11 | +use chalk_ir::StructId; |
| 12 | +use chalk_ir::TraitId; |
| 13 | +use chalk_ir::TypeName; |
| 14 | +use chalk_ir::UCanonical; |
| 15 | +use chalk_rust_ir::AssociatedTyDatum; |
| 16 | +use chalk_rust_ir::AssociatedTyValue; |
| 17 | +use chalk_rust_ir::AssociatedTyValueId; |
| 18 | +use chalk_rust_ir::ImplDatum; |
| 19 | +use chalk_rust_ir::OpaqueTyDatum; |
| 20 | +use chalk_rust_ir::StructDatum; |
| 21 | +use chalk_rust_ir::TraitDatum; |
| 22 | +use chalk_rust_ir::WellKnownTrait; |
| 23 | +use chalk_solve::RustIrDatabase; |
| 24 | +use chalk_solve::Solution; |
| 25 | +use chalk_solve::SolverChoice; |
| 26 | +use std::sync::Arc; |
| 27 | + |
| 28 | +#[derive(Debug, Default)] |
| 29 | +struct MockDatabase { |
| 30 | + chalk_db: ChalkDatabase, |
| 31 | + panic: bool, |
| 32 | +} |
| 33 | + |
| 34 | +impl MockDatabase { |
| 35 | + pub fn with(program_text: &str, solver_choice: SolverChoice) -> Self { |
| 36 | + Self { |
| 37 | + chalk_db: ChalkDatabase::with(program_text, solver_choice), |
| 38 | + panic: false, |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + pub fn solve( |
| 43 | + &self, |
| 44 | + goal: &UCanonical<InEnvironment<Goal<ChalkIr>>>, |
| 45 | + ) -> Option<Solution<ChalkIr>> { |
| 46 | + let solver = self.chalk_db.solver(); |
| 47 | + let solution = solver.lock().unwrap().solve(self, goal); |
| 48 | + solution |
| 49 | + } |
| 50 | +} |
| 51 | + |
| 52 | +impl RustIrDatabase<ChalkIr> for MockDatabase { |
| 53 | + fn custom_clauses(&self) -> Vec<ProgramClause<ChalkIr>> { |
| 54 | + if self.panic { |
| 55 | + unimplemented!() |
| 56 | + } else { |
| 57 | + self.chalk_db.custom_clauses() |
| 58 | + } |
| 59 | + } |
| 60 | + |
| 61 | + fn associated_ty_data(&self, ty: AssocTypeId<ChalkIr>) -> Arc<AssociatedTyDatum<ChalkIr>> { |
| 62 | + self.chalk_db.associated_ty_data(ty) |
| 63 | + } |
| 64 | + |
| 65 | + fn trait_datum(&self, id: TraitId<ChalkIr>) -> Arc<TraitDatum<ChalkIr>> { |
| 66 | + self.chalk_db.trait_datum(id) |
| 67 | + } |
| 68 | + |
| 69 | + fn impl_datum(&self, id: ImplId<ChalkIr>) -> Arc<ImplDatum<ChalkIr>> { |
| 70 | + self.chalk_db.impl_datum(id) |
| 71 | + } |
| 72 | + |
| 73 | + fn associated_ty_value( |
| 74 | + &self, |
| 75 | + id: AssociatedTyValueId<ChalkIr>, |
| 76 | + ) -> Arc<AssociatedTyValue<ChalkIr>> { |
| 77 | + self.chalk_db.associated_ty_value(id) |
| 78 | + } |
| 79 | + |
| 80 | + fn opaque_ty_data(&self, id: OpaqueTyId<ChalkIr>) -> Arc<OpaqueTyDatum<ChalkIr>> { |
| 81 | + self.chalk_db.opaque_ty_data(id) |
| 82 | + } |
| 83 | + |
| 84 | + fn struct_datum(&self, id: StructId<ChalkIr>) -> Arc<StructDatum<ChalkIr>> { |
| 85 | + self.chalk_db.struct_datum(id) |
| 86 | + } |
| 87 | + |
| 88 | + fn as_struct_id(&self, type_name: &TypeName<ChalkIr>) -> Option<StructId<ChalkIr>> { |
| 89 | + self.chalk_db.as_struct_id(type_name) |
| 90 | + } |
| 91 | + |
| 92 | + fn impls_for_trait( |
| 93 | + &self, |
| 94 | + trait_id: TraitId<ChalkIr>, |
| 95 | + parameters: &[Parameter<ChalkIr>], |
| 96 | + ) -> Vec<ImplId<ChalkIr>> { |
| 97 | + self.chalk_db.impls_for_trait(trait_id, parameters) |
| 98 | + } |
| 99 | + |
| 100 | + fn local_impls_to_coherence_check(&self, trait_id: TraitId<ChalkIr>) -> Vec<ImplId<ChalkIr>> { |
| 101 | + self.chalk_db.local_impls_to_coherence_check(trait_id) |
| 102 | + } |
| 103 | + |
| 104 | + fn impl_provided_for( |
| 105 | + &self, |
| 106 | + auto_trait_id: TraitId<ChalkIr>, |
| 107 | + struct_id: StructId<ChalkIr>, |
| 108 | + ) -> bool { |
| 109 | + self.chalk_db.impl_provided_for(auto_trait_id, struct_id) |
| 110 | + } |
| 111 | + |
| 112 | + fn well_known_trait_id(&self, well_known_trait: WellKnownTrait) -> Option<TraitId<ChalkIr>> { |
| 113 | + self.chalk_db.well_known_trait_id(well_known_trait) |
| 114 | + } |
| 115 | + |
| 116 | + fn interner(&self) -> &ChalkIr { |
| 117 | + &ChalkIr |
| 118 | + } |
| 119 | +} |
| 120 | + |
| 121 | +#[test] |
| 122 | +fn unwind_safety() { |
| 123 | + use self::MockDatabase; |
| 124 | + use chalk_integration::lowering::LowerGoal; |
| 125 | + use chalk_integration::query::LoweringDatabase; |
| 126 | + use chalk_solve::ext::GoalExt; |
| 127 | + use std::panic; |
| 128 | + |
| 129 | + // lower program |
| 130 | + let mut db = lower_program_with_db! { |
| 131 | + program { |
| 132 | + struct Foo { } |
| 133 | + trait Bar { } |
| 134 | + impl Bar for Foo { } |
| 135 | + } |
| 136 | + database MockDatabase |
| 137 | + }; |
| 138 | + |
| 139 | + let program = db.chalk_db.checked_program().unwrap(); |
| 140 | + |
| 141 | + // lower goal |
| 142 | + let goal = lower_goal! { |
| 143 | + goal { |
| 144 | + Foo: Bar |
| 145 | + } |
| 146 | + program &*program |
| 147 | + }; |
| 148 | + let peeled_goal = goal.into_peeled_goal(db.interner()); |
| 149 | + |
| 150 | + // solve goal but this will panic |
| 151 | + db.panic = true; |
| 152 | + let result = panic::catch_unwind(|| { |
| 153 | + db.solve(&peeled_goal); |
| 154 | + }); |
| 155 | + assert!(result.is_err() == true); |
| 156 | + |
| 157 | + // solve again but without panicking this time |
| 158 | + db.panic = false; |
| 159 | + assert!(db.solve(&peeled_goal).is_some()); |
| 160 | +} |
0 commit comments