diff options
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/src/autoderef.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/db.rs | 19 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 15 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 69 | ||||
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 42 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 199 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/method_resolution.rs | 37 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/simple.rs | 18 | ||||
-rw-r--r-- | crates/hir_ty/src/utils.rs | 2 |
10 files changed, 377 insertions, 27 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index 71bc436e6..2c07494a9 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -36,6 +36,7 @@ pub(crate) fn deref( | |||
36 | krate: CrateId, | 36 | krate: CrateId, |
37 | ty: InEnvironment<&Canonical<Ty>>, | 37 | ty: InEnvironment<&Canonical<Ty>>, |
38 | ) -> Option<Canonical<Ty>> { | 38 | ) -> Option<Canonical<Ty>> { |
39 | let _p = profile::span("deref"); | ||
39 | if let Some(derefed) = builtin_deref(&ty.goal.value) { | 40 | if let Some(derefed) = builtin_deref(&ty.goal.value) { |
40 | Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) | 41 | Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) |
41 | } else { | 42 | } else { |
@@ -56,6 +57,7 @@ fn deref_by_trait( | |||
56 | krate: CrateId, | 57 | krate: CrateId, |
57 | ty: InEnvironment<&Canonical<Ty>>, | 58 | ty: InEnvironment<&Canonical<Ty>>, |
58 | ) -> Option<Canonical<Ty>> { | 59 | ) -> Option<Canonical<Ty>> { |
60 | let _p = profile::span("deref_by_trait"); | ||
59 | let deref_trait = match db.lang_item(krate, "deref".into())? { | 61 | let deref_trait = match db.lang_item(krate, "deref".into())? { |
60 | LangItemTarget::TraitId(it) => it, | 62 | LangItemTarget::TraitId(it) => it, |
61 | _ => return None, | 63 | _ => return None, |
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 1690926ad..cf67d4266 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -128,13 +128,21 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
128 | id: chalk_db::AssociatedTyValueId, | 128 | id: chalk_db::AssociatedTyValueId, |
129 | ) -> Arc<chalk_db::AssociatedTyValue>; | 129 | ) -> Arc<chalk_db::AssociatedTyValue>; |
130 | 130 | ||
131 | #[salsa::invoke(crate::traits::trait_solve_query)] | 131 | #[salsa::invoke(trait_solve_wait)] |
132 | #[salsa::transparent] | ||
132 | fn trait_solve( | 133 | fn trait_solve( |
133 | &self, | 134 | &self, |
134 | krate: CrateId, | 135 | krate: CrateId, |
135 | goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, | 136 | goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, |
136 | ) -> Option<crate::Solution>; | 137 | ) -> Option<crate::Solution>; |
137 | 138 | ||
139 | #[salsa::invoke(crate::traits::trait_solve_query)] | ||
140 | fn trait_solve_query( | ||
141 | &self, | ||
142 | krate: CrateId, | ||
143 | goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, | ||
144 | ) -> Option<crate::Solution>; | ||
145 | |||
138 | #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)] | 146 | #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)] |
139 | fn program_clauses_for_chalk_env( | 147 | fn program_clauses_for_chalk_env( |
140 | &self, | 148 | &self, |
@@ -156,6 +164,15 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> | |||
156 | db.infer_query(def) | 164 | db.infer_query(def) |
157 | } | 165 | } |
158 | 166 | ||
167 | fn trait_solve_wait( | ||
168 | db: &dyn HirDatabase, | ||
169 | krate: CrateId, | ||
170 | goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, | ||
171 | ) -> Option<crate::Solution> { | ||
172 | let _p = profile::span("trait_solve::wait"); | ||
173 | db.trait_solve_query(krate, goal) | ||
174 | } | ||
175 | |||
159 | #[test] | 176 | #[test] |
160 | fn hir_database_is_object_safe() { | 177 | fn hir_database_is_object_safe() { |
161 | fn _assert_object_safe(_: &dyn HirDatabase) {} | 178 | fn _assert_object_safe(_: &dyn HirDatabase) {} |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index e7c9dabc2..4fb7d9cf2 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -9,6 +9,7 @@ use std::{ | |||
9 | 9 | ||
10 | use chalk_ir::BoundVar; | 10 | use chalk_ir::BoundVar; |
11 | use hir_def::{ | 11 | use hir_def::{ |
12 | body, | ||
12 | db::DefDatabase, | 13 | db::DefDatabase, |
13 | find_path, | 14 | find_path, |
14 | generics::TypeParamProvenance, | 15 | generics::TypeParamProvenance, |
@@ -18,7 +19,7 @@ use hir_def::{ | |||
18 | visibility::Visibility, | 19 | visibility::Visibility, |
19 | AssocContainerId, Lookup, ModuleId, TraitId, | 20 | AssocContainerId, Lookup, ModuleId, TraitId, |
20 | }; | 21 | }; |
21 | use hir_expand::name::Name; | 22 | use hir_expand::{hygiene::Hygiene, name::Name}; |
22 | 23 | ||
23 | use crate::{ | 24 | use crate::{ |
24 | const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id, | 25 | const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id, |
@@ -997,6 +998,18 @@ impl HirDisplay for TypeRef { | |||
997 | write!(f, "dyn ")?; | 998 | write!(f, "dyn ")?; |
998 | f.write_joined(bounds, " + ")?; | 999 | f.write_joined(bounds, " + ")?; |
999 | } | 1000 | } |
1001 | TypeRef::Macro(macro_call) => { | ||
1002 | let macro_call = macro_call.to_node(f.db.upcast()); | ||
1003 | let ctx = body::LowerCtx::with_hygiene(&Hygiene::new_unhygienic()); | ||
1004 | match macro_call.path() { | ||
1005 | Some(path) => match Path::from_src(path, &ctx) { | ||
1006 | Some(path) => path.hir_fmt(f)?, | ||
1007 | None => write!(f, "{{macro}}")?, | ||
1008 | }, | ||
1009 | None => write!(f, "{{macro}}")?, | ||
1010 | } | ||
1011 | write!(f, "!(..)")?; | ||
1012 | } | ||
1000 | TypeRef::Error => write!(f, "{{error}}")?, | 1013 | TypeRef::Error => write!(f, "{{error}}")?, |
1001 | } | 1014 | } |
1002 | Ok(()) | 1015 | Ok(()) |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 113234fa4..0505fa4ae 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -56,6 +56,7 @@ pub use mapping::{ | |||
56 | to_foreign_def_id, to_placeholder_idx, | 56 | to_foreign_def_id, to_placeholder_idx, |
57 | }; | 57 | }; |
58 | pub use traits::TraitEnvironment; | 58 | pub use traits::TraitEnvironment; |
59 | pub use utils::all_super_traits; | ||
59 | pub use walk::TypeWalk; | 60 | pub use walk::TypeWalk; |
60 | 61 | ||
61 | pub use chalk_ir::{ | 62 | pub use chalk_ir::{ |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index a035686bc..7fd46becd 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -5,12 +5,14 @@ | |||
5 | //! - Building the type for an item: This happens through the `type_for_def` query. | 5 | //! - Building the type for an item: This happens through the `type_for_def` query. |
6 | //! | 6 | //! |
7 | //! This usually involves resolving names, collecting generic arguments etc. | 7 | //! This usually involves resolving names, collecting generic arguments etc. |
8 | use std::cell::{Cell, RefCell}; | ||
8 | use std::{iter, sync::Arc}; | 9 | use std::{iter, sync::Arc}; |
9 | 10 | ||
10 | use base_db::CrateId; | 11 | use base_db::CrateId; |
11 | use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety}; | 12 | use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety}; |
12 | use hir_def::{ | 13 | use hir_def::{ |
13 | adt::StructKind, | 14 | adt::StructKind, |
15 | body::{Expander, LowerCtx}, | ||
14 | builtin_type::BuiltinType, | 16 | builtin_type::BuiltinType, |
15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, | 17 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, |
16 | path::{GenericArg, Path, PathSegment, PathSegments}, | 18 | path::{GenericArg, Path, PathSegment, PathSegments}, |
@@ -20,10 +22,11 @@ use hir_def::{ | |||
20 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, | 22 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, |
21 | TypeAliasId, TypeParamId, UnionId, VariantId, | 23 | TypeAliasId, TypeParamId, UnionId, VariantId, |
22 | }; | 24 | }; |
23 | use hir_expand::name::Name; | 25 | use hir_expand::{name::Name, ExpandResult}; |
24 | use la_arena::ArenaMap; | 26 | use la_arena::ArenaMap; |
25 | use smallvec::SmallVec; | 27 | use smallvec::SmallVec; |
26 | use stdx::impl_from; | 28 | use stdx::impl_from; |
29 | use syntax::ast; | ||
27 | 30 | ||
28 | use crate::{ | 31 | use crate::{ |
29 | db::HirDatabase, | 32 | db::HirDatabase, |
@@ -50,7 +53,7 @@ pub struct TyLoweringContext<'a> { | |||
50 | /// possible currently, so this should be fine for now. | 53 | /// possible currently, so this should be fine for now. |
51 | pub type_param_mode: TypeParamLoweringMode, | 54 | pub type_param_mode: TypeParamLoweringMode, |
52 | pub impl_trait_mode: ImplTraitLoweringMode, | 55 | pub impl_trait_mode: ImplTraitLoweringMode, |
53 | impl_trait_counter: std::cell::Cell<u16>, | 56 | impl_trait_counter: Cell<u16>, |
54 | /// When turning `impl Trait` into opaque types, we have to collect the | 57 | /// When turning `impl Trait` into opaque types, we have to collect the |
55 | /// bounds at the same time to get the IDs correct (without becoming too | 58 | /// bounds at the same time to get the IDs correct (without becoming too |
56 | /// complicated). I don't like using interior mutability (as for the | 59 | /// complicated). I don't like using interior mutability (as for the |
@@ -59,16 +62,17 @@ pub struct TyLoweringContext<'a> { | |||
59 | /// we're grouping the mutable data (the counter and this field) together | 62 | /// we're grouping the mutable data (the counter and this field) together |
60 | /// with the immutable context (the references to the DB and resolver). | 63 | /// with the immutable context (the references to the DB and resolver). |
61 | /// Splitting this up would be a possible fix. | 64 | /// Splitting this up would be a possible fix. |
62 | opaque_type_data: std::cell::RefCell<Vec<ReturnTypeImplTrait>>, | 65 | opaque_type_data: RefCell<Vec<ReturnTypeImplTrait>>, |
66 | expander: RefCell<Option<Expander>>, | ||
63 | } | 67 | } |
64 | 68 | ||
65 | impl<'a> TyLoweringContext<'a> { | 69 | impl<'a> TyLoweringContext<'a> { |
66 | pub fn new(db: &'a dyn HirDatabase, resolver: &'a Resolver) -> Self { | 70 | pub fn new(db: &'a dyn HirDatabase, resolver: &'a Resolver) -> Self { |
67 | let impl_trait_counter = std::cell::Cell::new(0); | 71 | let impl_trait_counter = Cell::new(0); |
68 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; | 72 | let impl_trait_mode = ImplTraitLoweringMode::Disallowed; |
69 | let type_param_mode = TypeParamLoweringMode::Placeholder; | 73 | let type_param_mode = TypeParamLoweringMode::Placeholder; |
70 | let in_binders = DebruijnIndex::INNERMOST; | 74 | let in_binders = DebruijnIndex::INNERMOST; |
71 | let opaque_type_data = std::cell::RefCell::new(Vec::new()); | 75 | let opaque_type_data = RefCell::new(Vec::new()); |
72 | Self { | 76 | Self { |
73 | db, | 77 | db, |
74 | resolver, | 78 | resolver, |
@@ -77,6 +81,7 @@ impl<'a> TyLoweringContext<'a> { | |||
77 | impl_trait_counter, | 81 | impl_trait_counter, |
78 | type_param_mode, | 82 | type_param_mode, |
79 | opaque_type_data, | 83 | opaque_type_data, |
84 | expander: RefCell::new(None), | ||
80 | } | 85 | } |
81 | } | 86 | } |
82 | 87 | ||
@@ -86,15 +91,18 @@ impl<'a> TyLoweringContext<'a> { | |||
86 | f: impl FnOnce(&TyLoweringContext) -> T, | 91 | f: impl FnOnce(&TyLoweringContext) -> T, |
87 | ) -> T { | 92 | ) -> T { |
88 | let opaque_ty_data_vec = self.opaque_type_data.replace(Vec::new()); | 93 | let opaque_ty_data_vec = self.opaque_type_data.replace(Vec::new()); |
94 | let expander = self.expander.replace(None); | ||
89 | let new_ctx = Self { | 95 | let new_ctx = Self { |
90 | in_binders: debruijn, | 96 | in_binders: debruijn, |
91 | impl_trait_counter: std::cell::Cell::new(self.impl_trait_counter.get()), | 97 | impl_trait_counter: Cell::new(self.impl_trait_counter.get()), |
92 | opaque_type_data: std::cell::RefCell::new(opaque_ty_data_vec), | 98 | opaque_type_data: RefCell::new(opaque_ty_data_vec), |
99 | expander: RefCell::new(expander), | ||
93 | ..*self | 100 | ..*self |
94 | }; | 101 | }; |
95 | let result = f(&new_ctx); | 102 | let result = f(&new_ctx); |
96 | self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); | 103 | self.impl_trait_counter.set(new_ctx.impl_trait_counter.get()); |
97 | self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner()); | 104 | self.opaque_type_data.replace(new_ctx.opaque_type_data.into_inner()); |
105 | self.expander.replace(new_ctx.expander.into_inner()); | ||
98 | result | 106 | result |
99 | } | 107 | } |
100 | 108 | ||
@@ -287,6 +295,53 @@ impl<'a> TyLoweringContext<'a> { | |||
287 | } | 295 | } |
288 | } | 296 | } |
289 | } | 297 | } |
298 | TypeRef::Macro(macro_call) => { | ||
299 | let (expander, recursion_start) = { | ||
300 | let mut expander = self.expander.borrow_mut(); | ||
301 | if expander.is_some() { | ||
302 | (Some(expander), false) | ||
303 | } else { | ||
304 | if let Some(module_id) = self.resolver.module() { | ||
305 | *expander = Some(Expander::new( | ||
306 | self.db.upcast(), | ||
307 | macro_call.file_id, | ||
308 | module_id, | ||
309 | )); | ||
310 | (Some(expander), true) | ||
311 | } else { | ||
312 | (None, false) | ||
313 | } | ||
314 | } | ||
315 | }; | ||
316 | let ty = if let Some(mut expander) = expander { | ||
317 | let expander_mut = expander.as_mut().unwrap(); | ||
318 | let macro_call = macro_call.to_node(self.db.upcast()); | ||
319 | match expander_mut.enter_expand::<ast::Type>(self.db.upcast(), macro_call) { | ||
320 | Ok(ExpandResult { value: Some((mark, expanded)), .. }) => { | ||
321 | let ctx = | ||
322 | LowerCtx::new(self.db.upcast(), expander_mut.current_file_id()); | ||
323 | let type_ref = TypeRef::from_ast(&ctx, expanded); | ||
324 | |||
325 | drop(expander); | ||
326 | let ty = self.lower_ty(&type_ref); | ||
327 | |||
328 | self.expander | ||
329 | .borrow_mut() | ||
330 | .as_mut() | ||
331 | .unwrap() | ||
332 | .exit(self.db.upcast(), mark); | ||
333 | Some(ty) | ||
334 | } | ||
335 | _ => None, | ||
336 | } | ||
337 | } else { | ||
338 | None | ||
339 | }; | ||
340 | if recursion_start { | ||
341 | *self.expander.borrow_mut() = None; | ||
342 | } | ||
343 | ty.unwrap_or_else(|| TyKind::Error.intern(&Interner)) | ||
344 | } | ||
290 | TypeRef::Error => TyKind::Error.intern(&Interner), | 345 | TypeRef::Error => TyKind::Error.intern(&Interner), |
291 | }; | 346 | }; |
292 | (ty, res) | 347 | (ty, res) |
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 3693e3284..48bbcfd9f 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -246,29 +246,39 @@ pub struct InherentImpls { | |||
246 | 246 | ||
247 | impl InherentImpls { | 247 | impl InherentImpls { |
248 | pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { | 248 | pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { |
249 | let mut map: FxHashMap<_, Vec<_>> = FxHashMap::default(); | 249 | let mut impls = Self { map: FxHashMap::default() }; |
250 | 250 | ||
251 | let crate_def_map = db.crate_def_map(krate); | 251 | let crate_def_map = db.crate_def_map(krate); |
252 | for (_module_id, module_data) in crate_def_map.modules() { | 252 | collect_def_map(db, &crate_def_map, &mut impls); |
253 | for impl_id in module_data.scope.impls() { | 253 | |
254 | let data = db.impl_data(impl_id); | 254 | return Arc::new(impls); |
255 | if data.target_trait.is_some() { | 255 | |
256 | continue; | 256 | fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut InherentImpls) { |
257 | for (_module_id, module_data) in def_map.modules() { | ||
258 | for impl_id in module_data.scope.impls() { | ||
259 | let data = db.impl_data(impl_id); | ||
260 | if data.target_trait.is_some() { | ||
261 | continue; | ||
262 | } | ||
263 | |||
264 | let self_ty = db.impl_self_ty(impl_id); | ||
265 | let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders()); | ||
266 | if let Some(fp) = fp { | ||
267 | impls.map.entry(fp).or_default().push(impl_id); | ||
268 | } | ||
269 | // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution) | ||
257 | } | 270 | } |
258 | 271 | ||
259 | let self_ty = db.impl_self_ty(impl_id); | 272 | // To better support custom derives, collect impls in all unnamed const items. |
260 | let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders()); | 273 | // const _: () = { ... }; |
261 | if let Some(fp) = fp { | 274 | for konst in module_data.scope.unnamed_consts() { |
262 | map.entry(fp).or_default().push(impl_id); | 275 | let body = db.body(konst.into()); |
276 | for (_, block_def_map) in body.blocks(db.upcast()) { | ||
277 | collect_def_map(db, &block_def_map, impls); | ||
278 | } | ||
263 | } | 279 | } |
264 | // `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution) | ||
265 | } | 280 | } |
266 | } | 281 | } |
267 | |||
268 | // NOTE: We're not collecting inherent impls from unnamed consts here, we intentionally only | ||
269 | // support trait impls there. | ||
270 | |||
271 | Arc::new(Self { map }) | ||
272 | } | 282 | } |
273 | 283 | ||
274 | pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] { | 284 | pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] { |
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index b8e373ed8..6588aa46c 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -1074,3 +1074,202 @@ fn macro_in_arm() { | |||
1074 | "#]], | 1074 | "#]], |
1075 | ); | 1075 | ); |
1076 | } | 1076 | } |
1077 | |||
1078 | #[test] | ||
1079 | fn macro_in_type_alias_position() { | ||
1080 | check_infer( | ||
1081 | r#" | ||
1082 | macro_rules! U32 { | ||
1083 | () => { u32 }; | ||
1084 | } | ||
1085 | |||
1086 | trait Foo { | ||
1087 | type Ty; | ||
1088 | } | ||
1089 | |||
1090 | impl<T> Foo for T { | ||
1091 | type Ty = U32!(); | ||
1092 | } | ||
1093 | |||
1094 | type TayTo = U32!(); | ||
1095 | |||
1096 | fn testy() { | ||
1097 | let a: <() as Foo>::Ty; | ||
1098 | let b: TayTo; | ||
1099 | } | ||
1100 | "#, | ||
1101 | expect![[r#" | ||
1102 | 147..196 '{ ...yTo; }': () | ||
1103 | 157..158 'a': u32 | ||
1104 | 185..186 'b': u32 | ||
1105 | "#]], | ||
1106 | ); | ||
1107 | } | ||
1108 | |||
1109 | #[test] | ||
1110 | fn nested_macro_in_type_alias_position() { | ||
1111 | check_infer( | ||
1112 | r#" | ||
1113 | macro_rules! U32Inner2 { | ||
1114 | () => { u32 }; | ||
1115 | } | ||
1116 | |||
1117 | macro_rules! U32Inner1 { | ||
1118 | () => { U32Inner2!() }; | ||
1119 | } | ||
1120 | |||
1121 | macro_rules! U32 { | ||
1122 | () => { U32Inner1!() }; | ||
1123 | } | ||
1124 | |||
1125 | trait Foo { | ||
1126 | type Ty; | ||
1127 | } | ||
1128 | |||
1129 | impl<T> Foo for T { | ||
1130 | type Ty = U32!(); | ||
1131 | } | ||
1132 | |||
1133 | type TayTo = U32!(); | ||
1134 | |||
1135 | fn testy() { | ||
1136 | let a: <() as Foo>::Ty; | ||
1137 | let b: TayTo; | ||
1138 | } | ||
1139 | "#, | ||
1140 | expect![[r#" | ||
1141 | 259..308 '{ ...yTo; }': () | ||
1142 | 269..270 'a': u32 | ||
1143 | 297..298 'b': u32 | ||
1144 | "#]], | ||
1145 | ); | ||
1146 | } | ||
1147 | |||
1148 | #[test] | ||
1149 | fn macros_in_type_alias_position_generics() { | ||
1150 | check_infer( | ||
1151 | r#" | ||
1152 | struct Foo<A, B>(A, B); | ||
1153 | |||
1154 | macro_rules! U32 { | ||
1155 | () => { u32 }; | ||
1156 | } | ||
1157 | |||
1158 | macro_rules! Bar { | ||
1159 | () => { Foo<U32!(), U32!()> }; | ||
1160 | } | ||
1161 | |||
1162 | trait Moo { | ||
1163 | type Ty; | ||
1164 | } | ||
1165 | |||
1166 | impl<T> Moo for T { | ||
1167 | type Ty = Bar!(); | ||
1168 | } | ||
1169 | |||
1170 | type TayTo = Bar!(); | ||
1171 | |||
1172 | fn main() { | ||
1173 | let a: <() as Moo>::Ty; | ||
1174 | let b: TayTo; | ||
1175 | } | ||
1176 | "#, | ||
1177 | expect![[r#" | ||
1178 | 228..277 '{ ...yTo; }': () | ||
1179 | 238..239 'a': Foo<u32, u32> | ||
1180 | 266..267 'b': Foo<u32, u32> | ||
1181 | "#]], | ||
1182 | ); | ||
1183 | } | ||
1184 | |||
1185 | #[test] | ||
1186 | fn macros_in_type_position() { | ||
1187 | check_infer( | ||
1188 | r#" | ||
1189 | struct Foo<A, B>(A, B); | ||
1190 | |||
1191 | macro_rules! U32 { | ||
1192 | () => { u32 }; | ||
1193 | } | ||
1194 | |||
1195 | macro_rules! Bar { | ||
1196 | () => { Foo<U32!(), U32!()> }; | ||
1197 | } | ||
1198 | |||
1199 | fn main() { | ||
1200 | let a: Bar!(); | ||
1201 | } | ||
1202 | "#, | ||
1203 | expect![[r#" | ||
1204 | 133..155 '{ ...!(); }': () | ||
1205 | 143..144 'a': Foo<u32, u32> | ||
1206 | "#]], | ||
1207 | ); | ||
1208 | } | ||
1209 | |||
1210 | #[test] | ||
1211 | fn macros_in_type_generics() { | ||
1212 | check_infer( | ||
1213 | r#" | ||
1214 | struct Foo<A, B>(A, B); | ||
1215 | |||
1216 | macro_rules! U32 { | ||
1217 | () => { u32 }; | ||
1218 | } | ||
1219 | |||
1220 | macro_rules! Bar { | ||
1221 | () => { Foo<U32!(), U32!()> }; | ||
1222 | } | ||
1223 | |||
1224 | trait Moo { | ||
1225 | type Ty; | ||
1226 | } | ||
1227 | |||
1228 | impl<T> Moo for T { | ||
1229 | type Ty = Foo<Bar!(), Bar!()>; | ||
1230 | } | ||
1231 | |||
1232 | type TayTo = Foo<Bar!(), U32!()>; | ||
1233 | |||
1234 | fn main() { | ||
1235 | let a: <() as Moo>::Ty; | ||
1236 | let b: TayTo; | ||
1237 | } | ||
1238 | "#, | ||
1239 | expect![[r#" | ||
1240 | 254..303 '{ ...yTo; }': () | ||
1241 | 264..265 'a': Foo<Foo<u32, u32>, Foo<u32, u32>> | ||
1242 | 292..293 'b': Foo<Foo<u32, u32>, u32> | ||
1243 | "#]], | ||
1244 | ); | ||
1245 | } | ||
1246 | |||
1247 | #[test] | ||
1248 | fn infinitely_recursive_macro_type() { | ||
1249 | check_infer( | ||
1250 | r#" | ||
1251 | struct Bar<T, X>(T, X); | ||
1252 | |||
1253 | macro_rules! Foo { | ||
1254 | () => { Foo!() } | ||
1255 | } | ||
1256 | |||
1257 | macro_rules! U32 { | ||
1258 | () => { u32 } | ||
1259 | } | ||
1260 | |||
1261 | type A = Foo!(); | ||
1262 | type B = Bar<Foo!(), U32!()>; | ||
1263 | |||
1264 | fn main() { | ||
1265 | let a: A; | ||
1266 | let b: B; | ||
1267 | } | ||
1268 | "#, | ||
1269 | expect![[r#" | ||
1270 | 166..197 '{ ...: B; }': () | ||
1271 | 176..177 'a': {unknown} | ||
1272 | 190..191 'b': Bar<{unknown}, u32> | ||
1273 | "#]], | ||
1274 | ); | ||
1275 | } | ||
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs index 4b2c82b41..a4c132bc5 100644 --- a/crates/hir_ty/src/tests/method_resolution.rs +++ b/crates/hir_ty/src/tests/method_resolution.rs | |||
@@ -1294,7 +1294,7 @@ mod b { | |||
1294 | } | 1294 | } |
1295 | 1295 | ||
1296 | #[test] | 1296 | #[test] |
1297 | fn impl_in_unnamed_const() { | 1297 | fn trait_impl_in_unnamed_const() { |
1298 | check_types( | 1298 | check_types( |
1299 | r#" | 1299 | r#" |
1300 | struct S; | 1300 | struct S; |
@@ -1314,3 +1314,38 @@ fn f() { | |||
1314 | "#, | 1314 | "#, |
1315 | ); | 1315 | ); |
1316 | } | 1316 | } |
1317 | |||
1318 | #[test] | ||
1319 | fn inherent_impl_in_unnamed_const() { | ||
1320 | check_types( | ||
1321 | r#" | ||
1322 | struct S; | ||
1323 | |||
1324 | const _: () = { | ||
1325 | impl S { | ||
1326 | fn method(&self) -> u16 { 0 } | ||
1327 | |||
1328 | pub(super) fn super_method(&self) -> u16 { 0 } | ||
1329 | |||
1330 | pub(crate) fn crate_method(&self) -> u16 { 0 } | ||
1331 | |||
1332 | pub fn pub_method(&self) -> u16 { 0 } | ||
1333 | } | ||
1334 | }; | ||
1335 | |||
1336 | fn f() { | ||
1337 | S.method(); | ||
1338 | //^^^^^^^^^^ u16 | ||
1339 | |||
1340 | S.super_method(); | ||
1341 | //^^^^^^^^^^^^^^^^ u16 | ||
1342 | |||
1343 | S.crate_method(); | ||
1344 | //^^^^^^^^^^^^^^^^ u16 | ||
1345 | |||
1346 | S.pub_method(); | ||
1347 | //^^^^^^^^^^^^^^ u16 | ||
1348 | } | ||
1349 | "#, | ||
1350 | ); | ||
1351 | } | ||
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs index 84c5c05fd..5948d0bc2 100644 --- a/crates/hir_ty/src/tests/simple.rs +++ b/crates/hir_ty/src/tests/simple.rs | |||
@@ -1765,6 +1765,24 @@ fn main() { | |||
1765 | } | 1765 | } |
1766 | 1766 | ||
1767 | #[test] | 1767 | #[test] |
1768 | fn shadowing_primitive_with_inner_items() { | ||
1769 | check_types( | ||
1770 | r#" | ||
1771 | struct i32; | ||
1772 | struct Foo; | ||
1773 | |||
1774 | impl i32 { fn foo(&self) -> Foo { Foo } } | ||
1775 | |||
1776 | fn main() { | ||
1777 | fn inner() {} | ||
1778 | let x: i32 = i32; | ||
1779 | x.foo(); | ||
1780 | //^ Foo | ||
1781 | }"#, | ||
1782 | ); | ||
1783 | } | ||
1784 | |||
1785 | #[test] | ||
1768 | fn not_shadowing_primitive_by_module() { | 1786 | fn not_shadowing_primitive_by_module() { |
1769 | check_types( | 1787 | check_types( |
1770 | r#" | 1788 | r#" |
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index 5f6cb052a..2f04ee57a 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs | |||
@@ -78,7 +78,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr | |||
78 | 78 | ||
79 | /// Returns an iterator over the whole super trait hierarchy (including the | 79 | /// Returns an iterator over the whole super trait hierarchy (including the |
80 | /// trait itself). | 80 | /// trait itself). |
81 | pub(super) fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | 81 | pub fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { |
82 | // we need to take care a bit here to avoid infinite loops in case of cycles | 82 | // we need to take care a bit here to avoid infinite loops in case of cycles |
83 | // (i.e. if we have `trait A: B; trait B: A;`) | 83 | // (i.e. if we have `trait A: B; trait B: A;`) |
84 | let mut result = vec![trait_]; | 84 | let mut result = vec![trait_]; |