aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/traits.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-09-24 22:12:26 +0100
committerGitHub <[email protected]>2019-09-24 22:12:26 +0100
commitc7420ddaaa76741d1eebe393406b38ba5596e54a (patch)
treeff9c2f3c665ef95ebf509dc69ff82d39ec42d176 /crates/ra_hir/src/ty/traits.rs
parent36fb3f53d712a11b7e3fc4bbd92094d1c8f19522 (diff)
parent6a8670665032f6103ca14e38ed9106126b20063d (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.rs44
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;
9use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
10 10
11use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; 11use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
12use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; 12use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait};
13 13
14use self::chalk::{from_chalk, ToChalk}; 14use 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)]
265pub enum FnTrait {
266 FnOnce,
267 FnMut,
268 Fn,
269}
270
271impl 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)]
282pub 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)]
291pub 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}