diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-24 22:12:26 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-24 22:12:26 +0100 |
commit | c7420ddaaa76741d1eebe393406b38ba5596e54a (patch) | |
tree | ff9c2f3c665ef95ebf509dc69ff82d39ec42d176 /crates/ra_hir/src/ty/traits.rs | |
parent | 36fb3f53d712a11b7e3fc4bbd92094d1c8f19522 (diff) | |
parent | 6a8670665032f6103ca14e38ed9106126b20063d (diff) |
Merge #1845
1845: Closure types r=flodiebold a=flodiebold
This adds types for closures and makes them implement the `Fn` traits (we don't currently care or try to infer `Fn` vs. `FnMut` vs. `FnOnce`; this would require move analysis, I think).
This requires some changes in Chalk; one is that we need to know the self type when asked for impls, so we can synthesize `Fn` trait impls for closures; but also there's a problem that prevents us from normalizing the closure output type correctly that I _think_ will be fixed on the Chalk side (basically, we ask too early and try to solve `Normalize(<?1 as FnOnce<(u32,)>>::Output => ?0)` -- note the variable in the self type -- and instead of an ambiguous answer, we get back that it can't be solved, so we don't try again. Niko mentioned he's making all goals where the self type is unconstrained flounder, which I think would mean this would be ambiguous).
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/traits.rs')
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index c0c132809..d11dab294 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -9,7 +9,7 @@ use ra_prof::profile; | |||
9 | use rustc_hash::FxHashSet; | 9 | use rustc_hash::FxHashSet; |
10 | 10 | ||
11 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; | 11 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; |
12 | use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; | 12 | use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait}; |
13 | 13 | ||
14 | use self::chalk::{from_chalk, ToChalk}; | 14 | use self::chalk::{from_chalk, ToChalk}; |
15 | 15 | ||
@@ -173,6 +173,14 @@ pub(crate) fn trait_solve_query( | |||
173 | ) -> Option<Solution> { | 173 | ) -> Option<Solution> { |
174 | let _p = profile("trait_solve_query"); | 174 | let _p = profile("trait_solve_query"); |
175 | debug!("trait_solve_query({})", goal.value.value.display(db)); | 175 | debug!("trait_solve_query({})", goal.value.value.display(db)); |
176 | |||
177 | if let Obligation::Projection(pred) = &goal.value.value { | ||
178 | if let Ty::Bound(_) = &pred.projection_ty.parameters[0] { | ||
179 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible | ||
180 | return Some(Solution::Ambig(Guidance::Unknown)); | ||
181 | } | ||
182 | } | ||
183 | |||
176 | let canonical = goal.to_chalk(db).cast(); | 184 | let canonical = goal.to_chalk(db).cast(); |
177 | // We currently don't deal with universes (I think / hope they're not yet | 185 | // We currently don't deal with universes (I think / hope they're not yet |
178 | // relevant for our use cases?) | 186 | // relevant for our use cases?) |
@@ -252,3 +260,37 @@ pub enum Guidance { | |||
252 | /// There's no useful information to feed back to type inference | 260 | /// There's no useful information to feed back to type inference |
253 | Unknown, | 261 | Unknown, |
254 | } | 262 | } |
263 | |||
264 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||
265 | pub enum FnTrait { | ||
266 | FnOnce, | ||
267 | FnMut, | ||
268 | Fn, | ||
269 | } | ||
270 | |||
271 | impl FnTrait { | ||
272 | fn lang_item_name(self) -> &'static str { | ||
273 | match self { | ||
274 | FnTrait::FnOnce => "fn_once", | ||
275 | FnTrait::FnMut => "fn_mut", | ||
276 | FnTrait::Fn => "fn", | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | |||
281 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
282 | pub struct ClosureFnTraitImplData { | ||
283 | def: DefWithBody, | ||
284 | expr: ExprId, | ||
285 | fn_trait: FnTrait, | ||
286 | } | ||
287 | |||
288 | /// An impl. Usually this comes from an impl block, but some built-in types get | ||
289 | /// synthetic impls. | ||
290 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
291 | pub enum Impl { | ||
292 | /// A normal impl from an impl block. | ||
293 | ImplBlock(ImplBlock), | ||
294 | /// Closure types implement the Fn traits synthetically. | ||
295 | ClosureFnTraitImpl(ClosureFnTraitImplData), | ||
296 | } | ||