aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model.rs22
-rw-r--r--crates/ra_hir/src/db.rs9
-rw-r--r--crates/ra_hir/src/diagnostics.rs4
-rw-r--r--crates/ra_hir/src/lib.rs2
-rw-r--r--crates/ra_hir/src/semantics.rs138
-rw-r--r--crates/ra_hir/src/source_analyzer.rs7
6 files changed, 150 insertions, 32 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 27cdabea0..0007d7fa8 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -4,6 +4,7 @@ use std::{iter, sync::Arc};
4use arrayvec::ArrayVec; 4use arrayvec::ArrayVec;
5use either::Either; 5use either::Either;
6use hir_def::{ 6use hir_def::{
7 adt::ReprKind,
7 adt::StructKind, 8 adt::StructKind,
8 adt::VariantData, 9 adt::VariantData,
9 builtin_type::BuiltinType, 10 builtin_type::BuiltinType,
@@ -83,9 +84,9 @@ impl Crate {
83 .collect() 84 .collect()
84 } 85 }
85 86
86 pub fn root_module(self, db: &dyn HirDatabase) -> Option<Module> { 87 pub fn root_module(self, db: &dyn HirDatabase) -> Module {
87 let module_id = db.crate_def_map(self.id).root; 88 let module_id = db.crate_def_map(self.id).root;
88 Some(Module::new(self, module_id)) 89 Module::new(self, module_id)
89 } 90 }
90 91
91 pub fn root_file(self, db: &dyn HirDatabase) -> FileId { 92 pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
@@ -431,6 +432,10 @@ impl Struct {
431 Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id) 432 Type::from_def(db, self.id.lookup(db.upcast()).container.module(db.upcast()).krate, self.id)
432 } 433 }
433 434
435 pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> {
436 db.struct_data(self.id).repr.clone()
437 }
438
434 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { 439 fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
435 db.struct_data(self.id).variant_data.clone() 440 db.struct_data(self.id).variant_data.clone()
436 } 441 }
@@ -1253,6 +1258,19 @@ impl Type {
1253 ) 1258 )
1254 } 1259 }
1255 1260
1261 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
1262 let adt_id = match self.ty.value {
1263 Ty::Apply(ApplicationTy { ctor: TypeCtor::Adt(adt_id), .. }) => adt_id,
1264 _ => return false,
1265 };
1266
1267 let adt = adt_id.into();
1268 match adt {
1269 Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)),
1270 _ => false,
1271 }
1272 }
1273
1256 pub fn is_raw_ptr(&self) -> bool { 1274 pub fn is_raw_ptr(&self) -> bool {
1257 matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. })) 1275 matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::RawPtr(..), .. }))
1258 } 1276 }
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index a2b9f3e35..07333c453 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -13,14 +13,7 @@ pub use hir_expand::db::{
13 AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery, 13 AstDatabase, AstDatabaseStorage, AstIdMapQuery, InternEagerExpansionQuery, InternMacroQuery,
14 MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroQuery, 14 MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroQuery,
15}; 15};
16pub use hir_ty::db::{ 16pub use hir_ty::db::*;
17 AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery,
18 GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase,
19 HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, InferQueryQuery,
20 InherentImplsInCrateQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery,
21 TraitDatumQuery, TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery,
22 ValueTyQuery,
23};
24 17
25#[test] 18#[test]
26fn hir_database_is_object_safe() { 19fn hir_database_is_object_safe() {
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index 266b513dc..363164b9b 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -1,8 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2pub use hir_def::diagnostics::UnresolvedModule; 2pub use hir_def::diagnostics::UnresolvedModule;
3pub use hir_expand::diagnostics::{ 3pub use hir_expand::diagnostics::{Diagnostic, DiagnosticSink, DiagnosticSinkBuilder};
4 AstDiagnostic, Diagnostic, DiagnosticSink, DiagnosticSinkBuilder,
5};
6pub use hir_ty::diagnostics::{ 4pub use hir_ty::diagnostics::{
7 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField, 5 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField,
8}; 6};
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 31f3241c9..34b02c536 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -49,7 +49,7 @@ pub use hir_def::{
49 docs::Documentation, 49 docs::Documentation,
50 nameres::ModuleSource, 50 nameres::ModuleSource,
51 path::{ModPath, Path, PathKind}, 51 path::{ModPath, Path, PathKind},
52 type_ref::Mutability, 52 type_ref::{Mutability, TypeRef},
53}; 53};
54pub use hir_expand::{ 54pub use hir_expand::{
55 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, 55 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc,
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 307b336f2..36b688ccb 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -8,7 +8,7 @@ use hir_def::{
8 resolver::{self, HasResolver, Resolver}, 8 resolver::{self, HasResolver, Resolver},
9 AsMacroCall, FunctionId, TraitId, VariantId, 9 AsMacroCall, FunctionId, TraitId, VariantId,
10}; 10};
11use hir_expand::{diagnostics::AstDiagnostic, hygiene::Hygiene, ExpansionInfo}; 11use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
12use hir_ty::associated_type_shorthand_candidates; 12use hir_ty::associated_type_shorthand_candidates;
13use itertools::Itertools; 13use itertools::Itertools;
14use ra_db::{FileId, FileRange}; 14use ra_db::{FileId, FileRange};
@@ -24,8 +24,9 @@ use crate::{
24 diagnostics::Diagnostic, 24 diagnostics::Diagnostic,
25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, 25 semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
26 source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer}, 26 source_analyzer::{resolve_hir_path, resolve_hir_path_qualifier, SourceAnalyzer},
27 AssocItem, Callable, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, Module, 27 AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef,
28 ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, 28 Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, TypeRef,
29 VariantDef,
29}; 30};
30use resolver::TypeNs; 31use resolver::TypeNs;
31 32
@@ -109,13 +110,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
109 self.imp.parse(file_id) 110 self.imp.parse(file_id)
110 } 111 }
111 112
112 pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST {
113 let file_id = d.source().file_id;
114 let root = self.db.parse_or_expand(file_id).unwrap();
115 self.imp.cache(root, file_id);
116 d.ast(self.db.upcast())
117 }
118
119 pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { 113 pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
120 self.imp.expand(macro_call) 114 self.imp.expand(macro_call)
121 } 115 }
@@ -145,8 +139,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
145 self.imp.original_range(node) 139 self.imp.original_range(node)
146 } 140 }
147 141
148 pub fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { 142 pub fn diagnostics_display_range(&self, diagnostics: &dyn Diagnostic) -> FileRange {
149 self.imp.diagnostics_range(diagnostics) 143 self.imp.diagnostics_display_range(diagnostics)
150 } 144 }
151 145
152 pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ { 146 pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
@@ -228,6 +222,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
228 self.imp.resolve_path(path) 222 self.imp.resolve_path(path)
229 } 223 }
230 224
225 pub fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> {
226 self.imp.resolve_extern_crate(extern_crate)
227 }
228
231 pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> { 229 pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> {
232 self.imp.resolve_variant(record_lit).map(VariantDef::from) 230 self.imp.resolve_variant(record_lit).map(VariantDef::from)
233 } 231 }
@@ -275,6 +273,18 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
275 pub fn assert_contains_node(&self, node: &SyntaxNode) { 273 pub fn assert_contains_node(&self, node: &SyntaxNode) {
276 self.imp.assert_contains_node(node) 274 self.imp.assert_contains_node(node)
277 } 275 }
276
277 pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool {
278 self.imp.is_unsafe_method_call(method_call_expr)
279 }
280
281 pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool {
282 self.imp.is_unsafe_ref_expr(ref_expr)
283 }
284
285 pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool {
286 self.imp.is_unsafe_ident_pat(ident_pat)
287 }
278} 288}
279 289
280impl<'db> SemanticsImpl<'db> { 290impl<'db> SemanticsImpl<'db> {
@@ -372,10 +382,11 @@ impl<'db> SemanticsImpl<'db> {
372 original_range(self.db, node.as_ref()) 382 original_range(self.db, node.as_ref())
373 } 383 }
374 384
375 fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange { 385 fn diagnostics_display_range(&self, diagnostics: &dyn Diagnostic) -> FileRange {
376 let src = diagnostics.source(); 386 let src = diagnostics.display_source();
377 let root = self.db.parse_or_expand(src.file_id).unwrap(); 387 let root = self.db.parse_or_expand(src.file_id).unwrap();
378 let node = src.value.to_node(&root); 388 let node = src.value.to_node(&root);
389 self.cache(root, src.file_id);
379 original_range(self.db, src.with_value(&node)) 390 original_range(self.db, src.with_value(&node))
380 } 391 }
381 392
@@ -443,6 +454,17 @@ impl<'db> SemanticsImpl<'db> {
443 self.analyze(path.syntax()).resolve_path(self.db, path) 454 self.analyze(path.syntax()).resolve_path(self.db, path)
444 } 455 }
445 456
457 fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> {
458 let krate = self.scope(extern_crate.syntax()).krate()?;
459 krate.dependencies(self.db).into_iter().find_map(|dep| {
460 if dep.name == extern_crate.name_ref()?.as_name() {
461 Some(dep.krate)
462 } else {
463 None
464 }
465 })
466 }
467
446 fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> { 468 fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
447 self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit) 469 self.analyze(record_lit.syntax()).resolve_variant(self.db, record_lit)
448 } 470 }
@@ -559,6 +581,90 @@ impl<'db> SemanticsImpl<'db> {
559 }); 581 });
560 InFile::new(file_id, node) 582 InFile::new(file_id, node)
561 } 583 }
584
585 pub fn is_unsafe_method_call(&self, method_call_expr: ast::MethodCallExpr) -> bool {
586 method_call_expr
587 .expr()
588 .and_then(|expr| {
589 let field_expr = if let ast::Expr::FieldExpr(field_expr) = expr {
590 field_expr
591 } else {
592 return None;
593 };
594 let ty = self.type_of_expr(&field_expr.expr()?)?;
595 if !ty.is_packed(self.db) {
596 return None;
597 }
598
599 let func = self.resolve_method_call(&method_call_expr).map(Function::from)?;
600 let is_unsafe = func.has_self_param(self.db)
601 && matches!(func.params(self.db).first(), Some(TypeRef::Reference(..)));
602 Some(is_unsafe)
603 })
604 .unwrap_or(false)
605 }
606
607 pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool {
608 ref_expr
609 .expr()
610 .and_then(|expr| {
611 let field_expr = match expr {
612 ast::Expr::FieldExpr(field_expr) => field_expr,
613 _ => return None,
614 };
615 let expr = field_expr.expr()?;
616 self.type_of_expr(&expr)
617 })
618 // Binding a reference to a packed type is possibly unsafe.
619 .map(|ty| ty.is_packed(self.db))
620 .unwrap_or(false)
621
622 // FIXME This needs layout computation to be correct. It will highlight
623 // more than it should with the current implementation.
624 }
625
626 pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool {
627 if !ident_pat.ref_token().is_some() {
628 return false;
629 }
630
631 ident_pat
632 .syntax()
633 .parent()
634 .and_then(|parent| {
635 // `IdentPat` can live under `RecordPat` directly under `RecordPatField` or
636 // `RecordPatFieldList`. `RecordPatField` also lives under `RecordPatFieldList`,
637 // so this tries to lookup the `IdentPat` anywhere along that structure to the
638 // `RecordPat` so we can get the containing type.
639 let record_pat = ast::RecordPatField::cast(parent.clone())
640 .and_then(|record_pat| record_pat.syntax().parent())
641 .or_else(|| Some(parent.clone()))
642 .and_then(|parent| {
643 ast::RecordPatFieldList::cast(parent)?
644 .syntax()
645 .parent()
646 .and_then(ast::RecordPat::cast)
647 });
648
649 // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if
650 // this is initialized from a `FieldExpr`.
651 if let Some(record_pat) = record_pat {
652 self.type_of_pat(&ast::Pat::RecordPat(record_pat))
653 } else if let Some(let_stmt) = ast::LetStmt::cast(parent) {
654 let field_expr = match let_stmt.initializer()? {
655 ast::Expr::FieldExpr(field_expr) => field_expr,
656 _ => return None,
657 };
658
659 self.type_of_expr(&field_expr.expr()?)
660 } else {
661 None
662 }
663 })
664 // Binding a reference to a packed type is possibly unsafe.
665 .map(|ty| ty.is_packed(self.db))
666 .unwrap_or(false)
667 }
562} 668}
563 669
564pub trait ToDef: AstNode + Clone { 670pub trait ToDef: AstNode + Clone {
@@ -612,6 +718,10 @@ impl<'a> SemanticsScope<'a> {
612 Some(Module { id: self.resolver.module()? }) 718 Some(Module { id: self.resolver.module()? })
613 } 719 }
614 720
721 pub fn krate(&self) -> Option<Crate> {
722 Some(Crate { id: self.resolver.krate()? })
723 }
724
615 /// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type 725 /// Note: `FxHashSet<TraitId>` should be treated as an opaque type, passed into `Type
616 // FIXME: rename to visible_traits to not repeat scope? 726 // FIXME: rename to visible_traits to not repeat scope?
617 pub fn traits_in_scope(&self) -> FxHashSet<TraitId> { 727 pub fn traits_in_scope(&self) -> FxHashSet<TraitId> {
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index d0cb62ef0..d3d62debf 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -265,8 +265,7 @@ impl SourceAnalyzer {
265 } 265 }
266 266
267 // This must be a normal source file rather than macro file. 267 // This must be a normal source file rather than macro file.
268 let hir_path = 268 let hir_path = Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?;
269 crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?;
270 269
271 // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we 270 // Case where path is a qualifier of another path, e.g. foo::bar::Baz where we
272 // trying to resolve foo::bar. 271 // trying to resolve foo::bar.
@@ -451,7 +450,7 @@ fn adjust(
451pub(crate) fn resolve_hir_path( 450pub(crate) fn resolve_hir_path(
452 db: &dyn HirDatabase, 451 db: &dyn HirDatabase,
453 resolver: &Resolver, 452 resolver: &Resolver,
454 path: &crate::Path, 453 path: &Path,
455) -> Option<PathResolution> { 454) -> Option<PathResolution> {
456 let types = 455 let types =
457 resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { 456 resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty {
@@ -512,7 +511,7 @@ pub(crate) fn resolve_hir_path(
512pub(crate) fn resolve_hir_path_qualifier( 511pub(crate) fn resolve_hir_path_qualifier(
513 db: &dyn HirDatabase, 512 db: &dyn HirDatabase,
514 resolver: &Resolver, 513 resolver: &Resolver,
515 path: &crate::Path, 514 path: &Path,
516) -> Option<PathResolution> { 515) -> Option<PathResolution> {
517 let items = resolver 516 let items = resolver
518 .resolve_module_path_in_items(db.upcast(), path.mod_path()) 517 .resolve_module_path_in_items(db.upcast(), path.mod_path())