diff options
Diffstat (limited to 'crates')
206 files changed, 9717 insertions, 6391 deletions
diff --git a/crates/base_db/src/fixture.rs b/crates/base_db/src/fixture.rs index 8d4641355..0132565e4 100644 --- a/crates/base_db/src/fixture.rs +++ b/crates/base_db/src/fixture.rs | |||
@@ -1,62 +1,4 @@ | |||
1 | //! Fixtures are strings containing rust source code with optional metadata. | 1 | //! A set of high-level utility fixture methods to use in tests. |
2 | //! A fixture without metadata is parsed into a single source file. | ||
3 | //! Use this to test functionality local to one file. | ||
4 | //! | ||
5 | //! Simple Example: | ||
6 | //! ``` | ||
7 | //! r#" | ||
8 | //! fn main() { | ||
9 | //! println!("Hello World") | ||
10 | //! } | ||
11 | //! "# | ||
12 | //! ``` | ||
13 | //! | ||
14 | //! Metadata can be added to a fixture after a `//-` comment. | ||
15 | //! The basic form is specifying filenames, | ||
16 | //! which is also how to define multiple files in a single test fixture | ||
17 | //! | ||
18 | //! Example using two files in the same crate: | ||
19 | //! ``` | ||
20 | //! " | ||
21 | //! //- /main.rs | ||
22 | //! mod foo; | ||
23 | //! fn main() { | ||
24 | //! foo::bar(); | ||
25 | //! } | ||
26 | //! | ||
27 | //! //- /foo.rs | ||
28 | //! pub fn bar() {} | ||
29 | //! " | ||
30 | //! ``` | ||
31 | //! | ||
32 | //! Example using two crates with one file each, with one crate depending on the other: | ||
33 | //! ``` | ||
34 | //! r#" | ||
35 | //! //- /main.rs crate:a deps:b | ||
36 | //! fn main() { | ||
37 | //! b::foo(); | ||
38 | //! } | ||
39 | //! //- /lib.rs crate:b | ||
40 | //! pub fn b() { | ||
41 | //! println!("Hello World") | ||
42 | //! } | ||
43 | //! "# | ||
44 | //! ``` | ||
45 | //! | ||
46 | //! Metadata allows specifying all settings and variables | ||
47 | //! that are available in a real rust project: | ||
48 | //! - crate names via `crate:cratename` | ||
49 | //! - dependencies via `deps:dep1,dep2` | ||
50 | //! - configuration settings via `cfg:dbg=false,opt_level=2` | ||
51 | //! - environment variables via `env:PATH=/bin,RUST_LOG=debug` | ||
52 | //! | ||
53 | //! Example using all available metadata: | ||
54 | //! ``` | ||
55 | //! " | ||
56 | //! //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo | ||
57 | //! fn insert_source_code_here() {} | ||
58 | //! " | ||
59 | //! ``` | ||
60 | use std::{mem, str::FromStr, sync::Arc}; | 2 | use std::{mem, str::FromStr, sync::Arc}; |
61 | 3 | ||
62 | use cfg::CfgOptions; | 4 | use cfg::CfgOptions; |
@@ -93,7 +35,7 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static { | |||
93 | fn with_position(ra_fixture: &str) -> (Self, FilePosition) { | 35 | fn with_position(ra_fixture: &str) -> (Self, FilePosition) { |
94 | let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture); | 36 | let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture); |
95 | let offset = match range_or_offset { | 37 | let offset = match range_or_offset { |
96 | RangeOrOffset::Range(_) => panic!(), | 38 | RangeOrOffset::Range(_) => panic!("Expected a cursor position, got a range instead"), |
97 | RangeOrOffset::Offset(it) => it, | 39 | RangeOrOffset::Offset(it) => it, |
98 | }; | 40 | }; |
99 | (db, FilePosition { file_id, offset }) | 41 | (db, FilePosition { file_id, offset }) |
@@ -103,7 +45,7 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static { | |||
103 | let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture); | 45 | let (db, file_id, range_or_offset) = Self::with_range_or_offset(ra_fixture); |
104 | let range = match range_or_offset { | 46 | let range = match range_or_offset { |
105 | RangeOrOffset::Range(it) => it, | 47 | RangeOrOffset::Range(it) => it, |
106 | RangeOrOffset::Offset(_) => panic!(), | 48 | RangeOrOffset::Offset(_) => panic!("Expected a cursor range, got a position instead"), |
107 | }; | 49 | }; |
108 | (db, FileRange { file_id, range }) | 50 | (db, FileRange { file_id, range }) |
109 | } | 51 | } |
@@ -112,7 +54,9 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static { | |||
112 | let fixture = ChangeFixture::parse(ra_fixture); | 54 | let fixture = ChangeFixture::parse(ra_fixture); |
113 | let mut db = Self::default(); | 55 | let mut db = Self::default(); |
114 | fixture.change.apply(&mut db); | 56 | fixture.change.apply(&mut db); |
115 | let (file_id, range_or_offset) = fixture.file_position.unwrap(); | 57 | let (file_id, range_or_offset) = fixture |
58 | .file_position | ||
59 | .expect("Could not find file position in fixture. Did you forget to add an `$0`?"); | ||
116 | (db, file_id, range_or_offset) | 60 | (db, file_id, range_or_offset) |
117 | } | 61 | } |
118 | 62 | ||
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs index 5f77a0b1f..980a0ed98 100644 --- a/crates/base_db/src/lib.rs +++ b/crates/base_db/src/lib.rs | |||
@@ -59,6 +59,8 @@ pub trait CheckCanceled { | |||
59 | Self: Sized + panic::RefUnwindSafe, | 59 | Self: Sized + panic::RefUnwindSafe, |
60 | F: FnOnce(&Self) -> T + panic::UnwindSafe, | 60 | F: FnOnce(&Self) -> T + panic::UnwindSafe, |
61 | { | 61 | { |
62 | // Uncomment to debug missing cancellations. | ||
63 | // let _span = profile::heartbeat_span(); | ||
62 | panic::catch_unwind(|| f(self)).map_err(|err| match err.downcast::<Canceled>() { | 64 | panic::catch_unwind(|| f(self)).map_err(|err| match err.downcast::<Canceled>() { |
63 | Ok(canceled) => *canceled, | 65 | Ok(canceled) => *canceled, |
64 | Err(payload) => panic::resume_unwind(payload), | 66 | Err(payload) => panic::resume_unwind(payload), |
@@ -68,6 +70,7 @@ pub trait CheckCanceled { | |||
68 | 70 | ||
69 | impl<T: salsa::Database> CheckCanceled for T { | 71 | impl<T: salsa::Database> CheckCanceled for T { |
70 | fn check_canceled(&self) { | 72 | fn check_canceled(&self) { |
73 | // profile::heartbeat(); | ||
71 | if self.salsa_runtime().is_current_revision_canceled() { | 74 | if self.salsa_runtime().is_current_revision_canceled() { |
72 | Canceled::throw() | 75 | Canceled::throw() |
73 | } | 76 | } |
diff --git a/crates/cfg/src/tests.rs b/crates/cfg/src/tests.rs index bd0f9ec48..d8736c893 100644 --- a/crates/cfg/src/tests.rs +++ b/crates/cfg/src/tests.rs | |||
@@ -8,7 +8,7 @@ fn assert_parse_result(input: &str, expected: CfgExpr) { | |||
8 | let (tt, _) = { | 8 | let (tt, _) = { |
9 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 9 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
10 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 10 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
11 | ast_to_token_tree(&tt).unwrap() | 11 | ast_to_token_tree(&tt) |
12 | }; | 12 | }; |
13 | let cfg = CfgExpr::parse(&tt); | 13 | let cfg = CfgExpr::parse(&tt); |
14 | assert_eq!(cfg, expected); | 14 | assert_eq!(cfg, expected); |
@@ -18,7 +18,7 @@ fn check_dnf(input: &str, expect: Expect) { | |||
18 | let (tt, _) = { | 18 | let (tt, _) = { |
19 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 19 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
20 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 20 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
21 | ast_to_token_tree(&tt).unwrap() | 21 | ast_to_token_tree(&tt) |
22 | }; | 22 | }; |
23 | let cfg = CfgExpr::parse(&tt); | 23 | let cfg = CfgExpr::parse(&tt); |
24 | let actual = format!("#![cfg({})]", DnfExpr::new(cfg)); | 24 | let actual = format!("#![cfg({})]", DnfExpr::new(cfg)); |
@@ -29,7 +29,7 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) { | |||
29 | let (tt, _) = { | 29 | let (tt, _) = { |
30 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 30 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
31 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 31 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
32 | ast_to_token_tree(&tt).unwrap() | 32 | ast_to_token_tree(&tt) |
33 | }; | 33 | }; |
34 | let cfg = CfgExpr::parse(&tt); | 34 | let cfg = CfgExpr::parse(&tt); |
35 | let dnf = DnfExpr::new(cfg); | 35 | let dnf = DnfExpr::new(cfg); |
@@ -42,7 +42,7 @@ fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) { | |||
42 | let (tt, _) = { | 42 | let (tt, _) = { |
43 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 43 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
44 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 44 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
45 | ast_to_token_tree(&tt).unwrap() | 45 | ast_to_token_tree(&tt) |
46 | }; | 46 | }; |
47 | let cfg = CfgExpr::parse(&tt); | 47 | let cfg = CfgExpr::parse(&tt); |
48 | let dnf = DnfExpr::new(cfg); | 48 | let dnf = DnfExpr::new(cfg); |
diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml index 2ef5bcbc9..9e329656f 100644 --- a/crates/hir/Cargo.toml +++ b/crates/hir/Cargo.toml | |||
@@ -13,7 +13,7 @@ doctest = false | |||
13 | log = "0.4.8" | 13 | log = "0.4.8" |
14 | rustc-hash = "1.1.0" | 14 | rustc-hash = "1.1.0" |
15 | either = "1.5.3" | 15 | either = "1.5.3" |
16 | arrayvec = "0.6" | 16 | arrayvec = "0.7" |
17 | itertools = "0.10.0" | 17 | itertools = "0.10.0" |
18 | smallvec = "1.4.0" | 18 | smallvec = "1.4.0" |
19 | 19 | ||
diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs index 1902a8d16..df5758342 100644 --- a/crates/hir/src/db.rs +++ b/crates/hir/src/db.rs | |||
@@ -1,14 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | pub use hir_def::db::{ | 3 | pub use hir_def::db::*; |
4 | AttrsQuery, BlockDefMapQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, | ||
5 | CrateDefMapQueryQuery, CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery, | ||
6 | ExprScopesQuery, FileItemTreeQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, | ||
7 | ImportMapQuery, InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery, | ||
8 | InternFunctionQuery, InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery, | ||
9 | InternTypeAliasQuery, InternUnionQuery, LangItemQuery, StaticDataQuery, StructDataQuery, | ||
10 | TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, | ||
11 | }; | ||
12 | pub use hir_expand::db::{ | 4 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery, | 5 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery, |
14 | InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery, | 6 | InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery, |
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 97a78ca25..01a4d205f 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs | |||
@@ -9,33 +9,33 @@ use hir_ty::display::{ | |||
9 | write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, | 9 | write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError, |
10 | HirFormatter, | 10 | HirFormatter, |
11 | }; | 11 | }; |
12 | use hir_ty::Interner; | ||
12 | use syntax::ast::{self, NameOwner}; | 13 | use syntax::ast::{self, NameOwner}; |
13 | 14 | ||
14 | use crate::{ | 15 | use crate::{ |
15 | Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam, | 16 | Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam, |
16 | Module, Static, Struct, Substitution, Trait, Type, TypeAlias, TypeParam, Union, Variant, | 17 | Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union, Variant, |
17 | }; | 18 | }; |
18 | 19 | ||
19 | impl HirDisplay for Function { | 20 | impl HirDisplay for Function { |
20 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 21 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
21 | let data = f.db.function_data(self.id); | 22 | let data = f.db.function_data(self.id); |
22 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | 23 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; |
23 | let qual = &data.qualifier; | 24 | if data.is_default() { |
24 | if qual.is_default { | ||
25 | write!(f, "default ")?; | 25 | write!(f, "default ")?; |
26 | } | 26 | } |
27 | if qual.is_const { | 27 | if data.is_const() { |
28 | write!(f, "const ")?; | 28 | write!(f, "const ")?; |
29 | } | 29 | } |
30 | if qual.is_async { | 30 | if data.is_async() { |
31 | write!(f, "async ")?; | 31 | write!(f, "async ")?; |
32 | } | 32 | } |
33 | if qual.is_unsafe { | 33 | if data.is_unsafe() { |
34 | write!(f, "unsafe ")?; | 34 | write!(f, "unsafe ")?; |
35 | } | 35 | } |
36 | if let Some(abi) = &qual.abi { | 36 | if let Some(abi) = &data.abi { |
37 | // FIXME: String escape? | 37 | // FIXME: String escape? |
38 | write!(f, "extern \"{}\" ", abi)?; | 38 | write!(f, "extern \"{}\" ", &**abi)?; |
39 | } | 39 | } |
40 | write!(f, "fn {}", data.name)?; | 40 | write!(f, "fn {}", data.name)?; |
41 | 41 | ||
@@ -68,7 +68,7 @@ impl HirDisplay for Function { | |||
68 | write!(f, ", ")?; | 68 | write!(f, ", ")?; |
69 | } else { | 69 | } else { |
70 | first = false; | 70 | first = false; |
71 | if data.has_self_param { | 71 | if data.has_self_param() { |
72 | write_self_param(type_ref, f)?; | 72 | write_self_param(type_ref, f)?; |
73 | continue; | 73 | continue; |
74 | } | 74 | } |
@@ -88,10 +88,10 @@ impl HirDisplay for Function { | |||
88 | // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns. | 88 | // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns. |
89 | // Use ugly pattern match to strip the Future trait. | 89 | // Use ugly pattern match to strip the Future trait. |
90 | // Better way? | 90 | // Better way? |
91 | let ret_type = if !qual.is_async { | 91 | let ret_type = if !data.is_async() { |
92 | &data.ret_type | 92 | &data.ret_type |
93 | } else { | 93 | } else { |
94 | match &data.ret_type { | 94 | match &*data.ret_type { |
95 | TypeRef::ImplTrait(bounds) => match &bounds[0] { | 95 | TypeRef::ImplTrait(bounds) => match &bounds[0] { |
96 | TypeBound::Path(path) => { | 96 | TypeBound::Path(path) => { |
97 | path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings | 97 | path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings |
@@ -235,8 +235,9 @@ impl HirDisplay for TypeParam { | |||
235 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 235 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
236 | write!(f, "{}", self.name(f.db))?; | 236 | write!(f, "{}", self.name(f.db))?; |
237 | let bounds = f.db.generic_predicates_for_param(self.id); | 237 | let bounds = f.db.generic_predicates_for_param(self.id); |
238 | let substs = Substitution::type_params(f.db, self.id.parent); | 238 | let substs = TyBuilder::type_params_subst(f.db, self.id.parent); |
239 | let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>(); | 239 | let predicates = |
240 | bounds.iter().cloned().map(|b| b.substitute(&Interner, &substs)).collect::<Vec<_>>(); | ||
240 | if !(predicates.is_empty() || f.omit_verbose_types()) { | 241 | if !(predicates.is_empty() || f.omit_verbose_types()) { |
241 | write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; | 242 | write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; |
242 | } | 243 | } |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4ee08ef21..0acfa582a 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -44,6 +44,7 @@ use hir_def::{ | |||
44 | per_ns::PerNs, | 44 | per_ns::PerNs, |
45 | resolver::{HasResolver, Resolver}, | 45 | resolver::{HasResolver, Resolver}, |
46 | src::HasSource as _, | 46 | src::HasSource as _, |
47 | type_ref::TraitRef, | ||
47 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, | 48 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, |
48 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, | 49 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, |
49 | LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, | 50 | LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, |
@@ -52,13 +53,14 @@ use hir_def::{ | |||
52 | use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; | 53 | use hir_expand::{diagnostics::DiagnosticSink, name::name, MacroDefKind}; |
53 | use hir_ty::{ | 54 | use hir_ty::{ |
54 | autoderef, could_unify, | 55 | autoderef, could_unify, |
55 | method_resolution::{self, TyFingerprint}, | 56 | method_resolution::{self, def_crates, TyFingerprint}, |
56 | primitive::UintTy, | 57 | primitive::UintTy, |
57 | to_assoc_type_id, | 58 | subst_prefix, |
58 | traits::{FnTrait, Solution, SolutionVariables}, | 59 | traits::FnTrait, |
59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, | 60 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, |
60 | DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, | 61 | DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, Substitution, |
61 | Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause, | 62 | TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind, |
63 | WhereClause, | ||
62 | }; | 64 | }; |
63 | use itertools::Itertools; | 65 | use itertools::Itertools; |
64 | use rustc_hash::FxHashSet; | 66 | use rustc_hash::FxHashSet; |
@@ -514,8 +516,8 @@ impl Field { | |||
514 | VariantDef::Union(it) => it.id.into(), | 516 | VariantDef::Union(it) => it.id.into(), |
515 | VariantDef::Variant(it) => it.parent.id.into(), | 517 | VariantDef::Variant(it) => it.parent.id.into(), |
516 | }; | 518 | }; |
517 | let substs = Substitution::type_params(db, generic_def_id); | 519 | let substs = TyBuilder::type_params_subst(db, generic_def_id); |
518 | let ty = db.field_types(var_id)[self.id].clone().subst(&substs); | 520 | let ty = db.field_types(var_id)[self.id].clone().substitute(&Interner, &substs); |
519 | Type::new(db, self.parent.module(db).id.krate(), var_id, ty) | 521 | Type::new(db, self.parent.module(db).id.krate(), var_id, ty) |
520 | } | 522 | } |
521 | 523 | ||
@@ -701,7 +703,7 @@ impl_from!(Struct, Union, Enum for Adt); | |||
701 | impl Adt { | 703 | impl Adt { |
702 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { | 704 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { |
703 | let subst = db.generic_defaults(self.into()); | 705 | let subst = db.generic_defaults(self.into()); |
704 | subst.iter().any(|ty| ty.value.is_unknown()) | 706 | subst.iter().any(|ty| ty.skip_binders().is_unknown()) |
705 | } | 707 | } |
706 | 708 | ||
707 | /// Turns this ADT into a type. Any type parameters of the ADT will be | 709 | /// Turns this ADT into a type. Any type parameters of the ADT will be |
@@ -831,7 +833,7 @@ impl Function { | |||
831 | } | 833 | } |
832 | 834 | ||
833 | pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { | 835 | pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { |
834 | if !db.function_data(self.id).has_self_param { | 836 | if !db.function_data(self.id).has_self_param() { |
835 | return None; | 837 | return None; |
836 | } | 838 | } |
837 | Some(SelfParam { func: self.id }) | 839 | Some(SelfParam { func: self.id }) |
@@ -863,7 +865,7 @@ impl Function { | |||
863 | } | 865 | } |
864 | 866 | ||
865 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { | 867 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { |
866 | db.function_data(self.id).qualifier.is_unsafe | 868 | db.function_data(self.id).is_unsafe() |
867 | } | 869 | } |
868 | 870 | ||
869 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 871 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { |
@@ -877,7 +879,7 @@ impl Function { | |||
877 | /// | 879 | /// |
878 | /// This is false in the case of required (not provided) trait methods. | 880 | /// This is false in the case of required (not provided) trait methods. |
879 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { | 881 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { |
880 | db.function_data(self.id).has_body | 882 | db.function_data(self.id).has_body() |
881 | } | 883 | } |
882 | 884 | ||
883 | /// A textual representation of the HIR of this function for debugging purposes. | 885 | /// A textual representation of the HIR of this function for debugging purposes. |
@@ -956,7 +958,7 @@ impl SelfParam { | |||
956 | func_data | 958 | func_data |
957 | .params | 959 | .params |
958 | .first() | 960 | .first() |
959 | .map(|param| match *param { | 961 | .map(|param| match &**param { |
960 | TypeRef::Reference(.., mutability) => match mutability { | 962 | TypeRef::Reference(.., mutability) => match mutability { |
961 | hir_def::type_ref::Mutability::Shared => Access::Shared, | 963 | hir_def::type_ref::Mutability::Shared => Access::Shared, |
962 | hir_def::type_ref::Mutability::Mut => Access::Exclusive, | 964 | hir_def::type_ref::Mutability::Mut => Access::Exclusive, |
@@ -1010,7 +1012,7 @@ impl Const { | |||
1010 | } | 1012 | } |
1011 | 1013 | ||
1012 | pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef { | 1014 | pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef { |
1013 | db.const_data(self.id).type_ref.clone() | 1015 | db.const_data(self.id).type_ref.as_ref().clone() |
1014 | } | 1016 | } |
1015 | } | 1017 | } |
1016 | 1018 | ||
@@ -1088,7 +1090,7 @@ pub struct TypeAlias { | |||
1088 | impl TypeAlias { | 1090 | impl TypeAlias { |
1089 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { | 1091 | pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool { |
1090 | let subst = db.generic_defaults(self.id.into()); | 1092 | let subst = db.generic_defaults(self.id.into()); |
1091 | subst.iter().any(|ty| ty.value.is_unknown()) | 1093 | subst.iter().any(|ty| ty.skip_binders().is_unknown()) |
1092 | } | 1094 | } |
1093 | 1095 | ||
1094 | pub fn module(self, db: &dyn HirDatabase) -> Module { | 1096 | pub fn module(self, db: &dyn HirDatabase) -> Module { |
@@ -1100,7 +1102,7 @@ impl TypeAlias { | |||
1100 | } | 1102 | } |
1101 | 1103 | ||
1102 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1104 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
1103 | db.type_alias_data(self.id).type_ref.clone() | 1105 | db.type_alias_data(self.id).type_ref.as_deref().cloned() |
1104 | } | 1106 | } |
1105 | 1107 | ||
1106 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | 1108 | pub fn ty(self, db: &dyn HirDatabase) -> Type { |
@@ -1128,7 +1130,7 @@ pub struct BuiltinType { | |||
1128 | impl BuiltinType { | 1130 | impl BuiltinType { |
1129 | pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { | 1131 | pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { |
1130 | let resolver = module.id.resolver(db.upcast()); | 1132 | let resolver = module.id.resolver(db.upcast()); |
1131 | Type::new_with_resolver(db, &resolver, Ty::builtin(self.inner)) | 1133 | Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner)) |
1132 | .expect("crate not present in resolver") | 1134 | .expect("crate not present in resolver") |
1133 | } | 1135 | } |
1134 | 1136 | ||
@@ -1501,8 +1503,8 @@ impl TypeParam { | |||
1501 | let resolver = self.id.parent.resolver(db.upcast()); | 1503 | let resolver = self.id.parent.resolver(db.upcast()); |
1502 | let krate = self.id.parent.module(db.upcast()).krate(); | 1504 | let krate = self.id.parent.module(db.upcast()).krate(); |
1503 | let ty = params.get(local_idx)?.clone(); | 1505 | let ty = params.get(local_idx)?.clone(); |
1504 | let subst = Substitution::type_params(db, self.id.parent); | 1506 | let subst = TyBuilder::type_params_subst(db, self.id.parent); |
1505 | let ty = ty.subst(&subst.prefix(local_idx)); | 1507 | let ty = ty.substitute(&Interner, &subst_prefix(&subst, local_idx)); |
1506 | Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) | 1508 | Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) |
1507 | } | 1509 | } |
1508 | } | 1510 | } |
@@ -1567,22 +1569,35 @@ impl Impl { | |||
1567 | } | 1569 | } |
1568 | 1570 | ||
1569 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { | 1571 | pub fn all_for_type(db: &dyn HirDatabase, Type { krate, ty, .. }: Type) -> Vec<Impl> { |
1570 | let def_crates = match ty.def_crates(db, krate) { | 1572 | let def_crates = match def_crates(db, &ty, krate) { |
1571 | Some(def_crates) => def_crates, | 1573 | Some(def_crates) => def_crates, |
1572 | None => return Vec::new(), | 1574 | None => return Vec::new(), |
1573 | }; | 1575 | }; |
1574 | 1576 | ||
1575 | let filter = |impl_def: &Impl| { | 1577 | let filter = |impl_def: &Impl| { |
1576 | let target_ty = impl_def.target_ty(db); | 1578 | let self_ty = impl_def.self_ty(db); |
1577 | let rref = target_ty.remove_ref(); | 1579 | let rref = self_ty.remove_ref(); |
1578 | ty.equals_ctor(rref.as_ref().map_or(&target_ty.ty, |it| &it.ty)) | 1580 | ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty)) |
1581 | }; | ||
1582 | |||
1583 | let fp = TyFingerprint::for_inherent_impl(&ty); | ||
1584 | let fp = if let Some(fp) = fp { | ||
1585 | fp | ||
1586 | } else { | ||
1587 | return Vec::new(); | ||
1579 | }; | 1588 | }; |
1580 | 1589 | ||
1581 | let mut all = Vec::new(); | 1590 | let mut all = Vec::new(); |
1582 | def_crates.iter().for_each(|&id| { | 1591 | def_crates.iter().for_each(|&id| { |
1583 | all.extend(db.inherent_impls_in_crate(id).all_impls().map(Self::from).filter(filter)) | 1592 | all.extend( |
1593 | db.inherent_impls_in_crate(id) | ||
1594 | .for_self_ty(&ty) | ||
1595 | .into_iter() | ||
1596 | .cloned() | ||
1597 | .map(Self::from) | ||
1598 | .filter(filter), | ||
1599 | ) | ||
1584 | }); | 1600 | }); |
1585 | let fp = TyFingerprint::for_impl(&ty); | ||
1586 | for id in def_crates | 1601 | for id in def_crates |
1587 | .iter() | 1602 | .iter() |
1588 | .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) | 1603 | .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db)) |
@@ -1590,13 +1605,12 @@ impl Impl { | |||
1590 | .chain(def_crates.iter().copied()) | 1605 | .chain(def_crates.iter().copied()) |
1591 | .unique() | 1606 | .unique() |
1592 | { | 1607 | { |
1593 | match fp { | 1608 | all.extend( |
1594 | Some(fp) => all.extend( | 1609 | db.trait_impls_in_crate(id) |
1595 | db.trait_impls_in_crate(id).for_self_ty(fp).map(Self::from).filter(filter), | 1610 | .for_self_ty_without_blanket_impls(fp) |
1596 | ), | 1611 | .map(Self::from) |
1597 | None => all | 1612 | .filter(filter), |
1598 | .extend(db.trait_impls_in_crate(id).all_impls().map(Self::from).filter(filter)), | 1613 | ); |
1599 | } | ||
1600 | } | 1614 | } |
1601 | all | 1615 | all |
1602 | } | 1616 | } |
@@ -1613,16 +1627,16 @@ impl Impl { | |||
1613 | 1627 | ||
1614 | // FIXME: the return type is wrong. This should be a hir version of | 1628 | // FIXME: the return type is wrong. This should be a hir version of |
1615 | // `TraitRef` (ie, resolved `TypeRef`). | 1629 | // `TraitRef` (ie, resolved `TypeRef`). |
1616 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1630 | pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> { |
1617 | db.impl_data(self.id).target_trait.clone() | 1631 | db.impl_data(self.id).target_trait.as_deref().cloned() |
1618 | } | 1632 | } |
1619 | 1633 | ||
1620 | pub fn target_ty(self, db: &dyn HirDatabase) -> Type { | 1634 | pub fn self_ty(self, db: &dyn HirDatabase) -> Type { |
1621 | let impl_data = db.impl_data(self.id); | 1635 | let impl_data = db.impl_data(self.id); |
1622 | let resolver = self.id.resolver(db.upcast()); | 1636 | let resolver = self.id.resolver(db.upcast()); |
1623 | let krate = self.id.lookup(db.upcast()).container.krate(); | 1637 | let krate = self.id.lookup(db.upcast()).container.krate(); |
1624 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | 1638 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); |
1625 | let ty = ctx.lower_ty(&impl_data.target_type); | 1639 | let ty = ctx.lower_ty(&impl_data.self_ty); |
1626 | Type::new_with_resolver_inner(db, krate, &resolver, ty) | 1640 | Type::new_with_resolver_inner(db, krate, &resolver, ty) |
1627 | } | 1641 | } |
1628 | 1642 | ||
@@ -1702,30 +1716,29 @@ impl Type { | |||
1702 | fn from_def( | 1716 | fn from_def( |
1703 | db: &dyn HirDatabase, | 1717 | db: &dyn HirDatabase, |
1704 | krate: CrateId, | 1718 | krate: CrateId, |
1705 | def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, | 1719 | def: impl HasResolver + Into<TyDefId>, |
1706 | ) -> Type { | 1720 | ) -> Type { |
1707 | let substs = Substitution::build_for_def(db, def).fill_with_unknown().build(); | 1721 | let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build(); |
1708 | let ty = db.ty(def.into()).subst(&substs); | ||
1709 | Type::new(db, krate, def, ty) | 1722 | Type::new(db, krate, def, ty) |
1710 | } | 1723 | } |
1711 | 1724 | ||
1712 | pub fn is_unit(&self) -> bool { | 1725 | pub fn is_unit(&self) -> bool { |
1713 | matches!(self.ty.interned(&Interner), TyKind::Tuple(0, ..)) | 1726 | matches!(self.ty.kind(&Interner), TyKind::Tuple(0, ..)) |
1714 | } | 1727 | } |
1715 | pub fn is_bool(&self) -> bool { | 1728 | pub fn is_bool(&self) -> bool { |
1716 | matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Bool)) | 1729 | matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Bool)) |
1717 | } | 1730 | } |
1718 | 1731 | ||
1719 | pub fn is_mutable_reference(&self) -> bool { | 1732 | pub fn is_mutable_reference(&self) -> bool { |
1720 | matches!(self.ty.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) | 1733 | matches!(self.ty.kind(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) |
1721 | } | 1734 | } |
1722 | 1735 | ||
1723 | pub fn is_usize(&self) -> bool { | 1736 | pub fn is_usize(&self) -> bool { |
1724 | matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) | 1737 | matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) |
1725 | } | 1738 | } |
1726 | 1739 | ||
1727 | pub fn remove_ref(&self) -> Option<Type> { | 1740 | pub fn remove_ref(&self) -> Option<Type> { |
1728 | match &self.ty.interned(&Interner) { | 1741 | match &self.ty.kind(&Interner) { |
1729 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), | 1742 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), |
1730 | _ => None, | 1743 | _ => None, |
1731 | } | 1744 | } |
@@ -1784,16 +1797,13 @@ impl Type { | |||
1784 | } | 1797 | } |
1785 | 1798 | ||
1786 | pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { | 1799 | pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { |
1787 | let trait_ref = hir_ty::TraitRef { | 1800 | let trait_ref = TyBuilder::trait_ref(db, trait_.id) |
1788 | trait_id: hir_ty::to_chalk_trait_id(trait_.id), | 1801 | .push(self.ty.clone()) |
1789 | substitution: Substitution::build_for_def(db, trait_.id) | 1802 | .fill(args.iter().map(|t| t.ty.clone())) |
1790 | .push(self.ty.clone()) | 1803 | .build(); |
1791 | .fill(args.iter().map(|t| t.ty.clone())) | ||
1792 | .build(), | ||
1793 | }; | ||
1794 | 1804 | ||
1795 | let goal = Canonical { | 1805 | let goal = Canonical { |
1796 | value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), | 1806 | value: hir_ty::InEnvironment::new(&self.env.env, trait_ref.cast(&Interner)), |
1797 | binders: CanonicalVarKinds::empty(&Interner), | 1807 | binders: CanonicalVarKinds::empty(&Interner), |
1798 | }; | 1808 | }; |
1799 | 1809 | ||
@@ -1803,22 +1813,18 @@ impl Type { | |||
1803 | pub fn normalize_trait_assoc_type( | 1813 | pub fn normalize_trait_assoc_type( |
1804 | &self, | 1814 | &self, |
1805 | db: &dyn HirDatabase, | 1815 | db: &dyn HirDatabase, |
1806 | trait_: Trait, | ||
1807 | args: &[Type], | 1816 | args: &[Type], |
1808 | alias: TypeAlias, | 1817 | alias: TypeAlias, |
1809 | ) -> Option<Type> { | 1818 | ) -> Option<Type> { |
1810 | let subst = Substitution::build_for_def(db, trait_.id) | 1819 | let projection = TyBuilder::assoc_type_projection(db, alias.id) |
1811 | .push(self.ty.clone()) | 1820 | .push(self.ty.clone()) |
1812 | .fill(args.iter().map(|t| t.ty.clone())) | 1821 | .fill(args.iter().map(|t| t.ty.clone())) |
1813 | .build(); | 1822 | .build(); |
1814 | let goal = Canonical::new( | 1823 | let goal = hir_ty::make_canonical( |
1815 | InEnvironment::new( | 1824 | InEnvironment::new( |
1816 | self.env.env.clone(), | 1825 | &self.env.env, |
1817 | AliasEq { | 1826 | AliasEq { |
1818 | alias: AliasTy::Projection(ProjectionTy { | 1827 | alias: AliasTy::Projection(projection), |
1819 | associated_ty_id: to_assoc_type_id(alias.id), | ||
1820 | substitution: subst, | ||
1821 | }), | ||
1822 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) | 1828 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) |
1823 | .intern(&Interner), | 1829 | .intern(&Interner), |
1824 | } | 1830 | } |
@@ -1828,9 +1834,12 @@ impl Type { | |||
1828 | ); | 1834 | ); |
1829 | 1835 | ||
1830 | match db.trait_solve(self.krate, goal)? { | 1836 | match db.trait_solve(self.krate, goal)? { |
1831 | Solution::Unique(SolutionVariables(subst)) => { | 1837 | Solution::Unique(s) => s |
1832 | subst.value.first().map(|ty| self.derived(ty.clone())) | 1838 | .value |
1833 | } | 1839 | .subst |
1840 | .as_slice(&Interner) | ||
1841 | .first() | ||
1842 | .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())), | ||
1834 | Solution::Ambig(_) => None, | 1843 | Solution::Ambig(_) => None, |
1835 | } | 1844 | } |
1836 | } | 1845 | } |
@@ -1852,15 +1861,15 @@ impl Type { | |||
1852 | } | 1861 | } |
1853 | 1862 | ||
1854 | pub fn is_closure(&self) -> bool { | 1863 | pub fn is_closure(&self) -> bool { |
1855 | matches!(&self.ty.interned(&Interner), TyKind::Closure { .. }) | 1864 | matches!(&self.ty.kind(&Interner), TyKind::Closure { .. }) |
1856 | } | 1865 | } |
1857 | 1866 | ||
1858 | pub fn is_fn(&self) -> bool { | 1867 | pub fn is_fn(&self) -> bool { |
1859 | matches!(&self.ty.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) | 1868 | matches!(&self.ty.kind(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) |
1860 | } | 1869 | } |
1861 | 1870 | ||
1862 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | 1871 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { |
1863 | let adt_id = match self.ty.interned(&Interner) { | 1872 | let adt_id = match self.ty.kind(&Interner) { |
1864 | &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, | 1873 | &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, |
1865 | _ => return false, | 1874 | _ => return false, |
1866 | }; | 1875 | }; |
@@ -1873,27 +1882,30 @@ impl Type { | |||
1873 | } | 1882 | } |
1874 | 1883 | ||
1875 | pub fn is_raw_ptr(&self) -> bool { | 1884 | pub fn is_raw_ptr(&self) -> bool { |
1876 | matches!(&self.ty.interned(&Interner), TyKind::Raw(..)) | 1885 | matches!(&self.ty.kind(&Interner), TyKind::Raw(..)) |
1877 | } | 1886 | } |
1878 | 1887 | ||
1879 | pub fn contains_unknown(&self) -> bool { | 1888 | pub fn contains_unknown(&self) -> bool { |
1880 | return go(&self.ty); | 1889 | return go(&self.ty); |
1881 | 1890 | ||
1882 | fn go(ty: &Ty) -> bool { | 1891 | fn go(ty: &Ty) -> bool { |
1883 | match ty.interned(&Interner) { | 1892 | match ty.kind(&Interner) { |
1884 | TyKind::Unknown => true, | 1893 | TyKind::Error => true, |
1885 | 1894 | ||
1886 | TyKind::Adt(_, substs) | 1895 | TyKind::Adt(_, substs) |
1887 | | TyKind::AssociatedType(_, substs) | 1896 | | TyKind::AssociatedType(_, substs) |
1888 | | TyKind::Tuple(_, substs) | 1897 | | TyKind::Tuple(_, substs) |
1889 | | TyKind::OpaqueType(_, substs) | 1898 | | TyKind::OpaqueType(_, substs) |
1890 | | TyKind::FnDef(_, substs) | 1899 | | TyKind::FnDef(_, substs) |
1891 | | TyKind::Closure(_, substs) => substs.iter().any(go), | 1900 | | TyKind::Closure(_, substs) => { |
1892 | 1901 | substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go) | |
1893 | TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => { | ||
1894 | go(ty) | ||
1895 | } | 1902 | } |
1896 | 1903 | ||
1904 | TyKind::Array(ty, _) | ||
1905 | | TyKind::Slice(ty) | ||
1906 | | TyKind::Raw(_, ty) | ||
1907 | | TyKind::Ref(_, _, ty) => go(ty), | ||
1908 | |||
1897 | TyKind::Scalar(_) | 1909 | TyKind::Scalar(_) |
1898 | | TyKind::Str | 1910 | | TyKind::Str |
1899 | | TyKind::Never | 1911 | | TyKind::Never |
@@ -1903,13 +1915,15 @@ impl Type { | |||
1903 | | TyKind::Dyn(_) | 1915 | | TyKind::Dyn(_) |
1904 | | TyKind::Function(_) | 1916 | | TyKind::Function(_) |
1905 | | TyKind::Alias(_) | 1917 | | TyKind::Alias(_) |
1906 | | TyKind::ForeignType(_) => false, | 1918 | | TyKind::Foreign(_) |
1919 | | TyKind::Generator(..) | ||
1920 | | TyKind::GeneratorWitness(..) => false, | ||
1907 | } | 1921 | } |
1908 | } | 1922 | } |
1909 | } | 1923 | } |
1910 | 1924 | ||
1911 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { | 1925 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { |
1912 | let (variant_id, substs) = match self.ty.interned(&Interner) { | 1926 | let (variant_id, substs) = match self.ty.kind(&Interner) { |
1913 | &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), | 1927 | &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), |
1914 | &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), | 1928 | &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), |
1915 | _ => return Vec::new(), | 1929 | _ => return Vec::new(), |
@@ -1919,15 +1933,18 @@ impl Type { | |||
1919 | .iter() | 1933 | .iter() |
1920 | .map(|(local_id, ty)| { | 1934 | .map(|(local_id, ty)| { |
1921 | let def = Field { parent: variant_id.into(), id: local_id }; | 1935 | let def = Field { parent: variant_id.into(), id: local_id }; |
1922 | let ty = ty.clone().subst(substs); | 1936 | let ty = ty.clone().substitute(&Interner, substs); |
1923 | (def, self.derived(ty)) | 1937 | (def, self.derived(ty)) |
1924 | }) | 1938 | }) |
1925 | .collect() | 1939 | .collect() |
1926 | } | 1940 | } |
1927 | 1941 | ||
1928 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { | 1942 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { |
1929 | if let TyKind::Tuple(_, substs) = &self.ty.interned(&Interner) { | 1943 | if let TyKind::Tuple(_, substs) = &self.ty.kind(&Interner) { |
1930 | substs.iter().map(|ty| self.derived(ty.clone())).collect() | 1944 | substs |
1945 | .iter(&Interner) | ||
1946 | .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())) | ||
1947 | .collect() | ||
1931 | } else { | 1948 | } else { |
1932 | Vec::new() | 1949 | Vec::new() |
1933 | } | 1950 | } |
@@ -1953,7 +1970,7 @@ impl Type { | |||
1953 | krate: Crate, | 1970 | krate: Crate, |
1954 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 1971 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
1955 | ) -> Option<T> { | 1972 | ) -> Option<T> { |
1956 | for krate in self.ty.def_crates(db, krate.id)? { | 1973 | for krate in def_crates(db, &self.ty, krate.id)? { |
1957 | let impls = db.inherent_impls_in_crate(krate); | 1974 | let impls = db.inherent_impls_in_crate(krate); |
1958 | 1975 | ||
1959 | for impl_def in impls.for_self_ty(&self.ty) { | 1976 | for impl_def in impls.for_self_ty(&self.ty) { |
@@ -1970,10 +1987,11 @@ impl Type { | |||
1970 | pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { | 1987 | pub fn type_parameters(&self) -> impl Iterator<Item = Type> + '_ { |
1971 | self.ty | 1988 | self.ty |
1972 | .strip_references() | 1989 | .strip_references() |
1973 | .substs() | 1990 | .as_adt() |
1974 | .into_iter() | 1991 | .into_iter() |
1975 | .flat_map(|substs| substs.iter()) | 1992 | .flat_map(|(_, substs)| substs.iter(&Interner)) |
1976 | .map(move |ty| self.derived(ty.clone())) | 1993 | .filter_map(|arg| arg.ty(&Interner).cloned()) |
1994 | .map(move |ty| self.derived(ty)) | ||
1977 | } | 1995 | } |
1978 | 1996 | ||
1979 | pub fn iterate_method_candidates<T>( | 1997 | pub fn iterate_method_candidates<T>( |
@@ -2048,6 +2066,18 @@ impl Type { | |||
2048 | self.ty.dyn_trait().map(Into::into) | 2066 | self.ty.dyn_trait().map(Into::into) |
2049 | } | 2067 | } |
2050 | 2068 | ||
2069 | /// If a type can be represented as `dyn Trait`, returns all traits accessible via this type, | ||
2070 | /// or an empty iterator otherwise. | ||
2071 | pub fn applicable_inherent_traits<'a>( | ||
2072 | &'a self, | ||
2073 | db: &'a dyn HirDatabase, | ||
2074 | ) -> impl Iterator<Item = Trait> + 'a { | ||
2075 | self.autoderef(db) | ||
2076 | .filter_map(|derefed_type| derefed_type.ty.dyn_trait()) | ||
2077 | .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id)) | ||
2078 | .map(Trait::from) | ||
2079 | } | ||
2080 | |||
2051 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { | 2081 | pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> { |
2052 | self.ty.impl_trait_bounds(db).map(|it| { | 2082 | self.ty.impl_trait_bounds(db).map(|it| { |
2053 | it.into_iter() | 2083 | it.into_iter() |
@@ -2079,7 +2109,7 @@ impl Type { | |||
2079 | substs: &Substitution, | 2109 | substs: &Substitution, |
2080 | cb: &mut impl FnMut(Type), | 2110 | cb: &mut impl FnMut(Type), |
2081 | ) { | 2111 | ) { |
2082 | for ty in substs.iter() { | 2112 | for ty in substs.iter(&Interner).filter_map(|a| a.ty(&Interner)) { |
2083 | walk_type(db, &type_.derived(ty.clone()), cb); | 2113 | walk_type(db, &type_.derived(ty.clone()), cb); |
2084 | } | 2114 | } |
2085 | } | 2115 | } |
@@ -2095,7 +2125,12 @@ impl Type { | |||
2095 | WhereClause::Implemented(trait_ref) => { | 2125 | WhereClause::Implemented(trait_ref) => { |
2096 | cb(type_.clone()); | 2126 | cb(type_.clone()); |
2097 | // skip the self type. it's likely the type we just got the bounds from | 2127 | // skip the self type. it's likely the type we just got the bounds from |
2098 | for ty in trait_ref.substitution.iter().skip(1) { | 2128 | for ty in trait_ref |
2129 | .substitution | ||
2130 | .iter(&Interner) | ||
2131 | .skip(1) | ||
2132 | .filter_map(|a| a.ty(&Interner)) | ||
2133 | { | ||
2099 | walk_type(db, &type_.derived(ty.clone()), cb); | 2134 | walk_type(db, &type_.derived(ty.clone()), cb); |
2100 | } | 2135 | } |
2101 | } | 2136 | } |
@@ -2106,19 +2141,23 @@ impl Type { | |||
2106 | 2141 | ||
2107 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { | 2142 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { |
2108 | let ty = type_.ty.strip_references(); | 2143 | let ty = type_.ty.strip_references(); |
2109 | match ty.interned(&Interner) { | 2144 | match ty.kind(&Interner) { |
2110 | TyKind::Adt(..) => { | 2145 | TyKind::Adt(_, substs) => { |
2111 | cb(type_.derived(ty.clone())); | 2146 | cb(type_.derived(ty.clone())); |
2147 | walk_substs(db, type_, &substs, cb); | ||
2112 | } | 2148 | } |
2113 | TyKind::AssociatedType(..) => { | 2149 | TyKind::AssociatedType(_, substs) => { |
2114 | if let Some(_) = ty.associated_type_parent_trait(db) { | 2150 | if let Some(_) = ty.associated_type_parent_trait(db) { |
2115 | cb(type_.derived(ty.clone())); | 2151 | cb(type_.derived(ty.clone())); |
2116 | } | 2152 | } |
2153 | walk_substs(db, type_, &substs, cb); | ||
2117 | } | 2154 | } |
2118 | TyKind::OpaqueType(..) => { | 2155 | TyKind::OpaqueType(_, subst) => { |
2119 | if let Some(bounds) = ty.impl_trait_bounds(db) { | 2156 | if let Some(bounds) = ty.impl_trait_bounds(db) { |
2120 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); | 2157 | walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); |
2121 | } | 2158 | } |
2159 | |||
2160 | walk_substs(db, type_, subst, cb); | ||
2122 | } | 2161 | } |
2123 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { | 2162 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { |
2124 | if let Some(bounds) = ty.impl_trait_bounds(db) { | 2163 | if let Some(bounds) = ty.impl_trait_bounds(db) { |
@@ -2141,15 +2180,24 @@ impl Type { | |||
2141 | ); | 2180 | ); |
2142 | } | 2181 | } |
2143 | 2182 | ||
2144 | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) | TyKind::Array(ty) | TyKind::Slice(ty) => { | 2183 | TyKind::Ref(_, _, ty) |
2184 | | TyKind::Raw(_, ty) | ||
2185 | | TyKind::Array(ty, _) | ||
2186 | | TyKind::Slice(ty) => { | ||
2145 | walk_type(db, &type_.derived(ty.clone()), cb); | 2187 | walk_type(db, &type_.derived(ty.clone()), cb); |
2146 | } | 2188 | } |
2147 | 2189 | ||
2190 | TyKind::FnDef(_, substs) | ||
2191 | | TyKind::Tuple(_, substs) | ||
2192 | | TyKind::Closure(.., substs) => { | ||
2193 | walk_substs(db, type_, &substs, cb); | ||
2194 | } | ||
2195 | TyKind::Function(hir_ty::FnPointer { substitution, .. }) => { | ||
2196 | walk_substs(db, type_, &substitution.0, cb); | ||
2197 | } | ||
2198 | |||
2148 | _ => {} | 2199 | _ => {} |
2149 | } | 2200 | } |
2150 | if let Some(substs) = ty.substs() { | ||
2151 | walk_substs(db, type_, &substs, cb); | ||
2152 | } | ||
2153 | } | 2201 | } |
2154 | 2202 | ||
2155 | walk_type(db, self, &mut cb); | 2203 | walk_type(db, self, &mut cb); |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index d3caeef4e..7955bf0b5 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -76,9 +76,11 @@ impl PathResolution { | |||
76 | pub fn assoc_type_shorthand_candidates<R>( | 76 | pub fn assoc_type_shorthand_candidates<R>( |
77 | &self, | 77 | &self, |
78 | db: &dyn HirDatabase, | 78 | db: &dyn HirDatabase, |
79 | mut cb: impl FnMut(TypeAlias) -> Option<R>, | 79 | mut cb: impl FnMut(&Name, TypeAlias) -> Option<R>, |
80 | ) -> Option<R> { | 80 | ) -> Option<R> { |
81 | associated_type_shorthand_candidates(db, self.in_type_ns()?, |_, _, id| cb(id.into())) | 81 | associated_type_shorthand_candidates(db, self.in_type_ns()?, |name, _, id| { |
82 | cb(name, id.into()) | ||
83 | }) | ||
82 | } | 84 | } |
83 | } | 85 | } |
84 | 86 | ||
@@ -492,9 +494,9 @@ impl<'db> SemanticsImpl<'db> { | |||
492 | fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> { | 494 | fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> { |
493 | // FIXME: this erases Substs | 495 | // FIXME: this erases Substs |
494 | let func = self.resolve_method_call(call)?; | 496 | let func = self.resolve_method_call(call)?; |
495 | let ty = self.db.value_ty(func.into()); | 497 | let (ty, _) = self.db.value_ty(func.into()).into_value_and_skipped_binders(); |
496 | let resolver = self.analyze(call.syntax()).resolver; | 498 | let resolver = self.analyze(call.syntax()).resolver; |
497 | let ty = Type::new_with_resolver(self.db, &resolver, ty.value)?; | 499 | let ty = Type::new_with_resolver(self.db, &resolver, ty)?; |
498 | let mut res = ty.as_callable(self.db)?; | 500 | let mut res = ty.as_callable(self.db)?; |
499 | res.is_bound_method = true; | 501 | res.is_bound_method = true; |
500 | Some(res) | 502 | Some(res) |
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index 37d162b32..847d2537d 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs | |||
@@ -20,7 +20,7 @@ use hir_def::{ | |||
20 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; | 20 | use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; |
21 | use hir_ty::{ | 21 | use hir_ty::{ |
22 | diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, | 22 | diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, |
23 | InferenceResult, Substitution, | 23 | InferenceResult, Interner, Substitution, TyExt, TyLoweringContext, |
24 | }; | 24 | }; |
25 | use syntax::{ | 25 | use syntax::{ |
26 | ast::{self, AstNode}, | 26 | ast::{self, AstNode}, |
@@ -161,14 +161,15 @@ impl SourceAnalyzer { | |||
161 | db: &dyn HirDatabase, | 161 | db: &dyn HirDatabase, |
162 | field: &ast::RecordExprField, | 162 | field: &ast::RecordExprField, |
163 | ) -> Option<(Field, Option<Local>)> { | 163 | ) -> Option<(Field, Option<Local>)> { |
164 | let expr_id = | 164 | let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?; |
165 | self.body_source_map.as_ref()?.node_field(InFile::new(self.file_id, field))?; | 165 | let expr = ast::Expr::from(record_expr); |
166 | let expr_id = self.body_source_map.as_ref()?.node_expr(InFile::new(self.file_id, &expr))?; | ||
166 | 167 | ||
168 | let local_name = field.field_name()?.as_name(); | ||
167 | let local = if field.name_ref().is_some() { | 169 | let local = if field.name_ref().is_some() { |
168 | None | 170 | None |
169 | } else { | 171 | } else { |
170 | let local_name = field.field_name()?.as_name(); | 172 | let path = ModPath::from_segments(PathKind::Plain, once(local_name.clone())); |
171 | let path = ModPath::from_segments(PathKind::Plain, once(local_name)); | ||
172 | match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) { | 173 | match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) { |
173 | Some(ValueNs::LocalBinding(pat_id)) => { | 174 | Some(ValueNs::LocalBinding(pat_id)) => { |
174 | Some(Local { pat_id, parent: self.resolver.body_owner()? }) | 175 | Some(Local { pat_id, parent: self.resolver.body_owner()? }) |
@@ -176,18 +177,24 @@ impl SourceAnalyzer { | |||
176 | _ => None, | 177 | _ => None, |
177 | } | 178 | } |
178 | }; | 179 | }; |
179 | let struct_field = self.infer.as_ref()?.record_field_resolution(expr_id)?; | 180 | let variant = self.infer.as_ref()?.variant_resolution_for_expr(expr_id)?; |
180 | Some((struct_field.into(), local)) | 181 | let variant_data = variant.variant_data(db.upcast()); |
182 | let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? }; | ||
183 | Some((field.into(), local)) | ||
181 | } | 184 | } |
182 | 185 | ||
183 | pub(crate) fn resolve_record_pat_field( | 186 | pub(crate) fn resolve_record_pat_field( |
184 | &self, | 187 | &self, |
185 | _db: &dyn HirDatabase, | 188 | db: &dyn HirDatabase, |
186 | field: &ast::RecordPatField, | 189 | field: &ast::RecordPatField, |
187 | ) -> Option<Field> { | 190 | ) -> Option<Field> { |
188 | let pat_id = self.pat_id(&field.pat()?)?; | 191 | let field_name = field.field_name()?.as_name(); |
189 | let struct_field = self.infer.as_ref()?.record_pat_field_resolution(pat_id)?; | 192 | let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?; |
190 | Some(struct_field.into()) | 193 | let pat_id = self.pat_id(&record_pat.into())?; |
194 | let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id)?; | ||
195 | let variant_data = variant.variant_data(db.upcast()); | ||
196 | let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? }; | ||
197 | Some(field.into()) | ||
191 | } | 198 | } |
192 | 199 | ||
193 | pub(crate) fn resolve_macro_call( | 200 | pub(crate) fn resolve_macro_call( |
@@ -299,7 +306,7 @@ impl SourceAnalyzer { | |||
299 | let infer = self.infer.as_ref()?; | 306 | let infer = self.infer.as_ref()?; |
300 | 307 | ||
301 | let expr_id = self.expr_id(db, &literal.clone().into())?; | 308 | let expr_id = self.expr_id(db, &literal.clone().into())?; |
302 | let substs = infer.type_of_expr[expr_id].substs()?; | 309 | let substs = infer.type_of_expr[expr_id].as_adt()?.1; |
303 | 310 | ||
304 | let (variant, missing_fields, _exhaustive) = | 311 | let (variant, missing_fields, _exhaustive) = |
305 | record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?; | 312 | record_literal_missing_fields(db, infer, expr_id, &body[expr_id])?; |
@@ -317,7 +324,7 @@ impl SourceAnalyzer { | |||
317 | let infer = self.infer.as_ref()?; | 324 | let infer = self.infer.as_ref()?; |
318 | 325 | ||
319 | let pat_id = self.pat_id(&pattern.clone().into())?; | 326 | let pat_id = self.pat_id(&pattern.clone().into())?; |
320 | let substs = infer.type_of_pat[pat_id].substs()?; | 327 | let substs = infer.type_of_pat[pat_id].as_adt()?.1; |
321 | 328 | ||
322 | let (variant, missing_fields, _exhaustive) = | 329 | let (variant, missing_fields, _exhaustive) = |
323 | record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; | 330 | record_pattern_missing_fields(db, infer, pat_id, &body[pat_id])?; |
@@ -339,7 +346,7 @@ impl SourceAnalyzer { | |||
339 | .into_iter() | 346 | .into_iter() |
340 | .map(|local_id| { | 347 | .map(|local_id| { |
341 | let field = FieldId { parent: variant, local_id }; | 348 | let field = FieldId { parent: variant, local_id }; |
342 | let ty = field_types[local_id].clone().subst(substs); | 349 | let ty = field_types[local_id].clone().substitute(&Interner, substs); |
343 | (field.into(), Type::new_with_resolver_inner(db, krate, &self.resolver, ty)) | 350 | (field.into(), Type::new_with_resolver_inner(db, krate, &self.resolver, ty)) |
344 | }) | 351 | }) |
345 | .collect() | 352 | .collect() |
@@ -466,7 +473,21 @@ fn resolve_hir_path_( | |||
466 | prefer_value_ns: bool, | 473 | prefer_value_ns: bool, |
467 | ) -> Option<PathResolution> { | 474 | ) -> Option<PathResolution> { |
468 | let types = || { | 475 | let types = || { |
469 | resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { | 476 | let (ty, unresolved) = match path.type_anchor() { |
477 | Some(type_ref) => { | ||
478 | let (_, res) = TyLoweringContext::new(db, resolver).lower_ty_ext(type_ref); | ||
479 | res.map(|ty_ns| (ty_ns, path.segments().first())) | ||
480 | } | ||
481 | None => { | ||
482 | let (ty, remaining) = | ||
483 | resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?; | ||
484 | match remaining { | ||
485 | Some(remaining) if remaining > 1 => None, | ||
486 | _ => Some((ty, path.segments().get(1))), | ||
487 | } | ||
488 | } | ||
489 | }?; | ||
490 | let res = match ty { | ||
470 | TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), | 491 | TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), |
471 | TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), | 492 | TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), |
472 | TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { | 493 | TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { |
@@ -476,7 +497,17 @@ fn resolve_hir_path_( | |||
476 | TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), | 497 | TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), |
477 | TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), | 498 | TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), |
478 | TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), | 499 | TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), |
479 | }) | 500 | }; |
501 | match unresolved { | ||
502 | Some(unresolved) => res | ||
503 | .assoc_type_shorthand_candidates(db, |name, alias| { | ||
504 | (name == unresolved.name).then(|| alias) | ||
505 | }) | ||
506 | .map(TypeAlias::from) | ||
507 | .map(Into::into) | ||
508 | .map(PathResolution::Def), | ||
509 | None => Some(res), | ||
510 | } | ||
480 | }; | 511 | }; |
481 | 512 | ||
482 | let body_owner = resolver.body_owner(); | 513 | let body_owner = resolver.body_owner(); |
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index 475d337f3..43324d8d9 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -11,6 +11,7 @@ doctest = false | |||
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | cov-mark = { version = "1.1", features = ["thread-local"] } | 13 | cov-mark = { version = "1.1", features = ["thread-local"] } |
14 | dashmap = { version = "4.0.2", features = ["raw-api"] } | ||
14 | log = "0.4.8" | 15 | log = "0.4.8" |
15 | once_cell = "1.3.1" | 16 | once_cell = "1.3.1" |
16 | rustc-hash = "1.1.0" | 17 | rustc-hash = "1.1.0" |
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs index 58e35353b..402fb1d8d 100644 --- a/crates/hir_def/src/adt.rs +++ b/crates/hir_def/src/adt.rs | |||
@@ -15,6 +15,7 @@ use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree}; | |||
15 | use crate::{ | 15 | use crate::{ |
16 | body::{CfgExpander, LowerCtx}, | 16 | body::{CfgExpander, LowerCtx}, |
17 | db::DefDatabase, | 17 | db::DefDatabase, |
18 | intern::Interned, | ||
18 | item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId}, | 19 | item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId}, |
19 | src::HasChildSource, | 20 | src::HasChildSource, |
20 | src::HasSource, | 21 | src::HasSource, |
@@ -58,7 +59,7 @@ pub enum VariantData { | |||
58 | #[derive(Debug, Clone, PartialEq, Eq)] | 59 | #[derive(Debug, Clone, PartialEq, Eq)] |
59 | pub struct FieldData { | 60 | pub struct FieldData { |
60 | pub name: Name, | 61 | pub name: Name, |
61 | pub type_ref: TypeRef, | 62 | pub type_ref: Interned<TypeRef>, |
62 | pub visibility: RawVisibility, | 63 | pub visibility: RawVisibility, |
63 | } | 64 | } |
64 | 65 | ||
@@ -292,7 +293,7 @@ fn lower_struct( | |||
292 | || Either::Left(fd.clone()), | 293 | || Either::Left(fd.clone()), |
293 | || FieldData { | 294 | || FieldData { |
294 | name: Name::new_tuple_field(i), | 295 | name: Name::new_tuple_field(i), |
295 | type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()), | 296 | type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())), |
296 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | 297 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), |
297 | }, | 298 | }, |
298 | ); | 299 | ); |
@@ -309,7 +310,7 @@ fn lower_struct( | |||
309 | || Either::Right(fd.clone()), | 310 | || Either::Right(fd.clone()), |
310 | || FieldData { | 311 | || FieldData { |
311 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), | 312 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), |
312 | type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()), | 313 | type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())), |
313 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | 314 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), |
314 | }, | 315 | }, |
315 | ); | 316 | ); |
@@ -358,7 +359,7 @@ fn lower_field( | |||
358 | ) -> FieldData { | 359 | ) -> FieldData { |
359 | FieldData { | 360 | FieldData { |
360 | name: field.name.clone(), | 361 | name: field.name.clone(), |
361 | type_ref: item_tree[field.type_ref].clone(), | 362 | type_ref: field.type_ref.clone(), |
362 | visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), | 363 | visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), |
363 | } | 364 | } |
364 | } | 365 | } |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 52a2bce9b..786fad6e1 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -1,23 +1,28 @@ | |||
1 | //! A higher level attributes based on TokenTree, with also some shortcuts. | 1 | //! A higher level attributes based on TokenTree, with also some shortcuts. |
2 | 2 | ||
3 | use std::{ops, sync::Arc}; | 3 | use std::{ |
4 | convert::{TryFrom, TryInto}, | ||
5 | ops, | ||
6 | sync::Arc, | ||
7 | }; | ||
4 | 8 | ||
5 | use base_db::CrateId; | 9 | use base_db::CrateId; |
6 | use cfg::{CfgExpr, CfgOptions}; | 10 | use cfg::{CfgExpr, CfgOptions}; |
7 | use either::Either; | 11 | use either::Either; |
8 | use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; | 12 | use hir_expand::{hygiene::Hygiene, name::AsName, AstId, AttrId, InFile}; |
9 | use itertools::Itertools; | 13 | use itertools::Itertools; |
10 | use la_arena::ArenaMap; | 14 | use la_arena::ArenaMap; |
11 | use mbe::ast_to_token_tree; | 15 | use mbe::ast_to_token_tree; |
12 | use smallvec::{smallvec, SmallVec}; | 16 | use smallvec::{smallvec, SmallVec}; |
13 | use syntax::{ | 17 | use syntax::{ |
14 | ast::{self, AstNode, AttrsOwner}, | 18 | ast::{self, AstNode, AttrsOwner}, |
15 | match_ast, AstToken, SmolStr, SyntaxNode, | 19 | match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize, |
16 | }; | 20 | }; |
17 | use tt::Subtree; | 21 | use tt::Subtree; |
18 | 22 | ||
19 | use crate::{ | 23 | use crate::{ |
20 | db::DefDatabase, | 24 | db::DefDatabase, |
25 | intern::Interned, | ||
21 | item_tree::{ItemTreeId, ItemTreeNode}, | 26 | item_tree::{ItemTreeId, ItemTreeNode}, |
22 | nameres::ModuleSource, | 27 | nameres::ModuleSource, |
23 | path::{ModPath, PathKind}, | 28 | path::{ModPath, PathKind}, |
@@ -93,13 +98,16 @@ impl RawAttrs { | |||
93 | pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self { | 98 | pub(crate) fn new(owner: &dyn ast::AttrsOwner, hygiene: &Hygiene) -> Self { |
94 | let entries = collect_attrs(owner) | 99 | let entries = collect_attrs(owner) |
95 | .enumerate() | 100 | .enumerate() |
96 | .flat_map(|(i, attr)| match attr { | 101 | .flat_map(|(i, attr)| { |
97 | Either::Left(attr) => Attr::from_src(attr, hygiene, i as u32), | 102 | let index = AttrId(i as u32); |
98 | Either::Right(comment) => comment.doc_comment().map(|doc| Attr { | 103 | match attr { |
99 | index: i as u32, | 104 | Either::Left(attr) => Attr::from_src(attr, hygiene, index), |
100 | input: Some(AttrInput::Literal(SmolStr::new(doc))), | 105 | Either::Right(comment) => comment.doc_comment().map(|doc| Attr { |
101 | path: ModPath::from(hir_expand::name!(doc)), | 106 | id: index, |
102 | }), | 107 | input: Some(AttrInput::Literal(SmolStr::new(doc))), |
108 | path: Interned::new(ModPath::from(hir_expand::name!(doc))), | ||
109 | }), | ||
110 | } | ||
103 | }) | 111 | }) |
104 | .collect::<Arc<_>>(); | 112 | .collect::<Arc<_>>(); |
105 | 113 | ||
@@ -156,7 +164,7 @@ impl RawAttrs { | |||
156 | let cfg = parts.next().unwrap(); | 164 | let cfg = parts.next().unwrap(); |
157 | let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; | 165 | let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() }; |
158 | let cfg = CfgExpr::parse(&cfg); | 166 | let cfg = CfgExpr::parse(&cfg); |
159 | let index = attr.index; | 167 | let index = attr.id; |
160 | let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { | 168 | let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| { |
161 | let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; | 169 | let tree = Subtree { delimiter: None, token_trees: attr.to_vec() }; |
162 | let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?; | 170 | let attr = ast::Attr::parse(&format!("#[{}]", tree)).ok()?; |
@@ -210,12 +218,11 @@ impl Attrs { | |||
210 | let mut res = ArenaMap::default(); | 218 | let mut res = ArenaMap::default(); |
211 | 219 | ||
212 | for (id, fld) in src.value.iter() { | 220 | for (id, fld) in src.value.iter() { |
213 | let attrs = match fld { | 221 | let owner: &dyn AttrsOwner = match fld { |
214 | Either::Left(_tuple) => Attrs::default(), | 222 | Either::Left(tuple) => tuple, |
215 | Either::Right(record) => { | 223 | Either::Right(record) => record, |
216 | RawAttrs::from_attrs_owner(db, src.with_value(record)).filter(db, krate) | ||
217 | } | ||
218 | }; | 224 | }; |
225 | let attrs = RawAttrs::from_attrs_owner(db, src.with_value(owner)).filter(db, krate); | ||
219 | 226 | ||
220 | res.insert(id, attrs); | 227 | res.insert(id, attrs); |
221 | } | 228 | } |
@@ -399,10 +406,14 @@ impl AttrsWithOwner { | |||
399 | return AttrSourceMap { attrs }; | 406 | return AttrSourceMap { attrs }; |
400 | } | 407 | } |
401 | AttrDefId::FieldId(id) => { | 408 | AttrDefId::FieldId(id) => { |
402 | id.parent.child_source(db).map(|source| match &source[id.local_id] { | 409 | let map = db.fields_attrs_source_map(id.parent); |
403 | Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()), | 410 | let file_id = id.parent.file_id(db); |
404 | Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()), | 411 | let root = db.parse_or_expand(file_id).unwrap(); |
405 | }) | 412 | let owner = match &map[id.local_id] { |
413 | Either::Left(it) => ast::AttrsOwnerNode::new(it.to_node(&root)), | ||
414 | Either::Right(it) => ast::AttrsOwnerNode::new(it.to_node(&root)), | ||
415 | }; | ||
416 | InFile::new(file_id, owner) | ||
406 | } | 417 | } |
407 | AttrDefId::AdtId(adt) => match adt { | 418 | AttrDefId::AdtId(adt) => match adt { |
408 | AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | 419 | AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), |
@@ -410,10 +421,12 @@ impl AttrsWithOwner { | |||
410 | AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | 421 | AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), |
411 | }, | 422 | }, |
412 | AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | 423 | AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), |
413 | AttrDefId::EnumVariantId(id) => id | 424 | AttrDefId::EnumVariantId(id) => { |
414 | .parent | 425 | let map = db.variants_attrs_source_map(id.parent); |
415 | .child_source(db) | 426 | let file_id = id.parent.lookup(db).id.file_id(); |
416 | .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), | 427 | let root = db.parse_or_expand(file_id).unwrap(); |
428 | InFile::new(file_id, ast::AttrsOwnerNode::new(map[id.local_id].to_node(&root))) | ||
429 | } | ||
417 | AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | 430 | AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), |
418 | AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | 431 | AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), |
419 | AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | 432 | AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), |
@@ -451,6 +464,55 @@ impl AttrsWithOwner { | |||
451 | .collect(), | 464 | .collect(), |
452 | } | 465 | } |
453 | } | 466 | } |
467 | |||
468 | pub fn docs_with_rangemap( | ||
469 | &self, | ||
470 | db: &dyn DefDatabase, | ||
471 | ) -> Option<(Documentation, DocsRangeMap)> { | ||
472 | // FIXME: code duplication in `docs` above | ||
473 | let docs = self.by_key("doc").attrs().flat_map(|attr| match attr.input.as_ref()? { | ||
474 | AttrInput::Literal(s) => Some((s, attr.id)), | ||
475 | AttrInput::TokenTree(_) => None, | ||
476 | }); | ||
477 | let indent = docs | ||
478 | .clone() | ||
479 | .flat_map(|(s, _)| s.lines()) | ||
480 | .filter(|line| !line.chars().all(|c| c.is_whitespace())) | ||
481 | .map(|line| line.chars().take_while(|c| c.is_whitespace()).count()) | ||
482 | .min() | ||
483 | .unwrap_or(0); | ||
484 | let mut buf = String::new(); | ||
485 | let mut mapping = Vec::new(); | ||
486 | for (doc, idx) in docs { | ||
487 | // str::lines doesn't yield anything for the empty string | ||
488 | if !doc.is_empty() { | ||
489 | for line in doc.split('\n') { | ||
490 | let line = line.trim_end(); | ||
491 | let line_len = line.len(); | ||
492 | let (offset, line) = match line.char_indices().nth(indent) { | ||
493 | Some((offset, _)) => (offset, &line[offset..]), | ||
494 | None => (0, line), | ||
495 | }; | ||
496 | let buf_offset = buf.len(); | ||
497 | buf.push_str(line); | ||
498 | mapping.push(( | ||
499 | TextRange::new(buf_offset.try_into().ok()?, buf.len().try_into().ok()?), | ||
500 | idx, | ||
501 | TextRange::new(offset.try_into().ok()?, line_len.try_into().ok()?), | ||
502 | )); | ||
503 | buf.push('\n'); | ||
504 | } | ||
505 | } else { | ||
506 | buf.push('\n'); | ||
507 | } | ||
508 | } | ||
509 | buf.pop(); | ||
510 | if buf.is_empty() { | ||
511 | None | ||
512 | } else { | ||
513 | Some((Documentation(buf), DocsRangeMap { mapping, source: self.source_map(db).attrs })) | ||
514 | } | ||
515 | } | ||
454 | } | 516 | } |
455 | 517 | ||
456 | fn inner_attributes( | 518 | fn inner_attributes( |
@@ -501,16 +563,54 @@ impl AttrSourceMap { | |||
501 | /// the attribute represented by `Attr`. | 563 | /// the attribute represented by `Attr`. |
502 | pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> { | 564 | pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> { |
503 | self.attrs | 565 | self.attrs |
504 | .get(attr.index as usize) | 566 | .get(attr.id.0 as usize) |
505 | .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index)) | 567 | .unwrap_or_else(|| panic!("cannot find `Attr` at index {:?}", attr.id)) |
506 | .as_ref() | 568 | .as_ref() |
507 | } | 569 | } |
508 | } | 570 | } |
509 | 571 | ||
572 | /// A struct to map text ranges from [`Documentation`] back to TextRanges in the syntax tree. | ||
573 | pub struct DocsRangeMap { | ||
574 | source: Vec<InFile<Either<ast::Attr, ast::Comment>>>, | ||
575 | // (docstring-line-range, attr_index, attr-string-range) | ||
576 | // a mapping from the text range of a line of the [`Documentation`] to the attribute index and | ||
577 | // the original (untrimmed) syntax doc line | ||
578 | mapping: Vec<(TextRange, AttrId, TextRange)>, | ||
579 | } | ||
580 | |||
581 | impl DocsRangeMap { | ||
582 | pub fn map(&self, range: TextRange) -> Option<InFile<TextRange>> { | ||
583 | let found = self.mapping.binary_search_by(|(probe, ..)| probe.ordering(range)).ok()?; | ||
584 | let (line_docs_range, idx, original_line_src_range) = self.mapping[found].clone(); | ||
585 | if !line_docs_range.contains_range(range) { | ||
586 | return None; | ||
587 | } | ||
588 | |||
589 | let relative_range = range - line_docs_range.start(); | ||
590 | |||
591 | let &InFile { file_id, value: ref source } = &self.source[idx.0 as usize]; | ||
592 | match source { | ||
593 | Either::Left(_) => None, // FIXME, figure out a nice way to handle doc attributes here | ||
594 | // as well as for whats done in syntax highlight doc injection | ||
595 | Either::Right(comment) => { | ||
596 | let text_range = comment.syntax().text_range(); | ||
597 | let range = TextRange::at( | ||
598 | text_range.start() | ||
599 | + TextSize::try_from(comment.prefix().len()).ok()? | ||
600 | + original_line_src_range.start() | ||
601 | + relative_range.start(), | ||
602 | text_range.len().min(range.len()), | ||
603 | ); | ||
604 | Some(InFile { file_id, value: range }) | ||
605 | } | ||
606 | } | ||
607 | } | ||
608 | } | ||
609 | |||
510 | #[derive(Debug, Clone, PartialEq, Eq)] | 610 | #[derive(Debug, Clone, PartialEq, Eq)] |
511 | pub struct Attr { | 611 | pub struct Attr { |
512 | index: u32, | 612 | pub(crate) id: AttrId, |
513 | pub(crate) path: ModPath, | 613 | pub(crate) path: Interned<ModPath>, |
514 | pub(crate) input: Option<AttrInput>, | 614 | pub(crate) input: Option<AttrInput>, |
515 | } | 615 | } |
516 | 616 | ||
@@ -523,8 +623,8 @@ pub enum AttrInput { | |||
523 | } | 623 | } |
524 | 624 | ||
525 | impl Attr { | 625 | impl Attr { |
526 | fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> { | 626 | fn from_src(ast: ast::Attr, hygiene: &Hygiene, id: AttrId) -> Option<Attr> { |
527 | let path = ModPath::from_src(ast.path()?, hygiene)?; | 627 | let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?); |
528 | let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { | 628 | let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { |
529 | let value = match lit.kind() { | 629 | let value = match lit.kind() { |
530 | ast::LiteralKind::String(string) => string.value()?.into(), | 630 | ast::LiteralKind::String(string) => string.value()?.into(), |
@@ -532,11 +632,11 @@ impl Attr { | |||
532 | }; | 632 | }; |
533 | Some(AttrInput::Literal(value)) | 633 | Some(AttrInput::Literal(value)) |
534 | } else if let Some(tt) = ast.token_tree() { | 634 | } else if let Some(tt) = ast.token_tree() { |
535 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) | 635 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt).0)) |
536 | } else { | 636 | } else { |
537 | None | 637 | None |
538 | }; | 638 | }; |
539 | Some(Attr { index, path, input }) | 639 | Some(Attr { id, path, input }) |
540 | } | 640 | } |
541 | 641 | ||
542 | /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths | 642 | /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths |
@@ -651,7 +751,38 @@ fn collect_attrs( | |||
651 | .chain(inner_docs.into_iter().flatten()) | 751 | .chain(inner_docs.into_iter().flatten()) |
652 | .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text))); | 752 | .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text))); |
653 | // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved | 753 | // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved |
654 | let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect(); | 754 | docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).map(|(_, attr)| attr) |
755 | } | ||
756 | |||
757 | pub(crate) fn variants_attrs_source_map( | ||
758 | db: &dyn DefDatabase, | ||
759 | def: EnumId, | ||
760 | ) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>> { | ||
761 | let mut res = ArenaMap::default(); | ||
762 | let child_source = def.child_source(db); | ||
763 | |||
764 | for (idx, variant) in child_source.value.iter() { | ||
765 | res.insert(idx, AstPtr::new(variant)); | ||
766 | } | ||
767 | |||
768 | Arc::new(res) | ||
769 | } | ||
770 | |||
771 | pub(crate) fn fields_attrs_source_map( | ||
772 | db: &dyn DefDatabase, | ||
773 | def: VariantId, | ||
774 | ) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>> { | ||
775 | let mut res = ArenaMap::default(); | ||
776 | let child_source = def.child_source(db); | ||
777 | |||
778 | for (idx, variant) in child_source.value.iter() { | ||
779 | res.insert( | ||
780 | idx, | ||
781 | variant | ||
782 | .as_ref() | ||
783 | .either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))), | ||
784 | ); | ||
785 | } | ||
655 | 786 | ||
656 | attrs.into_iter().map(|(_, attr)| attr) | 787 | Arc::new(res) |
657 | } | 788 | } |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 1080d9c2c..96b959967 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -226,7 +226,7 @@ pub struct Body { | |||
226 | /// The `ExprId` of the actual body expression. | 226 | /// The `ExprId` of the actual body expression. |
227 | pub body_expr: ExprId, | 227 | pub body_expr: ExprId, |
228 | /// Block expressions in this body that may contain inner items. | 228 | /// Block expressions in this body that may contain inner items. |
229 | pub block_scopes: Vec<BlockId>, | 229 | block_scopes: Vec<BlockId>, |
230 | _c: Count<Self>, | 230 | _c: Count<Self>, |
231 | } | 231 | } |
232 | 232 | ||
@@ -302,7 +302,8 @@ impl Body { | |||
302 | } | 302 | } |
303 | }; | 303 | }; |
304 | let expander = Expander::new(db, file_id, module); | 304 | let expander = Expander::new(db, file_id, module); |
305 | let (body, source_map) = Body::new(db, expander, params, body); | 305 | let (mut body, source_map) = Body::new(db, expander, params, body); |
306 | body.shrink_to_fit(); | ||
306 | (Arc::new(body), Arc::new(source_map)) | 307 | (Arc::new(body), Arc::new(source_map)) |
307 | } | 308 | } |
308 | 309 | ||
@@ -310,6 +311,16 @@ impl Body { | |||
310 | db.body_with_source_map(def).0 | 311 | db.body_with_source_map(def).0 |
311 | } | 312 | } |
312 | 313 | ||
314 | /// Returns an iterator over all block expressions in this body that define inner items. | ||
315 | pub fn blocks<'a>( | ||
316 | &'a self, | ||
317 | db: &'a dyn DefDatabase, | ||
318 | ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + '_ { | ||
319 | self.block_scopes | ||
320 | .iter() | ||
321 | .map(move |block| (*block, db.block_def_map(*block).expect("block ID without DefMap"))) | ||
322 | } | ||
323 | |||
313 | fn new( | 324 | fn new( |
314 | db: &dyn DefDatabase, | 325 | db: &dyn DefDatabase, |
315 | expander: Expander, | 326 | expander: Expander, |
@@ -318,6 +329,15 @@ impl Body { | |||
318 | ) -> (Body, BodySourceMap) { | 329 | ) -> (Body, BodySourceMap) { |
319 | lower::lower(db, expander, params, body) | 330 | lower::lower(db, expander, params, body) |
320 | } | 331 | } |
332 | |||
333 | fn shrink_to_fit(&mut self) { | ||
334 | let Self { _c: _, body_expr: _, block_scopes, exprs, labels, params, pats } = self; | ||
335 | block_scopes.shrink_to_fit(); | ||
336 | exprs.shrink_to_fit(); | ||
337 | labels.shrink_to_fit(); | ||
338 | params.shrink_to_fit(); | ||
339 | pats.shrink_to_fit(); | ||
340 | } | ||
321 | } | 341 | } |
322 | 342 | ||
323 | impl Index<ExprId> for Body { | 343 | impl Index<ExprId> for Body { |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 229e81dd4..c0b0b7841 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -30,6 +30,7 @@ use crate::{ | |||
30 | LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, | 30 | LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, |
31 | Statement, | 31 | Statement, |
32 | }, | 32 | }, |
33 | intern::Interned, | ||
33 | item_scope::BuiltinShadowMode, | 34 | item_scope::BuiltinShadowMode, |
34 | path::{GenericArgs, Path}, | 35 | path::{GenericArgs, Path}, |
35 | type_ref::{Mutability, Rawness, TypeRef}, | 36 | type_ref::{Mutability, Rawness, TypeRef}, |
@@ -322,8 +323,10 @@ impl ExprCollector<'_> { | |||
322 | Vec::new() | 323 | Vec::new() |
323 | }; | 324 | }; |
324 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); | 325 | let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); |
325 | let generic_args = | 326 | let generic_args = e |
326 | e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); | 327 | .generic_arg_list() |
328 | .and_then(|it| GenericArgs::from_ast(&self.ctx(), it)) | ||
329 | .map(Box::new); | ||
327 | self.alloc_expr( | 330 | self.alloc_expr( |
328 | Expr::MethodCall { receiver, method_name, args, generic_args }, | 331 | Expr::MethodCall { receiver, method_name, args, generic_args }, |
329 | syntax_ptr, | 332 | syntax_ptr, |
@@ -385,7 +388,7 @@ impl ExprCollector<'_> { | |||
385 | self.alloc_expr(Expr::Yield { expr }, syntax_ptr) | 388 | self.alloc_expr(Expr::Yield { expr }, syntax_ptr) |
386 | } | 389 | } |
387 | ast::Expr::RecordExpr(e) => { | 390 | ast::Expr::RecordExpr(e) => { |
388 | let path = e.path().and_then(|path| self.expander.parse_path(path)); | 391 | let path = e.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
389 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { | 392 | let record_lit = if let Some(nfl) = e.record_expr_field_list() { |
390 | let fields = nfl | 393 | let fields = nfl |
391 | .fields() | 394 | .fields() |
@@ -430,7 +433,7 @@ impl ExprCollector<'_> { | |||
430 | } | 433 | } |
431 | ast::Expr::CastExpr(e) => { | 434 | ast::Expr::CastExpr(e) => { |
432 | let expr = self.collect_expr_opt(e.expr()); | 435 | let expr = self.collect_expr_opt(e.expr()); |
433 | let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); | 436 | let type_ref = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty())); |
434 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) | 437 | self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) |
435 | } | 438 | } |
436 | ast::Expr::RefExpr(e) => { | 439 | ast::Expr::RefExpr(e) => { |
@@ -464,13 +467,16 @@ impl ExprCollector<'_> { | |||
464 | if let Some(pl) = e.param_list() { | 467 | if let Some(pl) = e.param_list() { |
465 | for param in pl.params() { | 468 | for param in pl.params() { |
466 | let pat = self.collect_pat_opt(param.pat()); | 469 | let pat = self.collect_pat_opt(param.pat()); |
467 | let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); | 470 | let type_ref = |
471 | param.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it))); | ||
468 | args.push(pat); | 472 | args.push(pat); |
469 | arg_types.push(type_ref); | 473 | arg_types.push(type_ref); |
470 | } | 474 | } |
471 | } | 475 | } |
472 | let ret_type = | 476 | let ret_type = e |
473 | e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it)); | 477 | .ret_type() |
478 | .and_then(|r| r.ty()) | ||
479 | .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it))); | ||
474 | let body = self.collect_expr_opt(e.body()); | 480 | let body = self.collect_expr_opt(e.body()); |
475 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) | 481 | self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) |
476 | } | 482 | } |
@@ -525,8 +531,9 @@ impl ExprCollector<'_> { | |||
525 | } | 531 | } |
526 | } | 532 | } |
527 | ast::Expr::MacroCall(e) => { | 533 | ast::Expr::MacroCall(e) => { |
534 | let macro_ptr = AstPtr::new(&e); | ||
528 | let mut ids = vec![]; | 535 | let mut ids = vec![]; |
529 | self.collect_macro_call(e, syntax_ptr.clone(), true, |this, expansion| { | 536 | self.collect_macro_call(e, macro_ptr, true, |this, expansion| { |
530 | ids.push(match expansion { | 537 | ids.push(match expansion { |
531 | Some(it) => this.collect_expr(it), | 538 | Some(it) => this.collect_expr(it), |
532 | None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()), | 539 | None => this.alloc_expr(Expr::Missing, syntax_ptr.clone()), |
@@ -549,7 +556,7 @@ impl ExprCollector<'_> { | |||
549 | fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>( | 556 | fn collect_macro_call<F: FnMut(&mut Self, Option<T>), T: ast::AstNode>( |
550 | &mut self, | 557 | &mut self, |
551 | e: ast::MacroCall, | 558 | e: ast::MacroCall, |
552 | syntax_ptr: AstPtr<ast::Expr>, | 559 | syntax_ptr: AstPtr<ast::MacroCall>, |
553 | is_error_recoverable: bool, | 560 | is_error_recoverable: bool, |
554 | mut collector: F, | 561 | mut collector: F, |
555 | ) { | 562 | ) { |
@@ -561,9 +568,13 @@ impl ExprCollector<'_> { | |||
561 | 568 | ||
562 | let res = match res { | 569 | let res = match res { |
563 | Ok(res) => res, | 570 | Ok(res) => res, |
564 | Err(UnresolvedMacro) => { | 571 | Err(UnresolvedMacro { path }) => { |
565 | self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedMacroCall( | 572 | self.source_map.diagnostics.push(BodyDiagnostic::UnresolvedMacroCall( |
566 | UnresolvedMacroCall { file: outer_file, node: syntax_ptr.cast().unwrap() }, | 573 | UnresolvedMacroCall { |
574 | file: outer_file, | ||
575 | node: syntax_ptr.cast().unwrap(), | ||
576 | path, | ||
577 | }, | ||
567 | )); | 578 | )); |
568 | collector(self, None); | 579 | collector(self, None); |
569 | return; | 580 | return; |
@@ -625,7 +636,8 @@ impl ExprCollector<'_> { | |||
625 | return; | 636 | return; |
626 | } | 637 | } |
627 | let pat = self.collect_pat_opt(stmt.pat()); | 638 | let pat = self.collect_pat_opt(stmt.pat()); |
628 | let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); | 639 | let type_ref = |
640 | stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it))); | ||
629 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); | 641 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); |
630 | self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer }); | 642 | self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer }); |
631 | } | 643 | } |
@@ -636,10 +648,14 @@ impl ExprCollector<'_> { | |||
636 | 648 | ||
637 | // Note that macro could be expended to multiple statements | 649 | // Note that macro could be expended to multiple statements |
638 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { | 650 | if let Some(ast::Expr::MacroCall(m)) = stmt.expr() { |
651 | let macro_ptr = AstPtr::new(&m); | ||
639 | let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); | 652 | let syntax_ptr = AstPtr::new(&stmt.expr().unwrap()); |
640 | 653 | ||
641 | self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| { | 654 | self.collect_macro_call( |
642 | match expansion { | 655 | m, |
656 | macro_ptr, | ||
657 | false, | ||
658 | |this, expansion| match expansion { | ||
643 | Some(expansion) => { | 659 | Some(expansion) => { |
644 | let statements: ast::MacroStmts = expansion; | 660 | let statements: ast::MacroStmts = expansion; |
645 | 661 | ||
@@ -653,8 +669,8 @@ impl ExprCollector<'_> { | |||
653 | let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); | 669 | let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone()); |
654 | this.statements_in_scope.push(Statement::Expr(expr)); | 670 | this.statements_in_scope.push(Statement::Expr(expr)); |
655 | } | 671 | } |
656 | } | 672 | }, |
657 | }); | 673 | ); |
658 | } else { | 674 | } else { |
659 | let expr = self.collect_expr_opt(stmt.expr()); | 675 | let expr = self.collect_expr_opt(stmt.expr()); |
660 | self.statements_in_scope.push(Statement::Expr(expr)); | 676 | self.statements_in_scope.push(Statement::Expr(expr)); |
@@ -673,12 +689,14 @@ impl ExprCollector<'_> { | |||
673 | let block_loc = | 689 | let block_loc = |
674 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; | 690 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; |
675 | let block_id = self.db.intern_block(block_loc); | 691 | let block_id = self.db.intern_block(block_loc); |
676 | self.body.block_scopes.push(block_id); | ||
677 | 692 | ||
678 | let opt_def_map = self.db.block_def_map(block_id); | 693 | let (module, def_map) = match self.db.block_def_map(block_id) { |
679 | let has_def_map = opt_def_map.is_some(); | 694 | Some(def_map) => { |
680 | let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); | 695 | self.body.block_scopes.push(block_id); |
681 | let module = if has_def_map { def_map.root() } else { self.expander.module }; | 696 | (def_map.root(), def_map) |
697 | } | ||
698 | None => (self.expander.module, self.expander.def_map.clone()), | ||
699 | }; | ||
682 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); | 700 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); |
683 | let prev_local_module = mem::replace(&mut self.expander.module, module); | 701 | let prev_local_module = mem::replace(&mut self.expander.module, module); |
684 | let prev_statements = std::mem::take(&mut self.statements_in_scope); | 702 | let prev_statements = std::mem::take(&mut self.statements_in_scope); |
@@ -753,7 +771,7 @@ impl ExprCollector<'_> { | |||
753 | } | 771 | } |
754 | } | 772 | } |
755 | ast::Pat::TupleStructPat(p) => { | 773 | ast::Pat::TupleStructPat(p) => { |
756 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 774 | let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
757 | let (args, ellipsis) = self.collect_tuple_pat(p.fields()); | 775 | let (args, ellipsis) = self.collect_tuple_pat(p.fields()); |
758 | Pat::TupleStruct { path, args, ellipsis } | 776 | Pat::TupleStruct { path, args, ellipsis } |
759 | } | 777 | } |
@@ -763,7 +781,7 @@ impl ExprCollector<'_> { | |||
763 | Pat::Ref { pat, mutability } | 781 | Pat::Ref { pat, mutability } |
764 | } | 782 | } |
765 | ast::Pat::PathPat(p) => { | 783 | ast::Pat::PathPat(p) => { |
766 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 784 | let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
767 | path.map(Pat::Path).unwrap_or(Pat::Missing) | 785 | path.map(Pat::Path).unwrap_or(Pat::Missing) |
768 | } | 786 | } |
769 | ast::Pat::OrPat(p) => { | 787 | ast::Pat::OrPat(p) => { |
@@ -777,7 +795,7 @@ impl ExprCollector<'_> { | |||
777 | } | 795 | } |
778 | ast::Pat::WildcardPat(_) => Pat::Wild, | 796 | ast::Pat::WildcardPat(_) => Pat::Wild, |
779 | ast::Pat::RecordPat(p) => { | 797 | ast::Pat::RecordPat(p) => { |
780 | let path = p.path().and_then(|path| self.expander.parse_path(path)); | 798 | let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new); |
781 | let args: Vec<_> = p | 799 | let args: Vec<_> = p |
782 | .record_pat_field_list() | 800 | .record_pat_field_list() |
783 | .expect("every struct should have a field list") | 801 | .expect("every struct should have a field list") |
@@ -839,8 +857,23 @@ impl ExprCollector<'_> { | |||
839 | Pat::Missing | 857 | Pat::Missing |
840 | } | 858 | } |
841 | } | 859 | } |
860 | ast::Pat::MacroPat(mac) => match mac.macro_call() { | ||
861 | Some(call) => { | ||
862 | let macro_ptr = AstPtr::new(&call); | ||
863 | let mut pat = None; | ||
864 | self.collect_macro_call(call, macro_ptr, true, |this, expanded_pat| { | ||
865 | pat = Some(this.collect_pat_opt(expanded_pat)); | ||
866 | }); | ||
867 | |||
868 | match pat { | ||
869 | Some(pat) => return pat, | ||
870 | None => Pat::Missing, | ||
871 | } | ||
872 | } | ||
873 | None => Pat::Missing, | ||
874 | }, | ||
842 | // FIXME: implement | 875 | // FIXME: implement |
843 | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, | 876 | ast::Pat::RangePat(_) => Pat::Missing, |
844 | }; | 877 | }; |
845 | let ptr = AstPtr::new(&pat); | 878 | let ptr = AstPtr::new(&pat); |
846 | self.alloc_pat(pattern, Either::Left(ptr)) | 879 | self.alloc_pat(pattern, Either::Left(ptr)) |
diff --git a/crates/hir_def/src/body/tests.rs b/crates/hir_def/src/body/tests.rs index faa133297..63f5fe88d 100644 --- a/crates/hir_def/src/body/tests.rs +++ b/crates/hir_def/src/body/tests.rs | |||
@@ -143,7 +143,7 @@ fn f() { | |||
143 | //^^^^^^^^^^^^^ could not convert tokens | 143 | //^^^^^^^^^^^^^ could not convert tokens |
144 | 144 | ||
145 | env!("OUT_DIR"); | 145 | env!("OUT_DIR"); |
146 | //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "load out dirs from check" to fix | 146 | //^^^^^^^^^^^^^^^ `OUT_DIR` not set, enable "run build scripts" to fix |
147 | 147 | ||
148 | compile_error!("compile_error works"); | 148 | compile_error!("compile_error works"); |
149 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works | 149 | //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ compile_error works |
@@ -180,7 +180,7 @@ fn unresolved_macro_diag() { | |||
180 | r#" | 180 | r#" |
181 | fn f() { | 181 | fn f() { |
182 | m!(); | 182 | m!(); |
183 | //^^^^ unresolved macro call | 183 | //^^^^ unresolved macro `m!` |
184 | } | 184 | } |
185 | "#, | 185 | "#, |
186 | ); | 186 | ); |
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs index 2a331dcaf..f2e809ca9 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs | |||
@@ -80,6 +80,10 @@ impl ChildBySource for ModuleId { | |||
80 | impl ChildBySource for ItemScope { | 80 | impl ChildBySource for ItemScope { |
81 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { | 81 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
82 | self.declarations().for_each(|item| add_module_def(db, res, item)); | 82 | self.declarations().for_each(|item| add_module_def(db, res, item)); |
83 | self.unnamed_consts().for_each(|konst| { | ||
84 | let src = konst.lookup(db).source(db); | ||
85 | res[keys::CONST].insert(src, konst); | ||
86 | }); | ||
83 | self.impls().for_each(|imp| add_impl(db, res, imp)); | 87 | self.impls().for_each(|imp| add_impl(db, res, imp)); |
84 | 88 | ||
85 | fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { | 89 | fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) { |
@@ -160,7 +164,7 @@ impl ChildBySource for EnumId { | |||
160 | impl ChildBySource for DefWithBodyId { | 164 | impl ChildBySource for DefWithBodyId { |
161 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { | 165 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
162 | let body = db.body(*self); | 166 | let body = db.body(*self); |
163 | for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { | 167 | for (_, def_map) in body.blocks(db) { |
164 | // All block expressions are merged into the same map, because they logically all add | 168 | // All block expressions are merged into the same map, because they logically all add |
165 | // inner items to the containing `DefWithBodyId`. | 169 | // inner items to the containing `DefWithBodyId`. |
166 | def_map[def_map.root()].scope.child_by_source_to(db, res); | 170 | def_map[def_map.root()].scope.child_by_source_to(db, res); |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 0be868ba2..135a6698e 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -9,8 +9,9 @@ use crate::{ | |||
9 | attr::Attrs, | 9 | attr::Attrs, |
10 | body::Expander, | 10 | body::Expander, |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, | 12 | intern::Interned, |
13 | type_ref::{TypeBound, TypeRef}, | 13 | item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param}, |
14 | type_ref::{TraitRef, TypeBound, TypeRef}, | ||
14 | visibility::RawVisibility, | 15 | visibility::RawVisibility, |
15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, | 16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
16 | Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, | 17 | Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, |
@@ -19,17 +20,12 @@ use crate::{ | |||
19 | #[derive(Debug, Clone, PartialEq, Eq)] | 20 | #[derive(Debug, Clone, PartialEq, Eq)] |
20 | pub struct FunctionData { | 21 | pub struct FunctionData { |
21 | pub name: Name, | 22 | pub name: Name, |
22 | pub params: Vec<TypeRef>, | 23 | pub params: Vec<Interned<TypeRef>>, |
23 | pub ret_type: TypeRef, | 24 | pub ret_type: Interned<TypeRef>, |
24 | pub attrs: Attrs, | 25 | pub attrs: Attrs, |
25 | /// True if the first param is `self`. This is relevant to decide whether this | ||
26 | /// can be called as a method. | ||
27 | pub has_self_param: bool, | ||
28 | pub has_body: bool, | ||
29 | pub qualifier: FunctionQualifier, | ||
30 | pub is_in_extern_block: bool, | ||
31 | pub is_varargs: bool, | ||
32 | pub visibility: RawVisibility, | 26 | pub visibility: RawVisibility, |
27 | pub abi: Option<Interned<str>>, | ||
28 | flags: FnFlags, | ||
33 | } | 29 | } |
34 | 30 | ||
35 | impl FunctionData { | 31 | impl FunctionData { |
@@ -52,31 +48,67 @@ impl FunctionData { | |||
52 | .next_back() | 48 | .next_back() |
53 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); | 49 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); |
54 | 50 | ||
51 | let mut flags = func.flags; | ||
52 | if is_varargs { | ||
53 | flags.bits |= FnFlags::IS_VARARGS; | ||
54 | } | ||
55 | |||
55 | Arc::new(FunctionData { | 56 | Arc::new(FunctionData { |
56 | name: func.name.clone(), | 57 | name: func.name.clone(), |
57 | params: enabled_params | 58 | params: enabled_params |
58 | .clone() | 59 | .clone() |
59 | .filter_map(|id| match &item_tree[id] { | 60 | .filter_map(|id| match &item_tree[id] { |
60 | Param::Normal(ty) => Some(item_tree[*ty].clone()), | 61 | Param::Normal(ty) => Some(ty.clone()), |
61 | Param::Varargs => None, | 62 | Param::Varargs => None, |
62 | }) | 63 | }) |
63 | .collect(), | 64 | .collect(), |
64 | ret_type: item_tree[func.ret_type].clone(), | 65 | ret_type: func.ret_type.clone(), |
65 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), | 66 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), |
66 | has_self_param: func.has_self_param, | ||
67 | has_body: func.has_body, | ||
68 | qualifier: func.qualifier.clone(), | ||
69 | is_in_extern_block: func.is_in_extern_block, | ||
70 | is_varargs, | ||
71 | visibility: item_tree[func.visibility].clone(), | 67 | visibility: item_tree[func.visibility].clone(), |
68 | abi: func.abi.clone(), | ||
69 | flags, | ||
72 | }) | 70 | }) |
73 | } | 71 | } |
72 | |||
73 | pub fn has_body(&self) -> bool { | ||
74 | self.flags.bits & FnFlags::HAS_BODY != 0 | ||
75 | } | ||
76 | |||
77 | /// True if the first param is `self`. This is relevant to decide whether this | ||
78 | /// can be called as a method. | ||
79 | pub fn has_self_param(&self) -> bool { | ||
80 | self.flags.bits & FnFlags::HAS_SELF_PARAM != 0 | ||
81 | } | ||
82 | |||
83 | pub fn is_default(&self) -> bool { | ||
84 | self.flags.bits & FnFlags::IS_DEFAULT != 0 | ||
85 | } | ||
86 | |||
87 | pub fn is_const(&self) -> bool { | ||
88 | self.flags.bits & FnFlags::IS_CONST != 0 | ||
89 | } | ||
90 | |||
91 | pub fn is_async(&self) -> bool { | ||
92 | self.flags.bits & FnFlags::IS_ASYNC != 0 | ||
93 | } | ||
94 | |||
95 | pub fn is_unsafe(&self) -> bool { | ||
96 | self.flags.bits & FnFlags::IS_UNSAFE != 0 | ||
97 | } | ||
98 | |||
99 | pub fn is_in_extern_block(&self) -> bool { | ||
100 | self.flags.bits & FnFlags::IS_IN_EXTERN_BLOCK != 0 | ||
101 | } | ||
102 | |||
103 | pub fn is_varargs(&self) -> bool { | ||
104 | self.flags.bits & FnFlags::IS_VARARGS != 0 | ||
105 | } | ||
74 | } | 106 | } |
75 | 107 | ||
76 | #[derive(Debug, Clone, PartialEq, Eq)] | 108 | #[derive(Debug, Clone, PartialEq, Eq)] |
77 | pub struct TypeAliasData { | 109 | pub struct TypeAliasData { |
78 | pub name: Name, | 110 | pub name: Name, |
79 | pub type_ref: Option<TypeRef>, | 111 | pub type_ref: Option<Interned<TypeRef>>, |
80 | pub visibility: RawVisibility, | 112 | pub visibility: RawVisibility, |
81 | pub is_extern: bool, | 113 | pub is_extern: bool, |
82 | /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). | 114 | /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). |
@@ -94,7 +126,7 @@ impl TypeAliasData { | |||
94 | 126 | ||
95 | Arc::new(TypeAliasData { | 127 | Arc::new(TypeAliasData { |
96 | name: typ.name.clone(), | 128 | name: typ.name.clone(), |
97 | type_ref: typ.type_ref.map(|id| item_tree[id].clone()), | 129 | type_ref: typ.type_ref.clone(), |
98 | visibility: item_tree[typ.visibility].clone(), | 130 | visibility: item_tree[typ.visibility].clone(), |
99 | is_extern: typ.is_extern, | 131 | is_extern: typ.is_extern, |
100 | bounds: typ.bounds.to_vec(), | 132 | bounds: typ.bounds.to_vec(), |
@@ -156,8 +188,8 @@ impl TraitData { | |||
156 | 188 | ||
157 | #[derive(Debug, Clone, PartialEq, Eq)] | 189 | #[derive(Debug, Clone, PartialEq, Eq)] |
158 | pub struct ImplData { | 190 | pub struct ImplData { |
159 | pub target_trait: Option<TypeRef>, | 191 | pub target_trait: Option<Interned<TraitRef>>, |
160 | pub target_type: TypeRef, | 192 | pub self_ty: Interned<TypeRef>, |
161 | pub items: Vec<AssocItemId>, | 193 | pub items: Vec<AssocItemId>, |
162 | pub is_negative: bool, | 194 | pub is_negative: bool, |
163 | } | 195 | } |
@@ -169,8 +201,8 @@ impl ImplData { | |||
169 | 201 | ||
170 | let item_tree = impl_loc.id.item_tree(db); | 202 | let item_tree = impl_loc.id.item_tree(db); |
171 | let impl_def = &item_tree[impl_loc.id.value]; | 203 | let impl_def = &item_tree[impl_loc.id.value]; |
172 | let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); | 204 | let target_trait = impl_def.target_trait.clone(); |
173 | let target_type = item_tree[impl_def.target_type].clone(); | 205 | let self_ty = impl_def.self_ty.clone(); |
174 | let is_negative = impl_def.is_negative; | 206 | let is_negative = impl_def.is_negative; |
175 | let module_id = impl_loc.container; | 207 | let module_id = impl_loc.container; |
176 | let container = AssocContainerId::ImplId(id); | 208 | let container = AssocContainerId::ImplId(id); |
@@ -187,7 +219,7 @@ impl ImplData { | |||
187 | ); | 219 | ); |
188 | let items = items.into_iter().map(|(_, item)| item).collect(); | 220 | let items = items.into_iter().map(|(_, item)| item).collect(); |
189 | 221 | ||
190 | Arc::new(ImplData { target_trait, target_type, items, is_negative }) | 222 | Arc::new(ImplData { target_trait, self_ty, items, is_negative }) |
191 | } | 223 | } |
192 | } | 224 | } |
193 | 225 | ||
@@ -195,7 +227,7 @@ impl ImplData { | |||
195 | pub struct ConstData { | 227 | pub struct ConstData { |
196 | /// const _: () = (); | 228 | /// const _: () = (); |
197 | pub name: Option<Name>, | 229 | pub name: Option<Name>, |
198 | pub type_ref: TypeRef, | 230 | pub type_ref: Interned<TypeRef>, |
199 | pub visibility: RawVisibility, | 231 | pub visibility: RawVisibility, |
200 | } | 232 | } |
201 | 233 | ||
@@ -207,7 +239,7 @@ impl ConstData { | |||
207 | 239 | ||
208 | Arc::new(ConstData { | 240 | Arc::new(ConstData { |
209 | name: konst.name.clone(), | 241 | name: konst.name.clone(), |
210 | type_ref: item_tree[konst.type_ref].clone(), | 242 | type_ref: konst.type_ref.clone(), |
211 | visibility: item_tree[konst.visibility].clone(), | 243 | visibility: item_tree[konst.visibility].clone(), |
212 | }) | 244 | }) |
213 | } | 245 | } |
@@ -216,7 +248,7 @@ impl ConstData { | |||
216 | #[derive(Debug, Clone, PartialEq, Eq)] | 248 | #[derive(Debug, Clone, PartialEq, Eq)] |
217 | pub struct StaticData { | 249 | pub struct StaticData { |
218 | pub name: Option<Name>, | 250 | pub name: Option<Name>, |
219 | pub type_ref: TypeRef, | 251 | pub type_ref: Interned<TypeRef>, |
220 | pub visibility: RawVisibility, | 252 | pub visibility: RawVisibility, |
221 | pub mutable: bool, | 253 | pub mutable: bool, |
222 | pub is_extern: bool, | 254 | pub is_extern: bool, |
@@ -230,7 +262,7 @@ impl StaticData { | |||
230 | 262 | ||
231 | Arc::new(StaticData { | 263 | Arc::new(StaticData { |
232 | name: Some(statik.name.clone()), | 264 | name: Some(statik.name.clone()), |
233 | type_ref: item_tree[statik.type_ref].clone(), | 265 | type_ref: statik.type_ref.clone(), |
234 | visibility: item_tree[statik.visibility].clone(), | 266 | visibility: item_tree[statik.visibility].clone(), |
235 | mutable: statik.mutable, | 267 | mutable: statik.mutable, |
236 | is_extern: statik.is_extern, | 268 | is_extern: statik.is_extern, |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 068b2ee38..7eadc8e0d 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -2,9 +2,10 @@ | |||
2 | use std::sync::Arc; | 2 | use std::sync::Arc; |
3 | 3 | ||
4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; | 4 | use base_db::{salsa, CrateId, SourceDatabase, Upcast}; |
5 | use either::Either; | ||
5 | use hir_expand::{db::AstDatabase, HirFileId}; | 6 | use hir_expand::{db::AstDatabase, HirFileId}; |
6 | use la_arena::ArenaMap; | 7 | use la_arena::ArenaMap; |
7 | use syntax::SmolStr; | 8 | use syntax::{ast, AstPtr, SmolStr}; |
8 | 9 | ||
9 | use crate::{ | 10 | use crate::{ |
10 | adt::{EnumData, StructData}, | 11 | adt::{EnumData, StructData}, |
@@ -13,6 +14,7 @@ use crate::{ | |||
13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, | 14 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, |
14 | generics::GenericParams, | 15 | generics::GenericParams, |
15 | import_map::ImportMap, | 16 | import_map::ImportMap, |
17 | intern::Interned, | ||
16 | item_tree::ItemTree, | 18 | item_tree::ItemTree, |
17 | lang_item::{LangItemTarget, LangItems}, | 19 | lang_item::{LangItemTarget, LangItems}, |
18 | nameres::DefMap, | 20 | nameres::DefMap, |
@@ -113,7 +115,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
113 | fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; | 115 | fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; |
114 | 116 | ||
115 | #[salsa::invoke(GenericParams::generic_params_query)] | 117 | #[salsa::invoke(GenericParams::generic_params_query)] |
116 | fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; | 118 | fn generic_params(&self, def: GenericDefId) -> Interned<GenericParams>; |
117 | 119 | ||
118 | #[salsa::invoke(Attrs::variants_attrs_query)] | 120 | #[salsa::invoke(Attrs::variants_attrs_query)] |
119 | fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; | 121 | fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; |
@@ -121,6 +123,18 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
121 | #[salsa::invoke(Attrs::fields_attrs_query)] | 123 | #[salsa::invoke(Attrs::fields_attrs_query)] |
122 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; | 124 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; |
123 | 125 | ||
126 | #[salsa::invoke(crate::attr::variants_attrs_source_map)] | ||
127 | fn variants_attrs_source_map( | ||
128 | &self, | ||
129 | def: EnumId, | ||
130 | ) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>>; | ||
131 | |||
132 | #[salsa::invoke(crate::attr::fields_attrs_source_map)] | ||
133 | fn fields_attrs_source_map( | ||
134 | &self, | ||
135 | def: VariantId, | ||
136 | ) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>>; | ||
137 | |||
124 | #[salsa::invoke(AttrsWithOwner::attrs_query)] | 138 | #[salsa::invoke(AttrsWithOwner::attrs_query)] |
125 | fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; | 139 | fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; |
126 | 140 | ||
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs index 97abf8653..a71ae2668 100644 --- a/crates/hir_def/src/diagnostics.rs +++ b/crates/hir_def/src/diagnostics.rs | |||
@@ -8,7 +8,7 @@ use hir_expand::diagnostics::{Diagnostic, DiagnosticCode, DiagnosticSink}; | |||
8 | use hir_expand::{HirFileId, InFile}; | 8 | use hir_expand::{HirFileId, InFile}; |
9 | use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; | 9 | use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange}; |
10 | 10 | ||
11 | use crate::{db::DefDatabase, DefWithBodyId}; | 11 | use crate::{db::DefDatabase, path::ModPath, DefWithBodyId}; |
12 | 12 | ||
13 | pub fn validate_body(db: &dyn DefDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) { | 13 | pub fn validate_body(db: &dyn DefDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) { |
14 | let source_map = db.body_with_source_map(owner).1; | 14 | let source_map = db.body_with_source_map(owner).1; |
@@ -103,6 +103,7 @@ impl Diagnostic for UnresolvedImport { | |||
103 | pub struct UnresolvedMacroCall { | 103 | pub struct UnresolvedMacroCall { |
104 | pub file: HirFileId, | 104 | pub file: HirFileId, |
105 | pub node: AstPtr<ast::MacroCall>, | 105 | pub node: AstPtr<ast::MacroCall>, |
106 | pub path: ModPath, | ||
106 | } | 107 | } |
107 | 108 | ||
108 | impl Diagnostic for UnresolvedMacroCall { | 109 | impl Diagnostic for UnresolvedMacroCall { |
@@ -110,7 +111,7 @@ impl Diagnostic for UnresolvedMacroCall { | |||
110 | DiagnosticCode("unresolved-macro-call") | 111 | DiagnosticCode("unresolved-macro-call") |
111 | } | 112 | } |
112 | fn message(&self) -> String { | 113 | fn message(&self) -> String { |
113 | "unresolved macro call".to_string() | 114 | format!("unresolved macro `{}!`", self.path) |
114 | } | 115 | } |
115 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | 116 | fn display_source(&self) -> InFile<SyntaxNodePtr> { |
116 | InFile::new(self.file, self.node.clone().into()) | 117 | InFile::new(self.file, self.node.clone().into()) |
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs index 6c7376fad..b4ad984bd 100644 --- a/crates/hir_def/src/expr.rs +++ b/crates/hir_def/src/expr.rs | |||
@@ -18,6 +18,7 @@ use syntax::ast::RangeOp; | |||
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, | 20 | builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, |
21 | intern::Interned, | ||
21 | path::{GenericArgs, Path}, | 22 | path::{GenericArgs, Path}, |
22 | type_ref::{Mutability, Rawness, TypeRef}, | 23 | type_ref::{Mutability, Rawness, TypeRef}, |
23 | BlockId, | 24 | BlockId, |
@@ -86,7 +87,7 @@ pub enum Expr { | |||
86 | receiver: ExprId, | 87 | receiver: ExprId, |
87 | method_name: Name, | 88 | method_name: Name, |
88 | args: Vec<ExprId>, | 89 | args: Vec<ExprId>, |
89 | generic_args: Option<GenericArgs>, | 90 | generic_args: Option<Box<GenericArgs>>, |
90 | }, | 91 | }, |
91 | Match { | 92 | Match { |
92 | expr: ExprId, | 93 | expr: ExprId, |
@@ -106,7 +107,7 @@ pub enum Expr { | |||
106 | expr: Option<ExprId>, | 107 | expr: Option<ExprId>, |
107 | }, | 108 | }, |
108 | RecordLit { | 109 | RecordLit { |
109 | path: Option<Path>, | 110 | path: Option<Box<Path>>, |
110 | fields: Vec<RecordLitField>, | 111 | fields: Vec<RecordLitField>, |
111 | spread: Option<ExprId>, | 112 | spread: Option<ExprId>, |
112 | }, | 113 | }, |
@@ -131,7 +132,7 @@ pub enum Expr { | |||
131 | }, | 132 | }, |
132 | Cast { | 133 | Cast { |
133 | expr: ExprId, | 134 | expr: ExprId, |
134 | type_ref: TypeRef, | 135 | type_ref: Interned<TypeRef>, |
135 | }, | 136 | }, |
136 | Ref { | 137 | Ref { |
137 | expr: ExprId, | 138 | expr: ExprId, |
@@ -161,8 +162,8 @@ pub enum Expr { | |||
161 | }, | 162 | }, |
162 | Lambda { | 163 | Lambda { |
163 | args: Vec<PatId>, | 164 | args: Vec<PatId>, |
164 | arg_types: Vec<Option<TypeRef>>, | 165 | arg_types: Vec<Option<Interned<TypeRef>>>, |
165 | ret_type: Option<TypeRef>, | 166 | ret_type: Option<Interned<TypeRef>>, |
166 | body: ExprId, | 167 | body: ExprId, |
167 | }, | 168 | }, |
168 | Tuple { | 169 | Tuple { |
@@ -240,7 +241,7 @@ pub struct RecordLitField { | |||
240 | 241 | ||
241 | #[derive(Debug, Clone, Eq, PartialEq)] | 242 | #[derive(Debug, Clone, Eq, PartialEq)] |
242 | pub enum Statement { | 243 | pub enum Statement { |
243 | Let { pat: PatId, type_ref: Option<TypeRef>, initializer: Option<ExprId> }, | 244 | Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> }, |
244 | Expr(ExprId), | 245 | Expr(ExprId), |
245 | } | 246 | } |
246 | 247 | ||
@@ -412,13 +413,13 @@ pub enum Pat { | |||
412 | Wild, | 413 | Wild, |
413 | Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, | 414 | Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, |
414 | Or(Vec<PatId>), | 415 | Or(Vec<PatId>), |
415 | Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, | 416 | Record { path: Option<Box<Path>>, args: Vec<RecordFieldPat>, ellipsis: bool }, |
416 | Range { start: ExprId, end: ExprId }, | 417 | Range { start: ExprId, end: ExprId }, |
417 | Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> }, | 418 | Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> }, |
418 | Path(Path), | 419 | Path(Box<Path>), |
419 | Lit(ExprId), | 420 | Lit(ExprId), |
420 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, | 421 | Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, |
421 | TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, | 422 | TupleStruct { path: Option<Box<Path>>, args: Vec<PatId>, ellipsis: Option<usize> }, |
422 | Ref { pat: PatId, mutability: Mutability }, | 423 | Ref { pat: PatId, mutability: Mutability }, |
423 | Box { inner: PatId }, | 424 | Box { inner: PatId }, |
424 | ConstBlock(ExprId), | 425 | ConstBlock(ExprId), |
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs index 109d3552f..2c4bbe585 100644 --- a/crates/hir_def/src/find_path.rs +++ b/crates/hir_def/src/find_path.rs | |||
@@ -425,106 +425,142 @@ mod tests { | |||
425 | 425 | ||
426 | #[test] | 426 | #[test] |
427 | fn same_module() { | 427 | fn same_module() { |
428 | let code = r#" | 428 | check_found_path( |
429 | //- /main.rs | 429 | r#" |
430 | struct S; | 430 | struct S; |
431 | $0 | 431 | $0 |
432 | "#; | 432 | "#, |
433 | check_found_path(code, "S", "S", "crate::S", "self::S"); | 433 | "S", |
434 | "S", | ||
435 | "crate::S", | ||
436 | "self::S", | ||
437 | ); | ||
434 | } | 438 | } |
435 | 439 | ||
436 | #[test] | 440 | #[test] |
437 | fn enum_variant() { | 441 | fn enum_variant() { |
438 | let code = r#" | 442 | check_found_path( |
439 | //- /main.rs | 443 | r#" |
440 | enum E { A } | 444 | enum E { A } |
441 | $0 | 445 | $0 |
442 | "#; | 446 | "#, |
443 | check_found_path(code, "E::A", "E::A", "E::A", "E::A"); | 447 | "E::A", |
448 | "E::A", | ||
449 | "E::A", | ||
450 | "E::A", | ||
451 | ); | ||
444 | } | 452 | } |
445 | 453 | ||
446 | #[test] | 454 | #[test] |
447 | fn sub_module() { | 455 | fn sub_module() { |
448 | let code = r#" | 456 | check_found_path( |
449 | //- /main.rs | 457 | r#" |
450 | mod foo { | 458 | mod foo { |
451 | pub struct S; | 459 | pub struct S; |
452 | } | 460 | } |
453 | $0 | 461 | $0 |
454 | "#; | 462 | "#, |
455 | check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S"); | 463 | "foo::S", |
464 | "foo::S", | ||
465 | "crate::foo::S", | ||
466 | "self::foo::S", | ||
467 | ); | ||
456 | } | 468 | } |
457 | 469 | ||
458 | #[test] | 470 | #[test] |
459 | fn super_module() { | 471 | fn super_module() { |
460 | let code = r#" | 472 | check_found_path( |
461 | //- /main.rs | 473 | r#" |
462 | mod foo; | 474 | //- /main.rs |
463 | //- /foo.rs | 475 | mod foo; |
464 | mod bar; | 476 | //- /foo.rs |
465 | struct S; | 477 | mod bar; |
466 | //- /foo/bar.rs | 478 | struct S; |
467 | $0 | 479 | //- /foo/bar.rs |
468 | "#; | 480 | $0 |
469 | check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S"); | 481 | "#, |
482 | "super::S", | ||
483 | "super::S", | ||
484 | "crate::foo::S", | ||
485 | "super::S", | ||
486 | ); | ||
470 | } | 487 | } |
471 | 488 | ||
472 | #[test] | 489 | #[test] |
473 | fn self_module() { | 490 | fn self_module() { |
474 | let code = r#" | 491 | check_found_path( |
475 | //- /main.rs | 492 | r#" |
476 | mod foo; | 493 | //- /main.rs |
477 | //- /foo.rs | 494 | mod foo; |
478 | $0 | 495 | //- /foo.rs |
479 | "#; | 496 | $0 |
480 | check_found_path(code, "self", "self", "crate::foo", "self"); | 497 | "#, |
498 | "self", | ||
499 | "self", | ||
500 | "crate::foo", | ||
501 | "self", | ||
502 | ); | ||
481 | } | 503 | } |
482 | 504 | ||
483 | #[test] | 505 | #[test] |
484 | fn crate_root() { | 506 | fn crate_root() { |
485 | let code = r#" | 507 | check_found_path( |
486 | //- /main.rs | 508 | r#" |
487 | mod foo; | 509 | //- /main.rs |
488 | //- /foo.rs | 510 | mod foo; |
489 | $0 | 511 | //- /foo.rs |
490 | "#; | 512 | $0 |
491 | check_found_path(code, "crate", "crate", "crate", "crate"); | 513 | "#, |
514 | "crate", | ||
515 | "crate", | ||
516 | "crate", | ||
517 | "crate", | ||
518 | ); | ||
492 | } | 519 | } |
493 | 520 | ||
494 | #[test] | 521 | #[test] |
495 | fn same_crate() { | 522 | fn same_crate() { |
496 | let code = r#" | 523 | check_found_path( |
497 | //- /main.rs | 524 | r#" |
498 | mod foo; | 525 | //- /main.rs |
499 | struct S; | 526 | mod foo; |
500 | //- /foo.rs | 527 | struct S; |
501 | $0 | 528 | //- /foo.rs |
502 | "#; | 529 | $0 |
503 | check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S"); | 530 | "#, |
531 | "crate::S", | ||
532 | "crate::S", | ||
533 | "crate::S", | ||
534 | "crate::S", | ||
535 | ); | ||
504 | } | 536 | } |
505 | 537 | ||
506 | #[test] | 538 | #[test] |
507 | fn different_crate() { | 539 | fn different_crate() { |
508 | let code = r#" | 540 | check_found_path( |
509 | //- /main.rs crate:main deps:std | 541 | r#" |
510 | $0 | 542 | //- /main.rs crate:main deps:std |
511 | //- /std.rs crate:std | 543 | $0 |
512 | pub struct S; | 544 | //- /std.rs crate:std |
513 | "#; | 545 | pub struct S; |
514 | check_found_path(code, "std::S", "std::S", "std::S", "std::S"); | 546 | "#, |
547 | "std::S", | ||
548 | "std::S", | ||
549 | "std::S", | ||
550 | "std::S", | ||
551 | ); | ||
515 | } | 552 | } |
516 | 553 | ||
517 | #[test] | 554 | #[test] |
518 | fn different_crate_renamed() { | 555 | fn different_crate_renamed() { |
519 | let code = r#" | ||
520 | //- /main.rs crate:main deps:std | ||
521 | extern crate std as std_renamed; | ||
522 | $0 | ||
523 | //- /std.rs crate:std | ||
524 | pub struct S; | ||
525 | "#; | ||
526 | check_found_path( | 556 | check_found_path( |
527 | code, | 557 | r#" |
558 | //- /main.rs crate:main deps:std | ||
559 | extern crate std as std_renamed; | ||
560 | $0 | ||
561 | //- /std.rs crate:std | ||
562 | pub struct S; | ||
563 | "#, | ||
528 | "std_renamed::S", | 564 | "std_renamed::S", |
529 | "std_renamed::S", | 565 | "std_renamed::S", |
530 | "std_renamed::S", | 566 | "std_renamed::S", |
@@ -537,41 +573,38 @@ mod tests { | |||
537 | cov_mark::check!(partially_imported); | 573 | cov_mark::check!(partially_imported); |
538 | // Tests that short paths are used even for external items, when parts of the path are | 574 | // Tests that short paths are used even for external items, when parts of the path are |
539 | // already in scope. | 575 | // already in scope. |
540 | let code = r#" | 576 | check_found_path( |
541 | //- /main.rs crate:main deps:syntax | 577 | r#" |
578 | //- /main.rs crate:main deps:syntax | ||
542 | 579 | ||
543 | use syntax::ast; | 580 | use syntax::ast; |
544 | $0 | 581 | $0 |
545 | 582 | ||
546 | //- /lib.rs crate:syntax | 583 | //- /lib.rs crate:syntax |
547 | pub mod ast { | 584 | pub mod ast { |
548 | pub enum ModuleItem { | 585 | pub enum ModuleItem { |
549 | A, B, C, | 586 | A, B, C, |
550 | } | 587 | } |
551 | } | 588 | } |
552 | "#; | 589 | "#, |
553 | check_found_path( | ||
554 | code, | ||
555 | "ast::ModuleItem", | 590 | "ast::ModuleItem", |
556 | "syntax::ast::ModuleItem", | 591 | "syntax::ast::ModuleItem", |
557 | "syntax::ast::ModuleItem", | 592 | "syntax::ast::ModuleItem", |
558 | "syntax::ast::ModuleItem", | 593 | "syntax::ast::ModuleItem", |
559 | ); | 594 | ); |
560 | 595 | ||
561 | let code = r#" | ||
562 | //- /main.rs crate:main deps:syntax | ||
563 | |||
564 | $0 | ||
565 | |||
566 | //- /lib.rs crate:syntax | ||
567 | pub mod ast { | ||
568 | pub enum ModuleItem { | ||
569 | A, B, C, | ||
570 | } | ||
571 | } | ||
572 | "#; | ||
573 | check_found_path( | 596 | check_found_path( |
574 | code, | 597 | r#" |
598 | //- /main.rs crate:main deps:syntax | ||
599 | $0 | ||
600 | |||
601 | //- /lib.rs crate:syntax | ||
602 | pub mod ast { | ||
603 | pub enum ModuleItem { | ||
604 | A, B, C, | ||
605 | } | ||
606 | } | ||
607 | "#, | ||
575 | "syntax::ast::ModuleItem", | 608 | "syntax::ast::ModuleItem", |
576 | "syntax::ast::ModuleItem", | 609 | "syntax::ast::ModuleItem", |
577 | "syntax::ast::ModuleItem", | 610 | "syntax::ast::ModuleItem", |
@@ -581,68 +614,86 @@ mod tests { | |||
581 | 614 | ||
582 | #[test] | 615 | #[test] |
583 | fn same_crate_reexport() { | 616 | fn same_crate_reexport() { |
584 | let code = r#" | 617 | check_found_path( |
585 | //- /main.rs | 618 | r#" |
586 | mod bar { | 619 | mod bar { |
587 | mod foo { pub(super) struct S; } | 620 | mod foo { pub(super) struct S; } |
588 | pub(crate) use foo::*; | 621 | pub(crate) use foo::*; |
589 | } | 622 | } |
590 | $0 | 623 | $0 |
591 | "#; | 624 | "#, |
592 | check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S"); | 625 | "bar::S", |
626 | "bar::S", | ||
627 | "crate::bar::S", | ||
628 | "self::bar::S", | ||
629 | ); | ||
593 | } | 630 | } |
594 | 631 | ||
595 | #[test] | 632 | #[test] |
596 | fn same_crate_reexport_rename() { | 633 | fn same_crate_reexport_rename() { |
597 | let code = r#" | 634 | check_found_path( |
598 | //- /main.rs | 635 | r#" |
599 | mod bar { | 636 | mod bar { |
600 | mod foo { pub(super) struct S; } | 637 | mod foo { pub(super) struct S; } |
601 | pub(crate) use foo::S as U; | 638 | pub(crate) use foo::S as U; |
602 | } | 639 | } |
603 | $0 | 640 | $0 |
604 | "#; | 641 | "#, |
605 | check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U"); | 642 | "bar::U", |
643 | "bar::U", | ||
644 | "crate::bar::U", | ||
645 | "self::bar::U", | ||
646 | ); | ||
606 | } | 647 | } |
607 | 648 | ||
608 | #[test] | 649 | #[test] |
609 | fn different_crate_reexport() { | 650 | fn different_crate_reexport() { |
610 | let code = r#" | 651 | check_found_path( |
611 | //- /main.rs crate:main deps:std | 652 | r#" |
612 | $0 | 653 | //- /main.rs crate:main deps:std |
613 | //- /std.rs crate:std deps:core | 654 | $0 |
614 | pub use core::S; | 655 | //- /std.rs crate:std deps:core |
615 | //- /core.rs crate:core | 656 | pub use core::S; |
616 | pub struct S; | 657 | //- /core.rs crate:core |
617 | "#; | 658 | pub struct S; |
618 | check_found_path(code, "std::S", "std::S", "std::S", "std::S"); | 659 | "#, |
660 | "std::S", | ||
661 | "std::S", | ||
662 | "std::S", | ||
663 | "std::S", | ||
664 | ); | ||
619 | } | 665 | } |
620 | 666 | ||
621 | #[test] | 667 | #[test] |
622 | fn prelude() { | 668 | fn prelude() { |
623 | let code = r#" | 669 | check_found_path( |
624 | //- /main.rs crate:main deps:std | 670 | r#" |
625 | $0 | 671 | //- /main.rs crate:main deps:std |
626 | //- /std.rs crate:std | 672 | $0 |
627 | pub mod prelude { pub struct S; } | 673 | //- /std.rs crate:std |
628 | #[prelude_import] | 674 | pub mod prelude { pub struct S; } |
629 | pub use prelude::*; | 675 | #[prelude_import] |
630 | "#; | 676 | pub use prelude::*; |
631 | check_found_path(code, "S", "S", "S", "S"); | 677 | "#, |
678 | "S", | ||
679 | "S", | ||
680 | "S", | ||
681 | "S", | ||
682 | ); | ||
632 | } | 683 | } |
633 | 684 | ||
634 | #[test] | 685 | #[test] |
635 | fn enum_variant_from_prelude() { | 686 | fn enum_variant_from_prelude() { |
636 | let code = r#" | 687 | let code = r#" |
637 | //- /main.rs crate:main deps:std | 688 | //- /main.rs crate:main deps:std |
638 | $0 | 689 | $0 |
639 | //- /std.rs crate:std | 690 | //- /std.rs crate:std |
640 | pub mod prelude { | 691 | pub mod prelude { |
641 | pub enum Option<T> { Some(T), None } | 692 | pub enum Option<T> { Some(T), None } |
642 | pub use Option::*; | 693 | pub use Option::*; |
643 | } | 694 | } |
644 | #[prelude_import] | 695 | #[prelude_import] |
645 | pub use prelude::*; | 696 | pub use prelude::*; |
646 | "#; | 697 | "#; |
647 | check_found_path(code, "None", "None", "None", "None"); | 698 | check_found_path(code, "None", "None", "None", "None"); |
648 | check_found_path(code, "Some", "Some", "Some", "Some"); | 699 | check_found_path(code, "Some", "Some", "Some", "Some"); |
@@ -650,71 +701,85 @@ mod tests { | |||
650 | 701 | ||
651 | #[test] | 702 | #[test] |
652 | fn shortest_path() { | 703 | fn shortest_path() { |
653 | let code = r#" | 704 | check_found_path( |
654 | //- /main.rs | 705 | r#" |
655 | pub mod foo; | 706 | //- /main.rs |
656 | pub mod baz; | 707 | pub mod foo; |
657 | struct S; | 708 | pub mod baz; |
658 | $0 | 709 | struct S; |
659 | //- /foo.rs | 710 | $0 |
660 | pub mod bar { pub struct S; } | 711 | //- /foo.rs |
661 | //- /baz.rs | 712 | pub mod bar { pub struct S; } |
662 | pub use crate::foo::bar::S; | 713 | //- /baz.rs |
663 | "#; | 714 | pub use crate::foo::bar::S; |
664 | check_found_path(code, "baz::S", "baz::S", "crate::baz::S", "self::baz::S"); | 715 | "#, |
716 | "baz::S", | ||
717 | "baz::S", | ||
718 | "crate::baz::S", | ||
719 | "self::baz::S", | ||
720 | ); | ||
665 | } | 721 | } |
666 | 722 | ||
667 | #[test] | 723 | #[test] |
668 | fn discount_private_imports() { | 724 | fn discount_private_imports() { |
669 | let code = r#" | 725 | check_found_path( |
670 | //- /main.rs | 726 | r#" |
671 | mod foo; | 727 | //- /main.rs |
672 | pub mod bar { pub struct S; } | 728 | mod foo; |
673 | use bar::S; | 729 | pub mod bar { pub struct S; } |
674 | //- /foo.rs | 730 | use bar::S; |
675 | $0 | 731 | //- /foo.rs |
676 | "#; | 732 | $0 |
677 | // crate::S would be shorter, but using private imports seems wrong | 733 | "#, |
678 | check_found_path(code, "crate::bar::S", "crate::bar::S", "crate::bar::S", "crate::bar::S"); | 734 | // crate::S would be shorter, but using private imports seems wrong |
735 | "crate::bar::S", | ||
736 | "crate::bar::S", | ||
737 | "crate::bar::S", | ||
738 | "crate::bar::S", | ||
739 | ); | ||
679 | } | 740 | } |
680 | 741 | ||
681 | #[test] | 742 | #[test] |
682 | fn import_cycle() { | 743 | fn import_cycle() { |
683 | let code = r#" | 744 | check_found_path( |
684 | //- /main.rs | 745 | r#" |
685 | pub mod foo; | 746 | //- /main.rs |
686 | pub mod bar; | 747 | pub mod foo; |
687 | pub mod baz; | 748 | pub mod bar; |
688 | //- /bar.rs | 749 | pub mod baz; |
689 | $0 | 750 | //- /bar.rs |
690 | //- /foo.rs | 751 | $0 |
691 | pub use super::baz; | 752 | //- /foo.rs |
692 | pub struct S; | 753 | pub use super::baz; |
693 | //- /baz.rs | 754 | pub struct S; |
694 | pub use super::foo; | 755 | //- /baz.rs |
695 | "#; | 756 | pub use super::foo; |
696 | check_found_path(code, "crate::foo::S", "crate::foo::S", "crate::foo::S", "crate::foo::S"); | 757 | "#, |
758 | "crate::foo::S", | ||
759 | "crate::foo::S", | ||
760 | "crate::foo::S", | ||
761 | "crate::foo::S", | ||
762 | ); | ||
697 | } | 763 | } |
698 | 764 | ||
699 | #[test] | 765 | #[test] |
700 | fn prefer_std_paths_over_alloc() { | 766 | fn prefer_std_paths_over_alloc() { |
701 | cov_mark::check!(prefer_std_paths); | 767 | cov_mark::check!(prefer_std_paths); |
702 | let code = r#" | 768 | check_found_path( |
703 | //- /main.rs crate:main deps:alloc,std | 769 | r#" |
704 | $0 | 770 | //- /main.rs crate:main deps:alloc,std |
771 | $0 | ||
705 | 772 | ||
706 | //- /std.rs crate:std deps:alloc | 773 | //- /std.rs crate:std deps:alloc |
707 | pub mod sync { | 774 | pub mod sync { |
708 | pub use alloc::sync::Arc; | 775 | pub use alloc::sync::Arc; |
709 | } | 776 | } |
710 | 777 | ||
711 | //- /zzz.rs crate:alloc | 778 | //- /zzz.rs crate:alloc |
712 | pub mod sync { | 779 | pub mod sync { |
713 | pub struct Arc; | 780 | pub struct Arc; |
714 | } | 781 | } |
715 | "#; | 782 | "#, |
716 | check_found_path( | ||
717 | code, | ||
718 | "std::sync::Arc", | 783 | "std::sync::Arc", |
719 | "std::sync::Arc", | 784 | "std::sync::Arc", |
720 | "std::sync::Arc", | 785 | "std::sync::Arc", |
@@ -725,26 +790,25 @@ mod tests { | |||
725 | #[test] | 790 | #[test] |
726 | fn prefer_core_paths_over_std() { | 791 | fn prefer_core_paths_over_std() { |
727 | cov_mark::check!(prefer_no_std_paths); | 792 | cov_mark::check!(prefer_no_std_paths); |
728 | let code = r#" | 793 | check_found_path( |
729 | //- /main.rs crate:main deps:core,std | 794 | r#" |
730 | #![no_std] | 795 | //- /main.rs crate:main deps:core,std |
796 | #![no_std] | ||
731 | 797 | ||
732 | $0 | 798 | $0 |
733 | 799 | ||
734 | //- /std.rs crate:std deps:core | 800 | //- /std.rs crate:std deps:core |
735 | 801 | ||
736 | pub mod fmt { | 802 | pub mod fmt { |
737 | pub use core::fmt::Error; | 803 | pub use core::fmt::Error; |
738 | } | 804 | } |
739 | 805 | ||
740 | //- /zzz.rs crate:core | 806 | //- /zzz.rs crate:core |
741 | 807 | ||
742 | pub mod fmt { | 808 | pub mod fmt { |
743 | pub struct Error; | 809 | pub struct Error; |
744 | } | 810 | } |
745 | "#; | 811 | "#, |
746 | check_found_path( | ||
747 | code, | ||
748 | "core::fmt::Error", | 812 | "core::fmt::Error", |
749 | "core::fmt::Error", | 813 | "core::fmt::Error", |
750 | "core::fmt::Error", | 814 | "core::fmt::Error", |
@@ -754,26 +818,25 @@ mod tests { | |||
754 | 818 | ||
755 | #[test] | 819 | #[test] |
756 | fn prefer_alloc_paths_over_std() { | 820 | fn prefer_alloc_paths_over_std() { |
757 | let code = r#" | 821 | check_found_path( |
758 | //- /main.rs crate:main deps:alloc,std | 822 | r#" |
759 | #![no_std] | 823 | //- /main.rs crate:main deps:alloc,std |
824 | #![no_std] | ||
760 | 825 | ||
761 | $0 | 826 | $0 |
762 | 827 | ||
763 | //- /std.rs crate:std deps:alloc | 828 | //- /std.rs crate:std deps:alloc |
764 | 829 | ||
765 | pub mod sync { | 830 | pub mod sync { |
766 | pub use alloc::sync::Arc; | 831 | pub use alloc::sync::Arc; |
767 | } | 832 | } |
768 | 833 | ||
769 | //- /zzz.rs crate:alloc | 834 | //- /zzz.rs crate:alloc |
770 | 835 | ||
771 | pub mod sync { | 836 | pub mod sync { |
772 | pub struct Arc; | 837 | pub struct Arc; |
773 | } | 838 | } |
774 | "#; | 839 | "#, |
775 | check_found_path( | ||
776 | code, | ||
777 | "alloc::sync::Arc", | 840 | "alloc::sync::Arc", |
778 | "alloc::sync::Arc", | 841 | "alloc::sync::Arc", |
779 | "alloc::sync::Arc", | 842 | "alloc::sync::Arc", |
@@ -783,20 +846,19 @@ mod tests { | |||
783 | 846 | ||
784 | #[test] | 847 | #[test] |
785 | fn prefer_shorter_paths_if_not_alloc() { | 848 | fn prefer_shorter_paths_if_not_alloc() { |
786 | let code = r#" | 849 | check_found_path( |
787 | //- /main.rs crate:main deps:megaalloc,std | 850 | r#" |
788 | $0 | 851 | //- /main.rs crate:main deps:megaalloc,std |
852 | $0 | ||
789 | 853 | ||
790 | //- /std.rs crate:std deps:megaalloc | 854 | //- /std.rs crate:std deps:megaalloc |
791 | pub mod sync { | 855 | pub mod sync { |
792 | pub use megaalloc::sync::Arc; | 856 | pub use megaalloc::sync::Arc; |
793 | } | 857 | } |
794 | 858 | ||
795 | //- /zzz.rs crate:megaalloc | 859 | //- /zzz.rs crate:megaalloc |
796 | pub struct Arc; | 860 | pub struct Arc; |
797 | "#; | 861 | "#, |
798 | check_found_path( | ||
799 | code, | ||
800 | "megaalloc::Arc", | 862 | "megaalloc::Arc", |
801 | "megaalloc::Arc", | 863 | "megaalloc::Arc", |
802 | "megaalloc::Arc", | 864 | "megaalloc::Arc", |
@@ -807,12 +869,11 @@ mod tests { | |||
807 | #[test] | 869 | #[test] |
808 | fn builtins_are_in_scope() { | 870 | fn builtins_are_in_scope() { |
809 | let code = r#" | 871 | let code = r#" |
810 | //- /main.rs | 872 | $0 |
811 | $0 | ||
812 | 873 | ||
813 | pub mod primitive { | 874 | pub mod primitive { |
814 | pub use u8; | 875 | pub use u8; |
815 | } | 876 | } |
816 | "#; | 877 | "#; |
817 | check_found_path(code, "u8", "u8", "u8", "u8"); | 878 | check_found_path(code, "u8", "u8", "u8", "u8"); |
818 | check_found_path(code, "u16", "u16", "u16", "u16"); | 879 | check_found_path(code, "u16", "u16", "u16", "u16"); |
@@ -822,10 +883,10 @@ mod tests { | |||
822 | fn inner_items() { | 883 | fn inner_items() { |
823 | check_found_path( | 884 | check_found_path( |
824 | r#" | 885 | r#" |
825 | fn main() { | 886 | fn main() { |
826 | struct Inner {} | 887 | struct Inner {} |
827 | $0 | 888 | $0 |
828 | } | 889 | } |
829 | "#, | 890 | "#, |
830 | "Inner", | 891 | "Inner", |
831 | "Inner", | 892 | "Inner", |
@@ -838,12 +899,12 @@ mod tests { | |||
838 | fn inner_items_from_outer_scope() { | 899 | fn inner_items_from_outer_scope() { |
839 | check_found_path( | 900 | check_found_path( |
840 | r#" | 901 | r#" |
841 | fn main() { | 902 | fn main() { |
842 | struct Struct {} | 903 | struct Struct {} |
843 | { | 904 | { |
844 | $0 | 905 | $0 |
845 | } | 906 | } |
846 | } | 907 | } |
847 | "#, | 908 | "#, |
848 | "Struct", | 909 | "Struct", |
849 | "Struct", | 910 | "Struct", |
@@ -857,14 +918,14 @@ mod tests { | |||
857 | cov_mark::check!(prefixed_in_block_expression); | 918 | cov_mark::check!(prefixed_in_block_expression); |
858 | check_found_path( | 919 | check_found_path( |
859 | r#" | 920 | r#" |
860 | fn main() { | 921 | fn main() { |
861 | mod module { | 922 | mod module { |
862 | struct Struct {} | 923 | struct Struct {} |
863 | } | 924 | } |
864 | { | 925 | { |
865 | $0 | 926 | $0 |
866 | } | 927 | } |
867 | } | 928 | } |
868 | "#, | 929 | "#, |
869 | "module::Struct", | 930 | "module::Struct", |
870 | "module::Struct", | 931 | "module::Struct", |
@@ -877,14 +938,14 @@ mod tests { | |||
877 | fn outer_items_with_inner_items_present() { | 938 | fn outer_items_with_inner_items_present() { |