aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/source_binder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/source_binder.rs')
-rw-r--r--crates/ra_hir/src/source_binder.rs113
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 @@
8use std::sync::Arc; 8use std::sync::Arc;
9 9
10use hir_def::{ 10use 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};
16use hir_expand::{ 20use hir_expand::{
17 name::AsName, AstId, HirFileId, MacroCallId, MacroCallLoc, MacroFileKind, Source, 21 hygiene::Hygiene, name::AsName, AstId, HirFileId, MacroCallId, MacroFileKind, Source,
18}; 22};
19use ra_syntax::{ 23use ra_syntax::{
20 ast::{self, AstNode}, 24 ast::{self, AstNode},
@@ -25,10 +29,12 @@ use ra_syntax::{
25 29
26use crate::{ 30use 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
34fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { 40fn 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
466fn scope_for( 463fn scope_for(