aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/ty/tests.rs15
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs56
2 files changed, 56 insertions, 15 deletions
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index c3edf42b1..3c55a093f 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2502,6 +2502,21 @@ fn test() { (&S).foo()<|>; }
2502} 2502}
2503 2503
2504#[test] 2504#[test]
2505fn method_resolution_where_clause_for_unknown_trait() {
2506 // The blanket impl shouldn't apply because we can't even resolve UnknownTrait
2507 let t = type_at(
2508 r#"
2509//- /main.rs
2510trait Trait { fn foo(self) -> u128; }
2511struct S;
2512impl<T> Trait for T where T: UnknownTrait {}
2513fn test() { (&S).foo()<|>; }
2514"#,
2515 );
2516 assert_eq!(t, "{unknown}");
2517}
2518
2519#[test]
2505fn method_resolution_where_clause_not_met() { 2520fn method_resolution_where_clause_not_met() {
2506 // The blanket impl shouldn't apply because we can't prove S: Clone 2521 // The blanket impl shouldn't apply because we can't prove S: Clone
2507 let t = type_at( 2522 let t = type_at(
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 2772a0432..787970186 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -15,6 +15,10 @@ use crate::{
15}; 15};
16use super::ChalkContext; 16use super::ChalkContext;
17 17
18/// This represents a trait whose name we could not resolve.
19const UNKNOWN_TRAIT: chalk_ir::TraitId =
20 chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() });
21
18pub(super) trait ToChalk { 22pub(super) trait ToChalk {
19 type Chalk; 23 type Chalk;
20 fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; 24 fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk;
@@ -45,7 +49,10 @@ impl ToChalk for Ty {
45 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), 49 Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"),
46 // FIXME this is clearly incorrect, but probably not too incorrect 50 // FIXME this is clearly incorrect, but probably not too incorrect
47 // and I'm not sure what to actually do with Ty::Unknown 51 // and I'm not sure what to actually do with Ty::Unknown
48 Ty::Unknown => PlaceholderIndex { ui: UniverseIndex::ROOT, idx: 0 }.to_ty(), 52 // maybe an alternative would be `for<T> T`? (meaningless in rust, but expressible in chalk's Ty)
53 Ty::Unknown => {
54 PlaceholderIndex { ui: UniverseIndex::ROOT, idx: usize::max_value() }.to_ty()
55 }
49 } 56 }
50 } 57 }
51 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { 58 fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self {
@@ -154,7 +161,13 @@ impl ToChalk for GenericPredicate {
154 GenericPredicate::Implemented(trait_ref) => { 161 GenericPredicate::Implemented(trait_ref) => {
155 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) 162 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0)
156 } 163 }
157 GenericPredicate::Error => panic!("Trying to pass errored where clause to Chalk"), 164 GenericPredicate::Error => {
165 let impossible_trait_ref = chalk_ir::TraitRef {
166 trait_id: UNKNOWN_TRAIT,
167 parameters: vec![Ty::Unknown.to_chalk(db).cast()],
168 };
169 make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0)
170 }
158 } 171 }
159 } 172 }
160 173
@@ -178,19 +191,13 @@ fn convert_where_clauses(
178 db: &impl HirDatabase, 191 db: &impl HirDatabase,
179 def: GenericDef, 192 def: GenericDef,
180 substs: &Substs, 193 substs: &Substs,
181) -> (Vec<chalk_ir::QuantifiedWhereClause>, bool) { 194) -> Vec<chalk_ir::QuantifiedWhereClause> {
182 let generic_predicates = db.generic_predicates(def); 195 let generic_predicates = db.generic_predicates(def);
183 let mut result = Vec::with_capacity(generic_predicates.len()); 196 let mut result = Vec::with_capacity(generic_predicates.len());
184 let mut has_error = false;
185 for pred in generic_predicates.iter() { 197 for pred in generic_predicates.iter() {
186 // FIXME: it would probably be nicer if we could just convert errored predicates to a where clause that is never true... 198 result.push(pred.clone().subst(substs).to_chalk(db));
187 if pred.is_error() {
188 has_error = true;
189 } else {
190 result.push(pred.clone().subst(substs).to_chalk(db));
191 }
192 } 199 }
193 (result, has_error) 200 result
194} 201}
195 202
196impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> 203impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB>
@@ -202,6 +209,23 @@ where
202 } 209 }
203 fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { 210 fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> {
204 debug!("trait_datum {:?}", trait_id); 211 debug!("trait_datum {:?}", trait_id);
212 if trait_id == UNKNOWN_TRAIT {
213 let trait_datum_bound = chalk_rust_ir::TraitDatumBound {
214 trait_ref: chalk_ir::TraitRef {
215 trait_id: UNKNOWN_TRAIT,
216 parameters: vec![chalk_ir::Ty::BoundVar(0).cast()],
217 },
218 associated_ty_ids: Vec::new(),
219 where_clauses: Vec::new(),
220 flags: chalk_rust_ir::TraitFlags {
221 auto: false,
222 marker: false,
223 upstream: true,
224 fundamental: false,
225 },
226 };
227 return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1) });
228 }
205 let trait_: Trait = from_chalk(self.db, trait_id); 229 let trait_: Trait = from_chalk(self.db, trait_id);
206 let generic_params = trait_.generic_params(self.db); 230 let generic_params = trait_.generic_params(self.db);
207 let bound_vars = Substs::bound_vars(&generic_params); 231 let bound_vars = Substs::bound_vars(&generic_params);
@@ -213,7 +237,7 @@ where
213 upstream: trait_.module(self.db).krate(self.db) != Some(self.krate), 237 upstream: trait_.module(self.db).krate(self.db) != Some(self.krate),
214 fundamental: false, 238 fundamental: false,
215 }; 239 };
216 let (where_clauses, _) = convert_where_clauses(self.db, trait_.into(), &bound_vars); 240 let where_clauses = convert_where_clauses(self.db, trait_.into(), &bound_vars);
217 let associated_ty_ids = Vec::new(); // FIXME add associated tys 241 let associated_ty_ids = Vec::new(); // FIXME add associated tys
218 let trait_datum_bound = 242 let trait_datum_bound =
219 chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids }; 243 chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids };
@@ -241,7 +265,7 @@ where
241 TypeCtor::Adt(adt) => { 265 TypeCtor::Adt(adt) => {
242 let generic_params = adt.generic_params(self.db); 266 let generic_params = adt.generic_params(self.db);
243 let bound_vars = Substs::bound_vars(&generic_params); 267 let bound_vars = Substs::bound_vars(&generic_params);
244 let (where_clauses, _) = convert_where_clauses(self.db, adt.into(), &bound_vars); 268 let where_clauses = convert_where_clauses(self.db, adt.into(), &bound_vars);
245 ( 269 (
246 generic_params.count_params_including_parent(), 270 generic_params.count_params_including_parent(),
247 where_clauses, 271 where_clauses,
@@ -281,8 +305,7 @@ where
281 } else { 305 } else {
282 chalk_rust_ir::ImplType::External 306 chalk_rust_ir::ImplType::External
283 }; 307 };
284 let (where_clauses, where_clause_error) = 308 let where_clauses = convert_where_clauses(self.db, impl_block.into(), &bound_vars);
285 convert_where_clauses(self.db, impl_block.into(), &bound_vars);
286 let impl_datum_bound = chalk_rust_ir::ImplDatumBound { 309 let impl_datum_bound = chalk_rust_ir::ImplDatumBound {
287 // FIXME handle negative impls (impl !Sync for Foo) 310 // FIXME handle negative impls (impl !Sync for Foo)
288 trait_ref: chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref.to_chalk(self.db)), 311 trait_ref: chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref.to_chalk(self.db)),
@@ -295,6 +318,9 @@ where
295 } 318 }
296 fn impls_for_trait(&self, trait_id: chalk_ir::TraitId) -> Vec<ImplId> { 319 fn impls_for_trait(&self, trait_id: chalk_ir::TraitId) -> Vec<ImplId> {
297 debug!("impls_for_trait {:?}", trait_id); 320 debug!("impls_for_trait {:?}", trait_id);
321 if trait_id == UNKNOWN_TRAIT {
322 return Vec::new();
323 }
298 let trait_ = from_chalk(self.db, trait_id); 324 let trait_ = from_chalk(self.db, trait_id);
299 self.db 325 self.db
300 .impls_for_trait(self.krate, trait_) 326 .impls_for_trait(self.krate, trait_)