diff options
author | Seivan Heidari <[email protected]> | 2019-11-28 07:19:14 +0000 |
---|---|---|
committer | Seivan Heidari <[email protected]> | 2019-11-28 07:19:14 +0000 |
commit | 18a0937585b836ec5ed054b9ae48e0156ab6d9ef (patch) | |
tree | 9de2c0267ddcc00df717f90034d0843d751a851b /crates/ra_hir/src/source_binder.rs | |
parent | a7394b44c870f585eacfeb3036a33471aff49ff8 (diff) | |
parent | 484acc8a61d599662ed63a4cbda091d38a982551 (diff) |
Merge branch 'master' of https://github.com/rust-analyzer/rust-analyzer into feature/themes
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 113 |
1 files changed, 55 insertions, 58 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 31390bb7f..76c493f1a 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -8,13 +8,17 @@ | |||
8 | use std::sync::Arc; | 8 | use std::sync::Arc; |
9 | 9 | ||
10 | use hir_def::{ | 10 | use hir_def::{ |
11 | body::{ | ||
12 | scope::{ExprScopes, ScopeId}, | ||
13 | BodySourceMap, | ||
14 | }, | ||
11 | expr::{ExprId, PatId}, | 15 | expr::{ExprId, PatId}, |
12 | path::known, | 16 | path::known, |
13 | resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, | 17 | resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, |
14 | DefWithBodyId, | 18 | AssocItemId, DefWithBodyId, |
15 | }; | 19 | }; |
16 | use hir_expand::{ | 20 | use hir_expand::{ |
17 | name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind, Source, | 21 | hygiene::Hygiene, name::AsName, AstId, HirFileId, MacroCallId, MacroFileKind, Source, |
18 | }; | 22 | }; |
19 | use ra_syntax::{ | 23 | use ra_syntax::{ |
20 | ast::{self, AstNode}, | 24 | ast::{self, AstNode}, |
@@ -25,10 +29,12 @@ use ra_syntax::{ | |||
25 | 29 | ||
26 | use crate::{ | 30 | use crate::{ |
27 | db::HirDatabase, | 31 | db::HirDatabase, |
28 | expr::{BodySourceMap, ExprScopes, ScopeId}, | 32 | ty::{ |
29 | ty::method_resolution::{self, implements_trait}, | 33 | method_resolution::{self, implements_trait}, |
34 | InEnvironment, TraitEnvironment, Ty, | ||
35 | }, | ||
30 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, | 36 | Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, |
31 | GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Ty, TypeAlias, | 37 | GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, |
32 | }; | 38 | }; |
33 | 39 | ||
34 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { | 40 | fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { |
@@ -88,7 +94,7 @@ pub struct SourceAnalyzer { | |||
88 | body_owner: Option<DefWithBody>, | 94 | body_owner: Option<DefWithBody>, |
89 | body_source_map: Option<Arc<BodySourceMap>>, | 95 | body_source_map: Option<Arc<BodySourceMap>>, |
90 | infer: Option<Arc<crate::ty::InferenceResult>>, | 96 | infer: Option<Arc<crate::ty::InferenceResult>>, |
91 | scopes: Option<Arc<crate::expr::ExprScopes>>, | 97 | scopes: Option<Arc<ExprScopes>>, |
92 | } | 98 | } |
93 | 99 | ||
94 | #[derive(Debug, Clone, PartialEq, Eq)] | 100 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -165,7 +171,7 @@ impl SourceAnalyzer { | |||
165 | resolver, | 171 | resolver, |
166 | body_owner: Some(def), | 172 | body_owner: Some(def), |
167 | body_source_map: Some(source_map), | 173 | body_source_map: Some(source_map), |
168 | infer: Some(db.infer(def)), | 174 | infer: Some(db.infer(def.into())), |
169 | scopes: Some(scopes), | 175 | scopes: Some(scopes), |
170 | file_id: node.file_id, | 176 | file_id: node.file_id, |
171 | } | 177 | } |
@@ -195,48 +201,52 @@ impl SourceAnalyzer { | |||
195 | self.body_source_map.as_ref()?.node_pat(src) | 201 | self.body_source_map.as_ref()?.node_pat(src) |
196 | } | 202 | } |
197 | 203 | ||
198 | pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> { | 204 | pub fn type_of(&self, db: &impl HirDatabase, expr: &ast::Expr) -> Option<Type> { |
199 | let expr_id = self.expr_id(expr)?; | 205 | let expr_id = self.expr_id(expr)?; |
200 | Some(self.infer.as_ref()?[expr_id].clone()) | 206 | let ty = self.infer.as_ref()?[expr_id].clone(); |
207 | let environment = TraitEnvironment::lower(db, &self.resolver); | ||
208 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | ||
201 | } | 209 | } |
202 | 210 | ||
203 | pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> { | 211 | pub fn type_of_pat(&self, db: &impl HirDatabase, pat: &ast::Pat) -> Option<Type> { |
204 | let pat_id = self.pat_id(pat)?; | 212 | let pat_id = self.pat_id(pat)?; |
205 | Some(self.infer.as_ref()?[pat_id].clone()) | 213 | let ty = self.infer.as_ref()?[pat_id].clone(); |
214 | let environment = TraitEnvironment::lower(db, &self.resolver); | ||
215 | Some(Type { krate: self.resolver.krate()?, ty: InEnvironment { value: ty, environment } }) | ||
206 | } | 216 | } |
207 | 217 | ||
208 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { | 218 | pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> { |
209 | let expr_id = self.expr_id(&call.clone().into())?; | 219 | let expr_id = self.expr_id(&call.clone().into())?; |
210 | self.infer.as_ref()?.method_resolution(expr_id) | 220 | self.infer.as_ref()?.method_resolution(expr_id).map(Function::from) |
211 | } | 221 | } |
212 | 222 | ||
213 | pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> { | 223 | pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> { |
214 | let expr_id = self.expr_id(&field.clone().into())?; | 224 | let expr_id = self.expr_id(&field.clone().into())?; |
215 | self.infer.as_ref()?.field_resolution(expr_id) | 225 | self.infer.as_ref()?.field_resolution(expr_id).map(|it| it.into()) |
216 | } | 226 | } |
217 | 227 | ||
218 | pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<crate::StructField> { | 228 | pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<crate::StructField> { |
219 | let expr_id = self.expr_id(&field.expr()?)?; | 229 | let expr_id = self.expr_id(&field.expr()?)?; |
220 | self.infer.as_ref()?.record_field_resolution(expr_id) | 230 | self.infer.as_ref()?.record_field_resolution(expr_id).map(|it| it.into()) |
221 | } | 231 | } |
222 | 232 | ||
223 | pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { | 233 | pub fn resolve_record_literal(&self, record_lit: &ast::RecordLit) -> Option<crate::VariantDef> { |
224 | let expr_id = self.expr_id(&record_lit.clone().into())?; | 234 | let expr_id = self.expr_id(&record_lit.clone().into())?; |
225 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id) | 235 | self.infer.as_ref()?.variant_resolution_for_expr(expr_id).map(|it| it.into()) |
226 | } | 236 | } |
227 | 237 | ||
228 | pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> { | 238 | pub fn resolve_record_pattern(&self, record_pat: &ast::RecordPat) -> Option<crate::VariantDef> { |
229 | let pat_id = self.pat_id(&record_pat.clone().into())?; | 239 | let pat_id = self.pat_id(&record_pat.clone().into())?; |
230 | self.infer.as_ref()?.variant_resolution_for_pat(pat_id) | 240 | self.infer.as_ref()?.variant_resolution_for_pat(pat_id).map(|it| it.into()) |
231 | } | 241 | } |
232 | 242 | ||
233 | pub fn resolve_macro_call( | 243 | pub fn resolve_macro_call( |
234 | &self, | 244 | &self, |
235 | db: &impl HirDatabase, | 245 | db: &impl HirDatabase, |
236 | macro_call: &ast::MacroCall, | 246 | macro_call: Source<&ast::MacroCall>, |
237 | ) -> Option<MacroDef> { | 247 | ) -> Option<MacroDef> { |
238 | // This must be a normal source file rather than macro file. | 248 | let hygiene = Hygiene::new(db, macro_call.file_id); |
239 | let path = macro_call.path().and_then(Path::from_ast)?; | 249 | let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &hygiene))?; |
240 | self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into()) | 250 | self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into()) |
241 | } | 251 | } |
242 | 252 | ||
@@ -248,7 +258,7 @@ impl SourceAnalyzer { | |||
248 | let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { | 258 | let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { |
249 | TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), | 259 | TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), |
250 | TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam { | 260 | TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam { |
251 | parent: self.resolver.generic_def().unwrap().into(), | 261 | parent: self.resolver.generic_def().unwrap(), |
252 | idx, | 262 | idx, |
253 | }), | 263 | }), |
254 | TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { | 264 | TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { |
@@ -290,13 +300,13 @@ impl SourceAnalyzer { | |||
290 | if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { | 300 | if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) { |
291 | let expr_id = self.expr_id(&path_expr.into())?; | 301 | let expr_id = self.expr_id(&path_expr.into())?; |
292 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { | 302 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) { |
293 | return Some(PathResolution::AssocItem(assoc)); | 303 | return Some(PathResolution::AssocItem(assoc.into())); |
294 | } | 304 | } |
295 | } | 305 | } |
296 | if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { | 306 | if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) { |
297 | let pat_id = self.pat_id(&path_pat.into())?; | 307 | let pat_id = self.pat_id(&path_pat.into())?; |
298 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { | 308 | if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) { |
299 | return Some(PathResolution::AssocItem(assoc)); | 309 | return Some(PathResolution::AssocItem(assoc.into())); |
300 | } | 310 | } |
301 | } | 311 | } |
302 | // This must be a normal source file rather than macro file. | 312 | // This must be a normal source file rather than macro file. |
@@ -323,7 +333,7 @@ impl SourceAnalyzer { | |||
323 | resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), | 333 | resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), |
324 | resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), | 334 | resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), |
325 | resolver::ScopeDef::GenericParam(idx) => { | 335 | resolver::ScopeDef::GenericParam(idx) => { |
326 | let parent = self.resolver.generic_def().unwrap().into(); | 336 | let parent = self.resolver.generic_def().unwrap(); |
327 | ScopeDef::GenericParam(GenericParam { parent, idx }) | 337 | ScopeDef::GenericParam(GenericParam { parent, idx }) |
328 | } | 338 | } |
329 | resolver::ScopeDef::Local(pat_id) => { | 339 | resolver::ScopeDef::Local(pat_id) => { |
@@ -358,14 +368,14 @@ impl SourceAnalyzer { | |||
358 | pub fn iterate_method_candidates<T>( | 368 | pub fn iterate_method_candidates<T>( |
359 | &self, | 369 | &self, |
360 | db: &impl HirDatabase, | 370 | db: &impl HirDatabase, |
361 | ty: Ty, | 371 | ty: &Type, |
362 | name: Option<&Name>, | 372 | name: Option<&Name>, |
363 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, | 373 | mut callback: impl FnMut(&Ty, Function) -> Option<T>, |
364 | ) -> Option<T> { | 374 | ) -> Option<T> { |
365 | // There should be no inference vars in types passed here | 375 | // There should be no inference vars in types passed here |
366 | // FIXME check that? | 376 | // FIXME check that? |
367 | // FIXME replace Unknown by bound vars here | 377 | // FIXME replace Unknown by bound vars here |
368 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 378 | let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 }; |
369 | method_resolution::iterate_method_candidates( | 379 | method_resolution::iterate_method_candidates( |
370 | &canonical, | 380 | &canonical, |
371 | db, | 381 | db, |
@@ -373,7 +383,7 @@ impl SourceAnalyzer { | |||
373 | name, | 383 | name, |
374 | method_resolution::LookupMode::MethodCall, | 384 | method_resolution::LookupMode::MethodCall, |
375 | |ty, it| match it { | 385 | |ty, it| match it { |
376 | AssocItem::Function(f) => callback(ty, f), | 386 | AssocItemId::FunctionId(f) => callback(ty, f.into()), |
377 | _ => None, | 387 | _ => None, |
378 | }, | 388 | }, |
379 | ) | 389 | ) |
@@ -382,34 +392,37 @@ impl SourceAnalyzer { | |||
382 | pub fn iterate_path_candidates<T>( | 392 | pub fn iterate_path_candidates<T>( |
383 | &self, | 393 | &self, |
384 | db: &impl HirDatabase, | 394 | db: &impl HirDatabase, |
385 | ty: Ty, | 395 | ty: &Type, |
386 | name: Option<&Name>, | 396 | name: Option<&Name>, |
387 | callback: impl FnMut(&Ty, AssocItem) -> Option<T>, | 397 | mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, |
388 | ) -> Option<T> { | 398 | ) -> Option<T> { |
389 | // There should be no inference vars in types passed here | 399 | // There should be no inference vars in types passed here |
390 | // FIXME check that? | 400 | // FIXME check that? |
391 | // FIXME replace Unknown by bound vars here | 401 | // FIXME replace Unknown by bound vars here |
392 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 402 | let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 }; |
393 | method_resolution::iterate_method_candidates( | 403 | method_resolution::iterate_method_candidates( |
394 | &canonical, | 404 | &canonical, |
395 | db, | 405 | db, |
396 | &self.resolver, | 406 | &self.resolver, |
397 | name, | 407 | name, |
398 | method_resolution::LookupMode::Path, | 408 | method_resolution::LookupMode::Path, |
399 | callback, | 409 | |ty, it| callback(ty, it.into()), |
400 | ) | 410 | ) |
401 | } | 411 | } |
402 | 412 | ||
403 | pub fn autoderef<'a>( | 413 | // pub fn autoderef<'a>( |
404 | &'a self, | 414 | // &'a self, |
405 | db: &'a impl HirDatabase, | 415 | // db: &'a impl HirDatabase, |
406 | ty: Ty, | 416 | // ty: Ty, |
407 | ) -> impl Iterator<Item = Ty> + 'a { | 417 | // ) -> impl Iterator<Item = Ty> + 'a { |
408 | // There should be no inference vars in types passed here | 418 | // // There should be no inference vars in types passed here |
409 | // FIXME check that? | 419 | // // FIXME check that? |
410 | let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; | 420 | // let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; |
411 | crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value) | 421 | // let krate = self.resolver.krate(); |
412 | } | 422 | // let environment = TraitEnvironment::lower(db, &self.resolver); |
423 | // let ty = crate::ty::InEnvironment { value: canonical, environment }; | ||
424 | // crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value) | ||
425 | // } | ||
413 | 426 | ||
414 | /// Checks that particular type `ty` implements `std::future::Future`. | 427 | /// Checks that particular type `ty` implements `std::future::Future`. |
415 | /// This function is used in `.await` syntax completion. | 428 | /// This function is used in `.await` syntax completion. |
@@ -435,32 +448,16 @@ impl SourceAnalyzer { | |||
435 | db: &impl HirDatabase, | 448 | db: &impl HirDatabase, |
436 | macro_call: Source<&ast::MacroCall>, | 449 | macro_call: Source<&ast::MacroCall>, |
437 | ) -> Option<Expansion> { | 450 | ) -> Option<Expansion> { |
438 | let def = self.resolve_macro_call(db, macro_call.value)?.id; | 451 | let def = self.resolve_macro_call(db, macro_call)?.id; |
439 | let ast_id = AstId::new( | 452 | let ast_id = AstId::new( |
440 | macro_call.file_id, | 453 | macro_call.file_id, |
441 | db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), | 454 | db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), |
442 | ); | 455 | ); |
443 | let macro_call_loc = MacroCallLoc { def, ast_id }; | ||
444 | Some(Expansion { | 456 | Some(Expansion { |
445 | macro_call_id: db.intern_macro(macro_call_loc), | 457 | macro_call_id: def.as_call_id(db, ast_id), |
446 | macro_file_kind: to_macro_file_kind(macro_call.value), | 458 | macro_file_kind: to_macro_file_kind(macro_call.value), |
447 | }) | 459 | }) |
448 | } | 460 | } |
449 | |||
450 | #[cfg(test)] | ||
451 | pub(crate) fn body_source_map(&self) -> Arc<BodySourceMap> { | ||
452 | self.body_source_map.clone().unwrap() | ||
453 | } | ||
454 | |||
455 | #[cfg(test)] | ||
456 | pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> { | ||
457 | self.infer.clone().unwrap() | ||
458 | } | ||
459 | |||
460 | #[cfg(test)] | ||
461 | pub(crate) fn analyzed_declaration(&self) -> Option<DefWithBody> { | ||
462 | self.body_owner | ||
463 | } | ||
464 | } | 461 | } |
465 | 462 | ||
466 | fn scope_for( | 463 | fn scope_for( |