diff options
32 files changed, 586 insertions, 486 deletions
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index dab8da7bb..4a11622fc 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Attributes & documentation for hir types. | 1 | //! Attributes & documentation for hir types. |
2 | use hir_def::{ | 2 | use hir_def::{ |
3 | attr::{Attrs, Documentation}, | 3 | attr::{AttrsWithOwner, Documentation}, |
4 | path::ModPath, | 4 | path::ModPath, |
5 | per_ns::PerNs, | 5 | per_ns::PerNs, |
6 | resolver::HasResolver, | 6 | resolver::HasResolver, |
@@ -16,7 +16,7 @@ use crate::{ | |||
16 | }; | 16 | }; |
17 | 17 | ||
18 | pub trait HasAttrs { | 18 | pub trait HasAttrs { |
19 | fn attrs(self, db: &dyn HirDatabase) -> Attrs; | 19 | fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner; |
20 | fn docs(self, db: &dyn HirDatabase) -> Option<Documentation>; | 20 | fn docs(self, db: &dyn HirDatabase) -> Option<Documentation>; |
21 | fn resolve_doc_path( | 21 | fn resolve_doc_path( |
22 | self, | 22 | self, |
@@ -36,7 +36,7 @@ pub enum Namespace { | |||
36 | macro_rules! impl_has_attrs { | 36 | macro_rules! impl_has_attrs { |
37 | ($(($def:ident, $def_id:ident),)*) => {$( | 37 | ($(($def:ident, $def_id:ident),)*) => {$( |
38 | impl HasAttrs for $def { | 38 | impl HasAttrs for $def { |
39 | fn attrs(self, db: &dyn HirDatabase) -> Attrs { | 39 | fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner { |
40 | let def = AttrDefId::$def_id(self.into()); | 40 | let def = AttrDefId::$def_id(self.into()); |
41 | db.attrs(def) | 41 | db.attrs(def) |
42 | } | 42 | } |
@@ -70,7 +70,7 @@ impl_has_attrs![ | |||
70 | macro_rules! impl_has_attrs_enum { | 70 | macro_rules! impl_has_attrs_enum { |
71 | ($($variant:ident),* for $enum:ident) => {$( | 71 | ($($variant:ident),* for $enum:ident) => {$( |
72 | impl HasAttrs for $variant { | 72 | impl HasAttrs for $variant { |
73 | fn attrs(self, db: &dyn HirDatabase) -> Attrs { | 73 | fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner { |
74 | $enum::$variant(self).attrs(db) | 74 | $enum::$variant(self).attrs(db) |
75 | } | 75 | } |
76 | fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> { | 76 | fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> { |
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index d57fad9ed..dc10a4d0f 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs | |||
@@ -6,7 +6,7 @@ use hir_def::{ | |||
6 | src::{HasChildSource, HasSource as _}, | 6 | src::{HasChildSource, HasSource as _}, |
7 | Lookup, VariantId, | 7 | Lookup, VariantId, |
8 | }; | 8 | }; |
9 | use hir_expand::{InFile, MacroDefKind}; | 9 | use hir_expand::InFile; |
10 | use syntax::ast; | 10 | use syntax::ast; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
@@ -113,15 +113,10 @@ impl HasSource for TypeAlias { | |||
113 | impl HasSource for MacroDef { | 113 | impl HasSource for MacroDef { |
114 | type Ast = Either<ast::Macro, ast::Fn>; | 114 | type Ast = Either<ast::Macro, ast::Fn>; |
115 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { | 115 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
116 | Some(match &self.id.kind { | 116 | Some(self.id.ast_id().either( |
117 | MacroDefKind::Declarative(id) | 117 | |id| id.with_value(Either::Left(id.to_node(db.upcast()))), |
118 | | MacroDefKind::BuiltIn(_, id) | 118 | |id| id.with_value(Either::Right(id.to_node(db.upcast()))), |
119 | | MacroDefKind::BuiltInDerive(_, id) | 119 | )) |
120 | | MacroDefKind::BuiltInEager(_, id) => { | ||
121 | id.with_value(Either::Left(id.to_node(db.upcast()))) | ||
122 | } | ||
123 | MacroDefKind::ProcMacro(_, id) => id.map(|_| Either::Right(id.to_node(db.upcast()))), | ||
124 | }) | ||
125 | } | 120 | } |
126 | } | 121 | } |
127 | impl HasSource for Impl { | 122 | impl HasSource for Impl { |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 5ebd0a3b8..30e577671 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -56,9 +56,9 @@ use hir_ty::{ | |||
56 | primitive::UintTy, | 56 | primitive::UintTy, |
57 | to_assoc_type_id, | 57 | to_assoc_type_id, |
58 | traits::{FnTrait, Solution, SolutionVariables}, | 58 | traits::{FnTrait, Solution, SolutionVariables}, |
59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, DebruijnIndex, | 59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, Cast, DebruijnIndex, |
60 | GenericPredicate, InEnvironment, Interner, Obligation, ProjectionTy, Scalar, Substitution, Ty, | 60 | InEnvironment, Interner, ProjectionTy, Scalar, Substitution, Ty, TyDefId, TyKind, |
61 | TyDefId, TyKind, TyVariableKind, | 61 | TyVariableKind, WhereClause, |
62 | }; | 62 | }; |
63 | use itertools::Itertools; | 63 | use itertools::Itertools; |
64 | use rustc_hash::FxHashSet; | 64 | use rustc_hash::FxHashSet; |
@@ -89,7 +89,7 @@ pub use crate::{ | |||
89 | pub use { | 89 | pub use { |
90 | hir_def::{ | 90 | hir_def::{ |
91 | adt::StructKind, | 91 | adt::StructKind, |
92 | attr::{Attr, Attrs, Documentation}, | 92 | attr::{Attr, Attrs, AttrsWithOwner, Documentation}, |
93 | body::scope::ExprScopes, | 93 | body::scope::ExprScopes, |
94 | find_path::PrefixKind, | 94 | find_path::PrefixKind, |
95 | import_map, | 95 | import_map, |
@@ -1461,7 +1461,7 @@ impl TypeParam { | |||
1461 | db.generic_predicates_for_param(self.id) | 1461 | db.generic_predicates_for_param(self.id) |
1462 | .into_iter() | 1462 | .into_iter() |
1463 | .filter_map(|pred| match &pred.value { | 1463 | .filter_map(|pred| match &pred.value { |
1464 | hir_ty::GenericPredicate::Implemented(trait_ref) => { | 1464 | hir_ty::WhereClause::Implemented(trait_ref) => { |
1465 | Some(Trait::from(trait_ref.hir_trait_id())) | 1465 | Some(Trait::from(trait_ref.hir_trait_id())) |
1466 | } | 1466 | } |
1467 | _ => None, | 1467 | _ => None, |
@@ -1767,7 +1767,7 @@ impl Type { | |||
1767 | let goal = Canonical { | 1767 | let goal = Canonical { |
1768 | value: hir_ty::InEnvironment::new( | 1768 | value: hir_ty::InEnvironment::new( |
1769 | self.ty.environment.clone(), | 1769 | self.ty.environment.clone(), |
1770 | hir_ty::Obligation::Trait(trait_ref), | 1770 | trait_ref.cast(&Interner), |
1771 | ), | 1771 | ), |
1772 | kinds: Arc::new([]), | 1772 | kinds: Arc::new([]), |
1773 | }; | 1773 | }; |
@@ -1789,14 +1789,15 @@ impl Type { | |||
1789 | let goal = Canonical { | 1789 | let goal = Canonical { |
1790 | value: InEnvironment::new( | 1790 | value: InEnvironment::new( |
1791 | self.ty.environment.clone(), | 1791 | self.ty.environment.clone(), |
1792 | Obligation::AliasEq(AliasEq { | 1792 | AliasEq { |
1793 | alias: AliasTy::Projection(ProjectionTy { | 1793 | alias: AliasTy::Projection(ProjectionTy { |
1794 | associated_ty_id: to_assoc_type_id(alias.id), | 1794 | associated_ty_id: to_assoc_type_id(alias.id), |
1795 | substitution: subst, | 1795 | substitution: subst, |
1796 | }), | 1796 | }), |
1797 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) | 1797 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) |
1798 | .intern(&Interner), | 1798 | .intern(&Interner), |
1799 | }), | 1799 | } |
1800 | .cast(&Interner), | ||
1800 | ), | 1801 | ), |
1801 | kinds: Arc::new([TyVariableKind::General]), | 1802 | kinds: Arc::new([TyVariableKind::General]), |
1802 | }; | 1803 | }; |
@@ -2022,7 +2023,7 @@ impl Type { | |||
2022 | self.ty.value.impl_trait_bounds(db).map(|it| { | 2023 | self.ty.value.impl_trait_bounds(db).map(|it| { |
2023 | it.into_iter() | 2024 | it.into_iter() |
2024 | .filter_map(|pred| match pred { | 2025 | .filter_map(|pred| match pred { |
2025 | hir_ty::GenericPredicate::Implemented(trait_ref) => { | 2026 | hir_ty::WhereClause::Implemented(trait_ref) => { |
2026 | Some(Trait::from(trait_ref.hir_trait_id())) | 2027 | Some(Trait::from(trait_ref.hir_trait_id())) |
2027 | } | 2028 | } |
2028 | _ => None, | 2029 | _ => None, |
@@ -2060,12 +2061,12 @@ impl Type { | |||
2060 | fn walk_bounds( | 2061 | fn walk_bounds( |
2061 | db: &dyn HirDatabase, | 2062 | db: &dyn HirDatabase, |
2062 | type_: &Type, | 2063 | type_: &Type, |
2063 | bounds: &[GenericPredicate], | 2064 | bounds: &[WhereClause], |
2064 | cb: &mut impl FnMut(Type), | 2065 | cb: &mut impl FnMut(Type), |
2065 | ) { | 2066 | ) { |
2066 | for pred in bounds { | 2067 | for pred in bounds { |
2067 | match pred { | 2068 | match pred { |
2068 | GenericPredicate::Implemented(trait_ref) => { | 2069 | WhereClause::Implemented(trait_ref) => { |
2069 | cb(type_.clone()); | 2070 | cb(type_.clone()); |
2070 | walk_substs(db, type_, &trait_ref.substitution, cb); | 2071 | walk_substs(db, type_, &trait_ref.substitution, cb); |
2071 | } | 2072 | } |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 0360fb627..2c10f46d8 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | item_tree::{ItemTreeId, ItemTreeNode}, | 21 | item_tree::{ItemTreeId, ItemTreeNode}, |
22 | nameres::ModuleSource, | 22 | nameres::ModuleSource, |
23 | path::{ModPath, PathKind}, | 23 | path::{ModPath, PathKind}, |
24 | src::HasChildSource, | 24 | src::{HasChildSource, HasSource}, |
25 | AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, | 25 | AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, |
26 | VariantId, | 26 | VariantId, |
27 | }; | 27 | }; |
@@ -51,6 +51,12 @@ pub(crate) struct RawAttrs { | |||
51 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | 51 | #[derive(Default, Debug, Clone, PartialEq, Eq)] |
52 | pub struct Attrs(RawAttrs); | 52 | pub struct Attrs(RawAttrs); |
53 | 53 | ||
54 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
55 | pub struct AttrsWithOwner { | ||
56 | attrs: Attrs, | ||
57 | owner: AttrDefId, | ||
58 | } | ||
59 | |||
54 | impl ops::Deref for RawAttrs { | 60 | impl ops::Deref for RawAttrs { |
55 | type Target = [Attr]; | 61 | type Target = [Attr]; |
56 | 62 | ||
@@ -73,6 +79,14 @@ impl ops::Deref for Attrs { | |||
73 | } | 79 | } |
74 | } | 80 | } |
75 | 81 | ||
82 | impl ops::Deref for AttrsWithOwner { | ||
83 | type Target = Attrs; | ||
84 | |||
85 | fn deref(&self) -> &Attrs { | ||
86 | &self.attrs | ||
87 | } | ||
88 | } | ||
89 | |||
76 | impl RawAttrs { | 90 | impl RawAttrs { |
77 | pub(crate) const EMPTY: Self = Self { entries: None }; | 91 | pub(crate) const EMPTY: Self = Self { entries: None }; |
78 | 92 | ||
@@ -169,77 +183,6 @@ impl RawAttrs { | |||
169 | impl Attrs { | 183 | impl Attrs { |
170 | pub const EMPTY: Self = Self(RawAttrs::EMPTY); | 184 | pub const EMPTY: Self = Self(RawAttrs::EMPTY); |
171 | 185 | ||
172 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { | ||
173 | let raw_attrs = match def { | ||
174 | AttrDefId::ModuleId(module) => { | ||
175 | let def_map = module.def_map(db); | ||
176 | let mod_data = &def_map[module.local_id]; | ||
177 | match mod_data.declaration_source(db) { | ||
178 | Some(it) => { | ||
179 | let raw_attrs = RawAttrs::from_attrs_owner( | ||
180 | db, | ||
181 | it.as_ref().map(|it| it as &dyn ast::AttrsOwner), | ||
182 | ); | ||
183 | match mod_data.definition_source(db) { | ||
184 | InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs | ||
185 | .merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))), | ||
186 | _ => raw_attrs, | ||
187 | } | ||
188 | } | ||
189 | None => RawAttrs::from_attrs_owner( | ||
190 | db, | ||
191 | mod_data.definition_source(db).as_ref().map(|src| match src { | ||
192 | ModuleSource::SourceFile(file) => file as &dyn ast::AttrsOwner, | ||
193 | ModuleSource::Module(module) => module as &dyn ast::AttrsOwner, | ||
194 | ModuleSource::BlockExpr(block) => block as &dyn ast::AttrsOwner, | ||
195 | }), | ||
196 | ), | ||
197 | } | ||
198 | } | ||
199 | AttrDefId::FieldId(it) => { | ||
200 | return db.fields_attrs(it.parent)[it.local_id].clone(); | ||
201 | } | ||
202 | AttrDefId::EnumVariantId(it) => { | ||
203 | return db.variants_attrs(it.parent)[it.local_id].clone(); | ||
204 | } | ||
205 | AttrDefId::AdtId(it) => match it { | ||
206 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
207 | AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
208 | AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
209 | }, | ||
210 | AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
211 | AttrDefId::MacroDefId(it) => { | ||
212 | it.ast_id().map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)) | ||
213 | } | ||
214 | AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
215 | AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
216 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
217 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
218 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
219 | AttrDefId::GenericParamId(it) => match it { | ||
220 | GenericParamId::TypeParamId(it) => { | ||
221 | let src = it.parent.child_source(db); | ||
222 | RawAttrs::from_attrs_owner( | ||
223 | db, | ||
224 | src.with_value( | ||
225 | src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _), | ||
226 | ), | ||
227 | ) | ||
228 | } | ||
229 | GenericParamId::LifetimeParamId(it) => { | ||
230 | let src = it.parent.child_source(db); | ||
231 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
232 | } | ||
233 | GenericParamId::ConstParamId(it) => { | ||
234 | let src = it.parent.child_source(db); | ||
235 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
236 | } | ||
237 | }, | ||
238 | }; | ||
239 | |||
240 | raw_attrs.filter(db, def.krate(db)) | ||
241 | } | ||
242 | |||
243 | pub(crate) fn variants_attrs_query( | 186 | pub(crate) fn variants_attrs_query( |
244 | db: &dyn DefDatabase, | 187 | db: &dyn DefDatabase, |
245 | e: EnumId, | 188 | e: EnumId, |
@@ -280,56 +223,6 @@ impl Attrs { | |||
280 | Arc::new(res) | 223 | Arc::new(res) |
281 | } | 224 | } |
282 | 225 | ||
283 | /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes. | ||
284 | /// | ||
285 | /// `owner` must be the original owner of the attributes. | ||
286 | // FIXME: figure out a better api that doesnt require the for_module hack | ||
287 | pub fn source_map(&self, owner: InFile<&dyn ast::AttrsOwner>) -> AttrSourceMap { | ||
288 | // FIXME: This doesn't work correctly for modules, as the attributes there can have up to | ||
289 | // two different owners | ||
290 | AttrSourceMap { | ||
291 | attrs: collect_attrs(owner.value) | ||
292 | .map(|attr| InFile::new(owner.file_id, attr)) | ||
293 | .collect(), | ||
294 | } | ||
295 | } | ||
296 | |||
297 | pub fn source_map_for_module( | ||
298 | &self, | ||
299 | db: &dyn DefDatabase, | ||
300 | module: crate::ModuleId, | ||
301 | ) -> AttrSourceMap { | ||
302 | let def_map = module.def_map(db); | ||
303 | let mod_data = &def_map[module.local_id]; | ||
304 | let attrs = match mod_data.declaration_source(db) { | ||
305 | Some(it) => { | ||
306 | let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner) | ||
307 | .map(|attr| InFile::new(it.file_id, attr)) | ||
308 | .collect(); | ||
309 | if let InFile { file_id, value: ModuleSource::SourceFile(file) } = | ||
310 | mod_data.definition_source(db) | ||
311 | { | ||
312 | attrs.extend( | ||
313 | collect_attrs(&file as &dyn ast::AttrsOwner) | ||
314 | .map(|attr| InFile::new(file_id, attr)), | ||
315 | ) | ||
316 | } | ||
317 | attrs | ||
318 | } | ||
319 | None => { | ||
320 | let InFile { file_id, value } = mod_data.definition_source(db); | ||
321 | match &value { | ||
322 | ModuleSource::SourceFile(file) => collect_attrs(file as &dyn ast::AttrsOwner), | ||
323 | ModuleSource::Module(module) => collect_attrs(module as &dyn ast::AttrsOwner), | ||
324 | ModuleSource::BlockExpr(block) => collect_attrs(block as &dyn ast::AttrsOwner), | ||
325 | } | ||
326 | .map(|attr| InFile::new(file_id, attr)) | ||
327 | .collect() | ||
328 | } | ||
329 | }; | ||
330 | AttrSourceMap { attrs } | ||
331 | } | ||
332 | |||
333 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { | 226 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { |
334 | AttrQuery { attrs: self, key } | 227 | AttrQuery { attrs: self, key } |
335 | } | 228 | } |
@@ -386,6 +279,180 @@ impl Attrs { | |||
386 | } | 279 | } |
387 | } | 280 | } |
388 | 281 | ||
282 | impl AttrsWithOwner { | ||
283 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Self { | ||
284 | // FIXME: this should use `Trace` to avoid duplication in `source_map` below | ||
285 | let raw_attrs = match def { | ||
286 | AttrDefId::ModuleId(module) => { | ||
287 | let def_map = module.def_map(db); | ||
288 | let mod_data = &def_map[module.local_id]; | ||
289 | match mod_data.declaration_source(db) { | ||
290 | Some(it) => { | ||
291 | let raw_attrs = RawAttrs::from_attrs_owner( | ||
292 | db, | ||
293 | it.as_ref().map(|it| it as &dyn ast::AttrsOwner), | ||
294 | ); | ||
295 | match mod_data.definition_source(db) { | ||
296 | InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs | ||
297 | .merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))), | ||
298 | _ => raw_attrs, | ||
299 | } | ||
300 | } | ||
301 | None => RawAttrs::from_attrs_owner( | ||
302 | db, | ||
303 | mod_data.definition_source(db).as_ref().map(|src| match src { | ||
304 | ModuleSource::SourceFile(file) => file as &dyn ast::AttrsOwner, | ||
305 | ModuleSource::Module(module) => module as &dyn ast::AttrsOwner, | ||
306 | ModuleSource::BlockExpr(block) => block as &dyn ast::AttrsOwner, | ||
307 | }), | ||
308 | ), | ||
309 | } | ||
310 | } | ||
311 | AttrDefId::FieldId(it) => { | ||
312 | return Self { attrs: db.fields_attrs(it.parent)[it.local_id].clone(), owner: def }; | ||
313 | } | ||
314 | AttrDefId::EnumVariantId(it) => { | ||
315 | return Self { | ||
316 | attrs: db.variants_attrs(it.parent)[it.local_id].clone(), | ||
317 | owner: def, | ||
318 | }; | ||
319 | } | ||
320 | AttrDefId::AdtId(it) => match it { | ||
321 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
322 | AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
323 | AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
324 | }, | ||
325 | AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
326 | AttrDefId::MacroDefId(it) => it | ||
327 | .ast_id() | ||
328 | .left() | ||
329 | .map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)), | ||
330 | AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
331 | AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
332 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
333 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
334 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
335 | AttrDefId::GenericParamId(it) => match it { | ||
336 | GenericParamId::TypeParamId(it) => { | ||
337 | let src = it.parent.child_source(db); | ||
338 | RawAttrs::from_attrs_owner( | ||
339 | db, | ||
340 | src.with_value( | ||
341 | src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _), | ||
342 | ), | ||
343 | ) | ||
344 | } | ||
345 | GenericParamId::LifetimeParamId(it) => { | ||
346 | let src = it.parent.child_source(db); | ||
347 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
348 | } | ||
349 | GenericParamId::ConstParamId(it) => { | ||
350 | let src = it.parent.child_source(db); | ||
351 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
352 | } | ||
353 | }, | ||
354 | }; | ||
355 | |||
356 | let attrs = raw_attrs.filter(db, def.krate(db)); | ||
357 | Self { attrs, owner: def } | ||
358 | } | ||
359 | |||
360 | pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap { | ||
361 | let owner = match self.owner { | ||
362 | AttrDefId::ModuleId(module) => { | ||
363 | // Modules can have 2 attribute owners (the `mod x;` item, and the module file itself). | ||
364 | |||
365 | let def_map = module.def_map(db); | ||
366 | let mod_data = &def_map[module.local_id]; | ||
367 | let attrs = match mod_data.declaration_source(db) { | ||
368 | Some(it) => { | ||
369 | let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner) | ||
370 | .map(|attr| InFile::new(it.file_id, attr)) | ||
371 | .collect(); | ||
372 | if let InFile { file_id, value: ModuleSource::SourceFile(file) } = | ||
373 | mod_data.definition_source(db) | ||
374 | { | ||
375 | attrs.extend( | ||
376 | collect_attrs(&file as &dyn ast::AttrsOwner) | ||
377 | .map(|attr| InFile::new(file_id, attr)), | ||
378 | ) | ||
379 | } | ||
380 | attrs | ||
381 | } | ||
382 | None => { | ||
383 | let InFile { file_id, value } = mod_data.definition_source(db); | ||
384 | match &value { | ||
385 | ModuleSource::SourceFile(file) => { | ||
386 | collect_attrs(file as &dyn ast::AttrsOwner) | ||
387 | } | ||
388 | ModuleSource::Module(module) => { | ||
389 | collect_attrs(module as &dyn ast::AttrsOwner) | ||
390 | } | ||
391 | ModuleSource::BlockExpr(block) => { | ||
392 | collect_attrs(block as &dyn ast::AttrsOwner) | ||
393 | } | ||
394 | } | ||
395 | .map(|attr| InFile::new(file_id, attr)) | ||
396 | .collect() | ||
397 | } | ||
398 | }; | ||
399 | return AttrSourceMap { attrs }; | ||
400 | } | ||
401 | AttrDefId::FieldId(id) => { | ||
402 | id.parent.child_source(db).map(|source| match &source[id.local_id] { | ||
403 | Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()), | ||
404 | Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()), | ||
405 | }) | ||
406 | } | ||
407 | AttrDefId::AdtId(adt) => match adt { | ||
408 | AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
409 | AdtId::UnionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
410 | AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
411 | }, | ||
412 | AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
413 | AttrDefId::EnumVariantId(id) => id | ||
414 | .parent | ||
415 | .child_source(db) | ||
416 | .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), | ||
417 | 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), | ||
419 | AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
420 | AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
421 | AttrDefId::MacroDefId(id) => match id.ast_id() { | ||
422 | Either::Left(it) => { | ||
423 | it.with_value(ast::AttrsOwnerNode::new(it.to_node(db.upcast()))) | ||
424 | } | ||
425 | Either::Right(it) => { | ||
426 | it.with_value(ast::AttrsOwnerNode::new(it.to_node(db.upcast()))) | ||
427 | } | ||
428 | }, | ||
429 | AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
430 | AttrDefId::GenericParamId(id) => match id { | ||
431 | GenericParamId::TypeParamId(id) => { | ||
432 | id.parent.child_source(db).map(|source| match &source[id.local_id] { | ||
433 | Either::Left(id) => ast::AttrsOwnerNode::new(id.clone()), | ||
434 | Either::Right(id) => ast::AttrsOwnerNode::new(id.clone()), | ||
435 | }) | ||
436 | } | ||
437 | GenericParamId::LifetimeParamId(id) => id | ||
438 | .parent | ||
439 | .child_source(db) | ||
440 | .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), | ||
441 | GenericParamId::ConstParamId(id) => id | ||
442 | .parent | ||
443 | .child_source(db) | ||
444 | .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), | ||
445 | }, | ||
446 | }; | ||
447 | |||
448 | AttrSourceMap { | ||
449 | attrs: collect_attrs(&owner.value) | ||
450 | .map(|attr| InFile::new(owner.file_id, attr)) | ||
451 | .collect(), | ||
452 | } | ||
453 | } | ||
454 | } | ||
455 | |||
389 | fn inner_attributes( | 456 | fn inner_attributes( |
390 | syntax: &SyntaxNode, | 457 | syntax: &SyntaxNode, |
391 | ) -> Option<(impl Iterator<Item = ast::Attr>, impl Iterator<Item = ast::Comment>)> { | 458 | ) -> Option<(impl Iterator<Item = ast::Attr>, impl Iterator<Item = ast::Comment>)> { |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 276caf5b3..53df85089 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -8,7 +8,7 @@ use syntax::SmolStr; | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | adt::{EnumData, StructData}, | 10 | adt::{EnumData, StructData}, |
11 | attr::Attrs, | 11 | attr::{Attrs, AttrsWithOwner}, |
12 | body::{scope::ExprScopes, Body, BodySourceMap}, | 12 | body::{scope::ExprScopes, Body, BodySourceMap}, |
13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, | 13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, |
14 | generics::GenericParams, | 14 | generics::GenericParams, |
@@ -120,8 +120,8 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
120 | #[salsa::invoke(Attrs::fields_attrs_query)] | 120 | #[salsa::invoke(Attrs::fields_attrs_query)] |
121 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; | 121 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; |
122 | 122 | ||
123 | #[salsa::invoke(Attrs::attrs_query)] | 123 | #[salsa::invoke(AttrsWithOwner::attrs_query)] |
124 | fn attrs(&self, def: AttrDefId) -> Attrs; | 124 | fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; |
125 | 125 | ||
126 | #[salsa::invoke(LangItems::crate_lang_items_query)] | 126 | #[salsa::invoke(LangItems::crate_lang_items_query)] |
127 | fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>; | 127 | fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>; |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 4bcdc0fc8..46a3c60cd 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -1294,29 +1294,37 @@ impl ModCollector<'_, '_> { | |||
1294 | let db = self.def_collector.db; | 1294 | let db = self.def_collector.db; |
1295 | match self.mod_dir.resolve_declaration(db, self.file_id, &module.name, path_attr) { | 1295 | match self.mod_dir.resolve_declaration(db, self.file_id, &module.name, path_attr) { |
1296 | Ok((file_id, is_mod_rs, mod_dir)) => { | 1296 | Ok((file_id, is_mod_rs, mod_dir)) => { |
1297 | let module_id = self.push_child_module( | ||
1298 | module.name.clone(), | ||
1299 | ast_id, | ||
1300 | Some((file_id, is_mod_rs)), | ||
1301 | &self.item_tree[module.visibility], | ||
1302 | ); | ||
1303 | let item_tree = db.file_item_tree(file_id.into()); | 1297 | let item_tree = db.file_item_tree(file_id.into()); |
1304 | ModCollector { | 1298 | if item_tree |
1305 | def_collector: &mut *self.def_collector, | 1299 | .top_level_attrs(db, self.def_collector.def_map.krate) |
1306 | macro_depth: self.macro_depth, | 1300 | .cfg() |
1307 | module_id, | 1301 | .map_or(true, |cfg| { |
1308 | file_id: file_id.into(), | 1302 | self.def_collector.cfg_options.check(&cfg) != Some(false) |
1309 | item_tree: &item_tree, | 1303 | }) |
1310 | mod_dir, | ||
1311 | } | ||
1312 | .collect(item_tree.top_level_items()); | ||
1313 | if is_macro_use | ||
1314 | || item_tree | ||
1315 | .top_level_attrs(db, self.def_collector.def_map.krate) | ||
1316 | .by_key("macro_use") | ||
1317 | .exists() | ||
1318 | { | 1304 | { |
1319 | self.import_all_legacy_macros(module_id); | 1305 | let module_id = self.push_child_module( |
1306 | module.name.clone(), | ||
1307 | ast_id, | ||
1308 | Some((file_id, is_mod_rs)), | ||
1309 | &self.item_tree[module.visibility], | ||
1310 | ); | ||
1311 | ModCollector { | ||
1312 | def_collector: &mut *self.def_collector, | ||
1313 | macro_depth: self.macro_depth, | ||
1314 | module_id, | ||
1315 | file_id: file_id.into(), | ||
1316 | item_tree: &item_tree, | ||
1317 | mod_dir, | ||
1318 | } | ||
1319 | .collect(item_tree.top_level_items()); | ||
1320 | if is_macro_use | ||
1321 | || item_tree | ||
1322 | .top_level_attrs(db, self.def_collector.def_map.krate) | ||
1323 | .by_key("macro_use") | ||
1324 | .exists() | ||
1325 | { | ||
1326 | self.import_all_legacy_macros(module_id); | ||
1327 | } | ||
1320 | } | 1328 | } |
1321 | } | 1329 | } |
1322 | Err(candidate) => { | 1330 | Err(candidate) => { |
diff --git a/crates/hir_def/src/nameres/tests/mod_resolution.rs b/crates/hir_def/src/nameres/tests/mod_resolution.rs index dfbbad1f9..16a2cd27a 100644 --- a/crates/hir_def/src/nameres/tests/mod_resolution.rs +++ b/crates/hir_def/src/nameres/tests/mod_resolution.rs | |||
@@ -819,3 +819,22 @@ pub mod hash { pub trait Hash {} } | |||
819 | "#]], | 819 | "#]], |
820 | ); | 820 | ); |
821 | } | 821 | } |
822 | |||
823 | #[test] | ||
824 | fn cfg_in_module_file() { | ||
825 | // Inner `#![cfg]` in a module file makes the whole module disappear. | ||
826 | check( | ||
827 | r#" | ||
828 | //- /main.rs | ||
829 | mod module; | ||
830 | |||
831 | //- /module.rs | ||
832 | #![cfg(NEVER)] | ||
833 | |||
834 | struct AlsoShoulntAppear; | ||
835 | "#, | ||
836 | expect![[r#" | ||
837 | crate | ||
838 | "#]], | ||
839 | ) | ||
840 | } | ||
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs index 20cda1683..0e0f7214a 100644 --- a/crates/hir_expand/src/hygiene.rs +++ b/crates/hir_expand/src/hygiene.rs | |||
@@ -145,7 +145,7 @@ fn make_hygiene_info( | |||
145 | ) -> Option<HygieneInfo> { | 145 | ) -> Option<HygieneInfo> { |
146 | let arg_tt = loc.kind.arg(db)?; | 146 | let arg_tt = loc.kind.arg(db)?; |
147 | 147 | ||
148 | let def_offset = loc.def.ast_id().and_then(|id| { | 148 | let def_offset = loc.def.ast_id().left().and_then(|id| { |
149 | let def_tt = match id.to_node(db) { | 149 | let def_tt = match id.to_node(db) { |
150 | ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(), | 150 | ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(), |
151 | ast::Macro::MacroDef(_) => return None, | 151 | ast::Macro::MacroDef(_) => return None, |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index c958b0865..f49fd4fda 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -15,6 +15,7 @@ pub mod proc_macro; | |||
15 | pub mod quote; | 15 | pub mod quote; |
16 | pub mod eager; | 16 | pub mod eager; |
17 | 17 | ||
18 | use either::Either; | ||
18 | pub use mbe::{ExpandError, ExpandResult}; | 19 | pub use mbe::{ExpandError, ExpandResult}; |
19 | 20 | ||
20 | use std::hash::Hash; | 21 | use std::hash::Hash; |
@@ -143,7 +144,7 @@ impl HirFileId { | |||
143 | 144 | ||
144 | let arg_tt = loc.kind.arg(db)?; | 145 | let arg_tt = loc.kind.arg(db)?; |
145 | 146 | ||
146 | let def = loc.def.ast_id().and_then(|id| { | 147 | let def = loc.def.ast_id().left().and_then(|id| { |
147 | let def_tt = match id.to_node(db) { | 148 | let def_tt = match id.to_node(db) { |
148 | ast::Macro::MacroRules(mac) => mac.token_tree()?, | 149 | ast::Macro::MacroRules(mac) => mac.token_tree()?, |
149 | ast::Macro::MacroDef(_) => return None, | 150 | ast::Macro::MacroDef(_) => return None, |
@@ -239,15 +240,15 @@ impl MacroDefId { | |||
239 | db.intern_macro(MacroCallLoc { def: self, krate, kind }) | 240 | db.intern_macro(MacroCallLoc { def: self, krate, kind }) |
240 | } | 241 | } |
241 | 242 | ||
242 | pub fn ast_id(&self) -> Option<AstId<ast::Macro>> { | 243 | pub fn ast_id(&self) -> Either<AstId<ast::Macro>, AstId<ast::Fn>> { |
243 | let id = match &self.kind { | 244 | let id = match &self.kind { |
244 | MacroDefKind::Declarative(id) => id, | 245 | MacroDefKind::Declarative(id) => id, |
245 | MacroDefKind::BuiltIn(_, id) => id, | 246 | MacroDefKind::BuiltIn(_, id) => id, |
246 | MacroDefKind::BuiltInDerive(_, id) => id, | 247 | MacroDefKind::BuiltInDerive(_, id) => id, |
247 | MacroDefKind::BuiltInEager(_, id) => id, | 248 | MacroDefKind::BuiltInEager(_, id) => id, |
248 | MacroDefKind::ProcMacro(..) => return None, | 249 | MacroDefKind::ProcMacro(_, id) => return Either::Right(*id), |
249 | }; | 250 | }; |
250 | Some(*id) | 251 | Either::Left(*id) |
251 | } | 252 | } |
252 | } | 253 | } |
253 | 254 | ||
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index 33b966026..23ab042c1 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -6,6 +6,7 @@ | |||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
9 | use chalk_ir::cast::Cast; | ||
9 | use hir_def::lang_item::LangItemTarget; | 10 | use hir_def::lang_item::LangItemTarget; |
10 | use hir_expand::name::name; | 11 | use hir_expand::name::name; |
11 | use log::{info, warn}; | 12 | use log::{info, warn}; |
@@ -15,8 +16,8 @@ use crate::{ | |||
15 | to_assoc_type_id, to_chalk_trait_id, | 16 | to_assoc_type_id, to_chalk_trait_id, |
16 | traits::{InEnvironment, Solution}, | 17 | traits::{InEnvironment, Solution}, |
17 | utils::generics, | 18 | utils::generics, |
18 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, Obligation, ProjectionTy, | 19 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, Interner, ProjectionTy, Substitution, |
19 | Substitution, TraitRef, Ty, TyKind, | 20 | TraitRef, Ty, TyKind, |
20 | }; | 21 | }; |
21 | 22 | ||
22 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
@@ -74,7 +75,7 @@ fn deref_by_trait( | |||
74 | let implements_goal = Canonical { | 75 | let implements_goal = Canonical { |
75 | kinds: ty.value.kinds.clone(), | 76 | kinds: ty.value.kinds.clone(), |
76 | value: InEnvironment { | 77 | value: InEnvironment { |
77 | value: Obligation::Trait(trait_ref), | 78 | value: trait_ref.cast(&Interner), |
78 | environment: ty.environment.clone(), | 79 | environment: ty.environment.clone(), |
79 | }, | 80 | }, |
80 | }; | 81 | }; |
@@ -92,7 +93,7 @@ fn deref_by_trait( | |||
92 | .intern(&Interner), | 93 | .intern(&Interner), |
93 | }; | 94 | }; |
94 | 95 | ||
95 | let obligation = super::Obligation::AliasEq(projection); | 96 | let obligation = projection.cast(&Interner); |
96 | 97 | ||
97 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; | 98 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; |
98 | 99 | ||
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs new file mode 100644 index 000000000..bf884ae15 --- /dev/null +++ b/crates/hir_ty/src/chalk_cast.rs | |||
@@ -0,0 +1,53 @@ | |||
1 | //! Implementations of the Chalk `Cast` trait for our types. | ||
2 | |||
3 | use chalk_ir::{ | ||
4 | cast::{Cast, CastTo}, | ||
5 | interner::HasInterner, | ||
6 | }; | ||
7 | |||
8 | use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause}; | ||
9 | |||
10 | macro_rules! has_interner { | ||
11 | ($t:ty) => { | ||
12 | impl HasInterner for $t { | ||
13 | type Interner = crate::Interner; | ||
14 | } | ||
15 | }; | ||
16 | } | ||
17 | |||
18 | has_interner!(WhereClause); | ||
19 | has_interner!(DomainGoal); | ||
20 | |||
21 | impl CastTo<WhereClause> for TraitRef { | ||
22 | fn cast_to(self, _interner: &Interner) -> WhereClause { | ||
23 | WhereClause::Implemented(self) | ||
24 | } | ||
25 | } | ||
26 | |||
27 | impl CastTo<WhereClause> for AliasEq { | ||
28 | fn cast_to(self, _interner: &Interner) -> WhereClause { | ||
29 | WhereClause::AliasEq(self) | ||
30 | } | ||
31 | } | ||
32 | |||
33 | impl CastTo<DomainGoal> for WhereClause { | ||
34 | fn cast_to(self, _interner: &Interner) -> DomainGoal { | ||
35 | DomainGoal::Holds(self) | ||
36 | } | ||
37 | } | ||
38 | |||
39 | macro_rules! transitive_impl { | ||
40 | ($a:ty, $b:ty, $c:ty) => { | ||
41 | impl CastTo<$c> for $a { | ||
42 | fn cast_to(self, interner: &Interner) -> $c { | ||
43 | self.cast::<$b>(interner).cast(interner) | ||
44 | } | ||
45 | } | ||
46 | }; | ||
47 | } | ||
48 | |||
49 | // In Chalk, these can be done as blanket impls, but that doesn't work here | ||
50 | // because of coherence | ||
51 | |||
52 | transitive_impl!(TraitRef, WhereClause, DomainGoal); | ||
53 | transitive_impl!(AliasEq, WhereClause, DomainGoal); | ||
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 74a048672..91a2e0b5b 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -12,8 +12,8 @@ use la_arena::ArenaMap; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | method_resolution::{InherentImpls, TraitImpls}, | 13 | method_resolution::{InherentImpls, TraitImpls}, |
14 | traits::chalk, | 14 | traits::chalk, |
15 | Binders, CallableDefId, FnDefId, GenericPredicate, ImplTraitId, InferenceResult, PolyFnSig, | 15 | Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, ReturnTypeImplTraits, |
16 | ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, | 16 | TraitRef, Ty, TyDefId, ValueTyDefId, WhereClause, |
17 | }; | 17 | }; |
18 | use hir_expand::name::Name; | 18 | use hir_expand::name::Name; |
19 | 19 | ||
@@ -57,13 +57,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
57 | 57 | ||
58 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] | 58 | #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] |
59 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] | 59 | #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] |
60 | fn generic_predicates_for_param( | 60 | fn generic_predicates_for_param(&self, param_id: TypeParamId) -> Arc<[Binders<WhereClause>]>; |
61 | &self, | ||
62 | param_id: TypeParamId, | ||
63 | ) -> Arc<[Binders<GenericPredicate>]>; | ||
64 | 61 | ||
65 | #[salsa::invoke(crate::lower::generic_predicates_query)] | 62 | #[salsa::invoke(crate::lower::generic_predicates_query)] |
66 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>; | 63 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<WhereClause>]>; |
67 | 64 | ||
68 | #[salsa::invoke(crate::lower::trait_environment_query)] | 65 | #[salsa::invoke(crate::lower::trait_environment_query)] |
69 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; | 66 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; |
@@ -122,7 +119,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
122 | fn trait_solve( | 119 | fn trait_solve( |
123 | &self, | 120 | &self, |
124 | krate: CrateId, | 121 | krate: CrateId, |
125 | goal: crate::Canonical<crate::InEnvironment<crate::Obligation>>, | 122 | goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, |
126 | ) -> Option<crate::traits::Solution>; | 123 | ) -> Option<crate::traits::Solution>; |
127 | 124 | ||
128 | #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] | 125 | #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 59a1bd9b0..3845009ae 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -19,8 +19,8 @@ use hir_expand::name::Name; | |||
19 | use crate::{ | 19 | use crate::{ |
20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, | 20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, |
21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, | 21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, |
22 | CallableDefId, CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation, | 22 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, |
23 | OpaqueTy, ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, | 23 | ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | pub struct HirFormatter<'a> { | 26 | pub struct HirFormatter<'a> { |
@@ -353,7 +353,7 @@ impl HirDisplay for Ty { | |||
353 | _ => Cow::Borrowed(&[][..]), | 353 | _ => Cow::Borrowed(&[][..]), |
354 | }; | 354 | }; |
355 | 355 | ||
356 | if let [GenericPredicate::Implemented(trait_ref), _] = predicates.as_ref() { | 356 | if let [WhereClause::Implemented(trait_ref), _] = predicates.as_ref() { |
357 | let trait_ = trait_ref.hir_trait_id(); | 357 | let trait_ = trait_ref.hir_trait_id(); |
358 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) { | 358 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) { |
359 | return write!(f, "{}", ty_display); | 359 | return write!(f, "{}", ty_display); |
@@ -652,7 +652,7 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai | |||
652 | 652 | ||
653 | pub fn write_bounds_like_dyn_trait_with_prefix( | 653 | pub fn write_bounds_like_dyn_trait_with_prefix( |
654 | prefix: &str, | 654 | prefix: &str, |
655 | predicates: &[GenericPredicate], | 655 | predicates: &[WhereClause], |
656 | f: &mut HirFormatter, | 656 | f: &mut HirFormatter, |
657 | ) -> Result<(), HirDisplayError> { | 657 | ) -> Result<(), HirDisplayError> { |
658 | write!(f, "{}", prefix)?; | 658 | write!(f, "{}", prefix)?; |
@@ -665,7 +665,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix( | |||
665 | } | 665 | } |
666 | 666 | ||
667 | fn write_bounds_like_dyn_trait( | 667 | fn write_bounds_like_dyn_trait( |
668 | predicates: &[GenericPredicate], | 668 | predicates: &[WhereClause], |
669 | f: &mut HirFormatter, | 669 | f: &mut HirFormatter, |
670 | ) -> Result<(), HirDisplayError> { | 670 | ) -> Result<(), HirDisplayError> { |
671 | // Note: This code is written to produce nice results (i.e. | 671 | // Note: This code is written to produce nice results (i.e. |
@@ -679,7 +679,7 @@ fn write_bounds_like_dyn_trait( | |||
679 | let mut is_fn_trait = false; | 679 | let mut is_fn_trait = false; |
680 | for p in predicates.iter() { | 680 | for p in predicates.iter() { |
681 | match p { | 681 | match p { |
682 | GenericPredicate::Implemented(trait_ref) => { | 682 | WhereClause::Implemented(trait_ref) => { |
683 | let trait_ = trait_ref.hir_trait_id(); | 683 | let trait_ = trait_ref.hir_trait_id(); |
684 | if !is_fn_trait { | 684 | if !is_fn_trait { |
685 | is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_); | 685 | is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_); |
@@ -710,12 +710,12 @@ fn write_bounds_like_dyn_trait( | |||
710 | } | 710 | } |
711 | } | 711 | } |
712 | } | 712 | } |
713 | GenericPredicate::AliasEq(alias_eq) if is_fn_trait => { | 713 | WhereClause::AliasEq(alias_eq) if is_fn_trait => { |
714 | is_fn_trait = false; | 714 | is_fn_trait = false; |
715 | write!(f, " -> ")?; | 715 | write!(f, " -> ")?; |
716 | alias_eq.ty.hir_fmt(f)?; | 716 | alias_eq.ty.hir_fmt(f)?; |
717 | } | 717 | } |
718 | GenericPredicate::AliasEq(AliasEq { ty, alias }) => { | 718 | WhereClause::AliasEq(AliasEq { ty, alias }) => { |
719 | // in types in actual Rust, these will always come | 719 | // in types in actual Rust, these will always come |
720 | // after the corresponding Implemented predicate | 720 | // after the corresponding Implemented predicate |
721 | if angle_open { | 721 | if angle_open { |
@@ -731,16 +731,6 @@ fn write_bounds_like_dyn_trait( | |||
731 | } | 731 | } |
732 | ty.hir_fmt(f)?; | 732 | ty.hir_fmt(f)?; |
733 | } | 733 | } |
734 | GenericPredicate::Error => { | ||
735 | if angle_open { | ||
736 | // impl Trait<X, {error}> | ||
737 | write!(f, ", ")?; | ||
738 | } else if !first { | ||
739 | // impl Trait + {error} | ||
740 | write!(f, " + ")?; | ||
741 | } | ||
742 | p.hir_fmt(f)?; | ||
743 | } | ||
744 | } | 734 | } |
745 | first = false; | 735 | first = false; |
746 | } | 736 | } |
@@ -778,18 +768,15 @@ impl HirDisplay for TraitRef { | |||
778 | } | 768 | } |
779 | } | 769 | } |
780 | 770 | ||
781 | impl HirDisplay for GenericPredicate { | 771 | impl HirDisplay for WhereClause { |
782 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 772 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
783 | if f.should_truncate() { | 773 | if f.should_truncate() { |
784 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | 774 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
785 | } | 775 | } |
786 | 776 | ||
787 | match self { | 777 | match self { |
788 | GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, | 778 | WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, |
789 | GenericPredicate::AliasEq(AliasEq { | 779 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { |
790 | alias: AliasTy::Projection(projection_ty), | ||
791 | ty, | ||
792 | }) => { | ||
793 | write!(f, "<")?; | 780 | write!(f, "<")?; |
794 | projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; | 781 | projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; |
795 | write!( | 782 | write!( |
@@ -799,7 +786,7 @@ impl HirDisplay for GenericPredicate { | |||
799 | )?; | 786 | )?; |
800 | ty.hir_fmt(f)?; | 787 | ty.hir_fmt(f)?; |
801 | } | 788 | } |
802 | GenericPredicate::AliasEq(_) | GenericPredicate::Error => write!(f, "{{error}}")?, | 789 | WhereClause::AliasEq(_) => write!(f, "{{error}}")?, |
803 | } | 790 | } |
804 | Ok(()) | 791 | Ok(()) |
805 | } | 792 | } |
@@ -818,22 +805,12 @@ impl HirDisplay for Lifetime { | |||
818 | } | 805 | } |
819 | } | 806 | } |
820 | 807 | ||
821 | impl HirDisplay for Obligation { | 808 | impl HirDisplay for DomainGoal { |
822 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 809 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
823 | match self { | 810 | match self { |
824 | Obligation::Trait(tr) => { | 811 | DomainGoal::Holds(wc) => { |
825 | write!(f, "Implements(")?; | 812 | write!(f, "Holds(")?; |
826 | tr.hir_fmt(f)?; | 813 | wc.hir_fmt(f)?; |
827 | write!(f, ")") | ||
828 | } | ||
829 | Obligation::AliasEq(AliasEq { alias, ty }) => { | ||
830 | write!(f, "Normalize(")?; | ||
831 | match alias { | ||
832 | AliasTy::Projection(projection_ty) => projection_ty.hir_fmt(f)?, | ||
833 | AliasTy::Opaque(opaque) => opaque.hir_fmt(f)?, | ||
834 | } | ||
835 | write!(f, " => ")?; | ||
836 | ty.hir_fmt(f)?; | ||
837 | write!(f, ")") | 814 | write!(f, ")") |
838 | } | 815 | } |
839 | } | 816 | } |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 82186979a..b9e434c78 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -18,7 +18,7 @@ use std::mem; | |||
18 | use std::ops::Index; | 18 | use std::ops::Index; |
19 | use std::sync::Arc; | 19 | use std::sync::Arc; |
20 | 20 | ||
21 | use chalk_ir::Mutability; | 21 | use chalk_ir::{cast::Cast, Mutability}; |
22 | use hir_def::{ | 22 | use hir_def::{ |
23 | body::Body, | 23 | body::Body, |
24 | data::{ConstData, FunctionData, StaticData}, | 24 | data::{ConstData, FunctionData, StaticData}, |
@@ -37,7 +37,7 @@ use stdx::impl_from; | |||
37 | use syntax::SmolStr; | 37 | use syntax::SmolStr; |
38 | 38 | ||
39 | use super::{ | 39 | use super::{ |
40 | traits::{Guidance, Obligation, Solution}, | 40 | traits::{DomainGoal, Guidance, Solution}, |
41 | InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, | 41 | InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, |
42 | }; | 42 | }; |
43 | use crate::{ | 43 | use crate::{ |
@@ -204,7 +204,7 @@ struct InferenceContext<'a> { | |||
204 | resolver: Resolver, | 204 | resolver: Resolver, |
205 | table: unify::InferenceTable, | 205 | table: unify::InferenceTable, |
206 | trait_env: Arc<TraitEnvironment>, | 206 | trait_env: Arc<TraitEnvironment>, |
207 | obligations: Vec<Obligation>, | 207 | obligations: Vec<DomainGoal>, |
208 | result: InferenceResult, | 208 | result: InferenceResult, |
209 | /// The return type of the function being inferred, or the closure if we're | 209 | /// The return type of the function being inferred, or the closure if we're |
210 | /// currently within one. | 210 | /// currently within one. |
@@ -403,8 +403,8 @@ impl<'a> InferenceContext<'a> { | |||
403 | }), | 403 | }), |
404 | ty: ty.clone(), | 404 | ty: ty.clone(), |
405 | }; | 405 | }; |
406 | self.obligations.push(Obligation::Trait(trait_ref)); | 406 | self.obligations.push(trait_ref.cast(&Interner)); |
407 | self.obligations.push(Obligation::AliasEq(alias_eq)); | 407 | self.obligations.push(alias_eq.cast(&Interner)); |
408 | self.resolve_ty_as_possible(ty) | 408 | self.resolve_ty_as_possible(ty) |
409 | } | 409 | } |
410 | None => self.err_ty(), | 410 | None => self.err_ty(), |
@@ -430,7 +430,7 @@ impl<'a> InferenceContext<'a> { | |||
430 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { | 430 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { |
431 | let var = self.table.new_type_var(); | 431 | let var = self.table.new_type_var(); |
432 | let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; | 432 | let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; |
433 | let obligation = Obligation::AliasEq(alias_eq); | 433 | let obligation = alias_eq.cast(&Interner); |
434 | self.obligations.push(obligation); | 434 | self.obligations.push(obligation); |
435 | var | 435 | var |
436 | } | 436 | } |
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index b86474ed4..07eb96573 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -4,12 +4,11 @@ | |||
4 | //! | 4 | //! |
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use chalk_ir::{Mutability, TyVariableKind}; | 7 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; |
8 | use hir_def::lang_item::LangItemTarget; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | autoderef, to_chalk_trait_id, traits::Solution, Interner, Obligation, Substitution, TraitRef, | 11 | autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind, |
12 | Ty, TyKind, | ||
13 | }; | 12 | }; |
14 | 13 | ||
15 | use super::{InEnvironment, InferenceContext}; | 14 | use super::{InEnvironment, InferenceContext}; |
@@ -143,7 +142,7 @@ impl<'a> InferenceContext<'a> { | |||
143 | .build(); | 142 | .build(); |
144 | let trait_ref = | 143 | let trait_ref = |
145 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; | 144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; |
146 | let goal = InEnvironment::new(self.trait_env.clone(), Obligation::Trait(trait_ref)); | 145 | let goal = InEnvironment::new(self.trait_env.clone(), trait_ref.cast(&Interner)); |
147 | 146 | ||
148 | let canonicalizer = self.canonicalizer(); | 147 | let canonicalizer = self.canonicalizer(); |
149 | let canonicalized = canonicalizer.canonicalize_obligation(goal); | 148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 93548b6c0..79bbc5dab 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::iter::{repeat, repeat_with}; | 3 | use std::iter::{repeat, repeat_with}; |
4 | use std::{mem, sync::Arc}; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use chalk_ir::{Mutability, TyVariableKind}; | 6 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; |
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
9 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | to_assoc_type_id, to_chalk_trait_id, | 21 | to_assoc_type_id, to_chalk_trait_id, |
22 | traits::{chalk::from_chalk, FnTrait, InEnvironment}, | 22 | traits::{chalk::from_chalk, FnTrait, InEnvironment}, |
23 | utils::{generics, variant_data, Generics}, | 23 | utils::{generics, variant_data, Generics}, |
24 | AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, Rawness, Scalar, | 24 | AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar, |
25 | Substitution, TraitRef, Ty, TyKind, | 25 | Substitution, TraitRef, Ty, TyKind, |
26 | }; | 26 | }; |
27 | 27 | ||
@@ -90,10 +90,9 @@ impl<'a> InferenceContext<'a> { | |||
90 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); | 90 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); |
91 | 91 | ||
92 | let trait_env = Arc::clone(&self.trait_env); | 92 | let trait_env = Arc::clone(&self.trait_env); |
93 | let implements_fn_trait = Obligation::Trait(TraitRef { | 93 | let implements_fn_trait: DomainGoal = |
94 | trait_id: to_chalk_trait_id(fn_once_trait), | 94 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } |
95 | substitution: substs.clone(), | 95 | .cast(&Interner); |
96 | }); | ||
97 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { | 96 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { |
98 | value: implements_fn_trait.clone(), | 97 | value: implements_fn_trait.clone(), |
99 | environment: trait_env, | 98 | environment: trait_env, |
@@ -938,22 +937,20 @@ impl<'a> InferenceContext<'a> { | |||
938 | let generic_predicates = self.db.generic_predicates(def.into()); | 937 | let generic_predicates = self.db.generic_predicates(def.into()); |
939 | for predicate in generic_predicates.iter() { | 938 | for predicate in generic_predicates.iter() { |
940 | let predicate = predicate.clone().subst(parameters); | 939 | let predicate = predicate.clone().subst(parameters); |
941 | if let Some(obligation) = Obligation::from_predicate(predicate) { | 940 | self.obligations.push(predicate.cast(&Interner)); |
942 | self.obligations.push(obligation); | ||
943 | } | ||
944 | } | 941 | } |
945 | // add obligation for trait implementation, if this is a trait method | 942 | // add obligation for trait implementation, if this is a trait method |
946 | match def { | 943 | match def { |
947 | CallableDefId::FunctionId(f) => { | 944 | CallableDefId::FunctionId(f) => { |
948 | if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container | 945 | if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container |
949 | { | 946 | { |
950 | // construct a TraitDef | 947 | // construct a TraitRef |
951 | let substs = | 948 | let substs = |
952 | parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); | 949 | parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); |
953 | self.obligations.push(Obligation::Trait(TraitRef { | 950 | self.obligations.push( |
954 | trait_id: to_chalk_trait_id(trait_), | 951 | TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs } |
955 | substitution: substs, | 952 | .cast(&Interner), |
956 | })); | 953 | ); |
957 | } | 954 | } |
958 | } | 955 | } |
959 | CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} | 956 | CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} |
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index e15135fc1..58cce56ab 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | use std::iter; | 3 | use std::iter; |
4 | 4 | ||
5 | use chalk_ir::cast::Cast; | ||
5 | use hir_def::{ | 6 | use hir_def::{ |
6 | path::{Path, PathSegment}, | 7 | path::{Path, PathSegment}, |
7 | resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, | 8 | resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, |
@@ -256,10 +257,13 @@ impl<'a> InferenceContext<'a> { | |||
256 | .push(ty.clone()) | 257 | .push(ty.clone()) |
257 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 258 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
258 | .build(); | 259 | .build(); |
259 | self.obligations.push(super::Obligation::Trait(TraitRef { | 260 | self.obligations.push( |
260 | trait_id: to_chalk_trait_id(trait_), | 261 | TraitRef { |
261 | substitution: trait_substs.clone(), | 262 | trait_id: to_chalk_trait_id(trait_), |
262 | })); | 263 | substitution: trait_substs.clone(), |
264 | } | ||
265 | .cast(&Interner), | ||
266 | ); | ||
263 | Some(trait_substs) | 267 | Some(trait_substs) |
264 | } | 268 | } |
265 | AssocContainerId::ModuleId(_) => None, | 269 | AssocContainerId::ModuleId(_) => None, |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 4738ec08a..1fc03c8f4 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -5,10 +5,10 @@ use std::borrow::Cow; | |||
5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind}; | 5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind}; |
6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
7 | 7 | ||
8 | use super::{InferenceContext, Obligation}; | 8 | use super::{DomainGoal, InferenceContext}; |
9 | use crate::{ | 9 | use crate::{ |
10 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate, | 10 | AliasEq, AliasTy, BoundVar, Canonical, DebruijnIndex, FnPointer, InEnvironment, InferenceVar, |
11 | InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, | 11 | Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | impl<'a> InferenceContext<'a> { | 14 | impl<'a> InferenceContext<'a> { |
@@ -87,14 +87,11 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
87 | 87 | ||
88 | pub(crate) fn canonicalize_obligation( | 88 | pub(crate) fn canonicalize_obligation( |
89 | mut self, | 89 | mut self, |
90 | obligation: InEnvironment<Obligation>, | 90 | obligation: InEnvironment<DomainGoal>, |
91 | ) -> Canonicalized<InEnvironment<Obligation>> { | 91 | ) -> Canonicalized<InEnvironment<DomainGoal>> { |
92 | let result = match obligation.value { | 92 | let result = match obligation.value { |
93 | Obligation::Trait(tr) => { | 93 | DomainGoal::Holds(wc) => { |
94 | Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST)) | 94 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) |
95 | } | ||
96 | Obligation::AliasEq(alias_eq) => { | ||
97 | Obligation::AliasEq(self.do_canonicalize(alias_eq, DebruijnIndex::INNERMOST)) | ||
98 | } | 95 | } |
99 | }; | 96 | }; |
100 | self.into_canonicalized(InEnvironment { | 97 | self.into_canonicalized(InEnvironment { |
@@ -382,21 +379,16 @@ impl InferenceTable { | |||
382 | } | 379 | } |
383 | } | 380 | } |
384 | 381 | ||
385 | fn unify_preds( | 382 | fn unify_preds(&mut self, pred1: &WhereClause, pred2: &WhereClause, depth: usize) -> bool { |
386 | &mut self, | ||
387 | pred1: &GenericPredicate, | ||
388 | pred2: &GenericPredicate, | ||
389 | depth: usize, | ||
390 | ) -> bool { | ||
391 | match (pred1, pred2) { | 383 | match (pred1, pred2) { |
392 | (GenericPredicate::Implemented(tr1), GenericPredicate::Implemented(tr2)) | 384 | (WhereClause::Implemented(tr1), WhereClause::Implemented(tr2)) |
393 | if tr1.trait_id == tr2.trait_id => | 385 | if tr1.trait_id == tr2.trait_id => |
394 | { | 386 | { |
395 | self.unify_substs(&tr1.substitution, &tr2.substitution, depth + 1) | 387 | self.unify_substs(&tr1.substitution, &tr2.substitution, depth + 1) |
396 | } | 388 | } |
397 | ( | 389 | ( |
398 | GenericPredicate::AliasEq(AliasEq { alias: alias1, ty: ty1 }), | 390 | WhereClause::AliasEq(AliasEq { alias: alias1, ty: ty1 }), |
399 | GenericPredicate::AliasEq(AliasEq { alias: alias2, ty: ty2 }), | 391 | WhereClause::AliasEq(AliasEq { alias: alias2, ty: ty2 }), |
400 | ) => { | 392 | ) => { |
401 | let (substitution1, substitution2) = match (alias1, alias2) { | 393 | let (substitution1, substitution2) = match (alias1, alias2) { |
402 | (AliasTy::Projection(projection_ty1), AliasTy::Projection(projection_ty2)) | 394 | (AliasTy::Projection(projection_ty1), AliasTy::Projection(projection_ty2)) |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 2afcb5413..c46529879 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -13,6 +13,7 @@ mod op; | |||
13 | mod lower; | 13 | mod lower; |
14 | pub(crate) mod infer; | 14 | pub(crate) mod infer; |
15 | pub(crate) mod utils; | 15 | pub(crate) mod utils; |
16 | mod chalk_cast; | ||
16 | 17 | ||
17 | pub mod display; | 18 | pub mod display; |
18 | pub mod db; | 19 | pub mod db; |
@@ -45,9 +46,11 @@ pub use lower::{ | |||
45 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, | 46 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, |
46 | TyDefId, TyLoweringContext, ValueTyDefId, | 47 | TyDefId, TyLoweringContext, ValueTyDefId, |
47 | }; | 48 | }; |
48 | pub use traits::{AliasEq, InEnvironment, Obligation, TraitEnvironment}; | 49 | pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment}; |
49 | 50 | ||
50 | pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind}; | 51 | pub use chalk_ir::{ |
52 | cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, | ||
53 | }; | ||
51 | 54 | ||
52 | pub use crate::traits::chalk::Interner; | 55 | pub use crate::traits::chalk::Interner; |
53 | 56 | ||
@@ -276,7 +279,7 @@ pub enum TyKind { | |||
276 | /// represents the `Self` type inside the bounds. This is currently | 279 | /// represents the `Self` type inside the bounds. This is currently |
277 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | 280 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it |
278 | /// didn't seem worth the overhead yet. | 281 | /// didn't seem worth the overhead yet. |
279 | Dyn(Arc<[GenericPredicate]>), | 282 | Dyn(Arc<[WhereClause]>), |
280 | 283 | ||
281 | /// A placeholder for a type which could not be computed; this is propagated | 284 | /// A placeholder for a type which could not be computed; this is propagated |
282 | /// to avoid useless error messages. Doubles as a placeholder where type | 285 | /// to avoid useless error messages. Doubles as a placeholder where type |
@@ -564,42 +567,34 @@ impl TypeWalk for TraitRef { | |||
564 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | 567 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the |
565 | /// parameters of a generic item. | 568 | /// parameters of a generic item. |
566 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 569 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
567 | pub enum GenericPredicate { | 570 | pub enum WhereClause { |
568 | /// The given trait needs to be implemented for its type parameters. | 571 | /// The given trait needs to be implemented for its type parameters. |
569 | Implemented(TraitRef), | 572 | Implemented(TraitRef), |
570 | /// An associated type bindings like in `Iterator<Item = T>`. | 573 | /// An associated type bindings like in `Iterator<Item = T>`. |
571 | AliasEq(AliasEq), | 574 | AliasEq(AliasEq), |
572 | /// We couldn't resolve the trait reference. (If some type parameters can't | ||
573 | /// be resolved, they will just be Unknown). | ||
574 | Error, | ||
575 | } | 575 | } |
576 | 576 | ||
577 | impl GenericPredicate { | 577 | impl WhereClause { |
578 | pub fn is_error(&self) -> bool { | ||
579 | matches!(self, GenericPredicate::Error) | ||
580 | } | ||
581 | |||
582 | pub fn is_implemented(&self) -> bool { | 578 | pub fn is_implemented(&self) -> bool { |
583 | matches!(self, GenericPredicate::Implemented(_)) | 579 | matches!(self, WhereClause::Implemented(_)) |
584 | } | 580 | } |
585 | 581 | ||
586 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> { | 582 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> { |
587 | match self { | 583 | match self { |
588 | GenericPredicate::Implemented(tr) => Some(tr.clone()), | 584 | WhereClause::Implemented(tr) => Some(tr.clone()), |
589 | GenericPredicate::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => { | 585 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => { |
590 | Some(proj.trait_ref(db)) | 586 | Some(proj.trait_ref(db)) |
591 | } | 587 | } |
592 | GenericPredicate::AliasEq(_) | GenericPredicate::Error => None, | 588 | WhereClause::AliasEq(_) => None, |
593 | } | 589 | } |
594 | } | 590 | } |
595 | } | 591 | } |
596 | 592 | ||
597 | impl TypeWalk for GenericPredicate { | 593 | impl TypeWalk for WhereClause { |
598 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | 594 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
599 | match self { | 595 | match self { |
600 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f), | 596 | WhereClause::Implemented(trait_ref) => trait_ref.walk(f), |
601 | GenericPredicate::AliasEq(alias_eq) => alias_eq.walk(f), | 597 | WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), |
602 | GenericPredicate::Error => {} | ||
603 | } | 598 | } |
604 | } | 599 | } |
605 | 600 | ||
@@ -609,9 +604,8 @@ impl TypeWalk for GenericPredicate { | |||
609 | binders: DebruijnIndex, | 604 | binders: DebruijnIndex, |
610 | ) { | 605 | ) { |
611 | match self { | 606 | match self { |
612 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), | 607 | WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), |
613 | GenericPredicate::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders), | 608 | WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders), |
614 | GenericPredicate::Error => {} | ||
615 | } | 609 | } |
616 | } | 610 | } |
617 | } | 611 | } |
@@ -815,7 +809,7 @@ impl Ty { | |||
815 | pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { | 809 | pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { |
816 | match self.interned(&Interner) { | 810 | match self.interned(&Interner) { |
817 | TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b { | 811 | TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b { |
818 | GenericPredicate::Implemented(trait_ref) => Some(trait_ref), | 812 | WhereClause::Implemented(trait_ref) => Some(trait_ref), |
819 | _ => None, | 813 | _ => None, |
820 | }), | 814 | }), |
821 | _ => None, | 815 | _ => None, |
@@ -894,7 +888,7 @@ impl Ty { | |||
894 | } | 888 | } |
895 | } | 889 | } |
896 | 890 | ||
897 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> { | 891 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<WhereClause>> { |
898 | match self.interned(&Interner) { | 892 | match self.interned(&Interner) { |
899 | TyKind::OpaqueType(opaque_ty_id, ..) => { | 893 | TyKind::OpaqueType(opaque_ty_id, ..) => { |
900 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { | 894 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { |
@@ -907,7 +901,7 @@ impl Ty { | |||
907 | // This is only used by type walking. | 901 | // This is only used by type walking. |
908 | // Parameters will be walked outside, and projection predicate is not used. | 902 | // Parameters will be walked outside, and projection predicate is not used. |
909 | // So just provide the Future trait. | 903 | // So just provide the Future trait. |
910 | let impl_bound = GenericPredicate::Implemented(TraitRef { | 904 | let impl_bound = WhereClause::Implemented(TraitRef { |
911 | trait_id: to_chalk_trait_id(future_trait), | 905 | trait_id: to_chalk_trait_id(future_trait), |
912 | substitution: Substitution::empty(), | 906 | substitution: Substitution::empty(), |
913 | }); | 907 | }); |
@@ -1166,7 +1160,7 @@ pub struct ReturnTypeImplTraits { | |||
1166 | 1160 | ||
1167 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 1161 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
1168 | pub(crate) struct ReturnTypeImplTrait { | 1162 | pub(crate) struct ReturnTypeImplTrait { |
1169 | pub(crate) bounds: Binders<Vec<GenericPredicate>>, | 1163 | pub(crate) bounds: Binders<Vec<WhereClause>>, |
1170 | } | 1164 | } |
1171 | 1165 | ||
1172 | pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { | 1166 | pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 7d22c3df5..cbbb535e5 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -33,9 +33,9 @@ use crate::{ | |||
33 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, | 33 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, |
34 | variant_data, | 34 | variant_data, |
35 | }, | 35 | }, |
36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, | 36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, ImplTraitId, |
37 | GenericPredicate, ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait, | 37 | OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, |
38 | ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, | 38 | TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, WhereClause, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | #[derive(Debug)] | 41 | #[derive(Debug)] |
@@ -373,8 +373,7 @@ impl<'a> TyLoweringContext<'a> { | |||
373 | // FIXME report error (ambiguous associated type) | 373 | // FIXME report error (ambiguous associated type) |
374 | TyKind::Unknown.intern(&Interner) | 374 | TyKind::Unknown.intern(&Interner) |
375 | } else { | 375 | } else { |
376 | TyKind::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) | 376 | TyKind::Dyn(Arc::new([WhereClause::Implemented(trait_ref)])).intern(&Interner) |
377 | .intern(&Interner) | ||
378 | }; | 377 | }; |
379 | return (ty, None); | 378 | return (ty, None); |
380 | } | 379 | } |
@@ -667,7 +666,7 @@ impl<'a> TyLoweringContext<'a> { | |||
667 | pub(crate) fn lower_where_predicate( | 666 | pub(crate) fn lower_where_predicate( |
668 | &'a self, | 667 | &'a self, |
669 | where_predicate: &'a WherePredicate, | 668 | where_predicate: &'a WherePredicate, |
670 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 669 | ) -> impl Iterator<Item = WhereClause> + 'a { |
671 | match where_predicate { | 670 | match where_predicate { |
672 | WherePredicate::ForLifetime { target, bound, .. } | 671 | WherePredicate::ForLifetime { target, bound, .. } |
673 | | WherePredicate::TypeBound { target, bound } => { | 672 | | WherePredicate::TypeBound { target, bound } => { |
@@ -699,17 +698,15 @@ impl<'a> TyLoweringContext<'a> { | |||
699 | &'a self, | 698 | &'a self, |
700 | bound: &'a TypeBound, | 699 | bound: &'a TypeBound, |
701 | self_ty: Ty, | 700 | self_ty: Ty, |
702 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 701 | ) -> impl Iterator<Item = WhereClause> + 'a { |
703 | let mut bindings = None; | 702 | let mut bindings = None; |
704 | let trait_ref = match bound { | 703 | let trait_ref = match bound { |
705 | TypeBound::Path(path) => { | 704 | TypeBound::Path(path) => { |
706 | bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); | 705 | bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); |
707 | Some( | 706 | bindings.clone().map(WhereClause::Implemented) |
708 | bindings.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented), | ||
709 | ) | ||
710 | } | 707 | } |
711 | TypeBound::Lifetime(_) => None, | 708 | TypeBound::Lifetime(_) => None, |
712 | TypeBound::Error => Some(GenericPredicate::Error), | 709 | TypeBound::Error => None, |
713 | }; | 710 | }; |
714 | trait_ref.into_iter().chain( | 711 | trait_ref.into_iter().chain( |
715 | bindings | 712 | bindings |
@@ -722,7 +719,7 @@ impl<'a> TyLoweringContext<'a> { | |||
722 | &'a self, | 719 | &'a self, |
723 | bound: &'a TypeBound, | 720 | bound: &'a TypeBound, |
724 | trait_ref: TraitRef, | 721 | trait_ref: TraitRef, |
725 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 722 | ) -> impl Iterator<Item = WhereClause> + 'a { |
726 | let last_segment = match bound { | 723 | let last_segment = match bound { |
727 | TypeBound::Path(path) => path.segments().last(), | 724 | TypeBound::Path(path) => path.segments().last(), |
728 | TypeBound::Error | TypeBound::Lifetime(_) => None, | 725 | TypeBound::Error | TypeBound::Lifetime(_) => None, |
@@ -738,7 +735,7 @@ impl<'a> TyLoweringContext<'a> { | |||
738 | &binding.name, | 735 | &binding.name, |
739 | ); | 736 | ); |
740 | let (super_trait_ref, associated_ty) = match found { | 737 | let (super_trait_ref, associated_ty) = match found { |
741 | None => return SmallVec::<[GenericPredicate; 1]>::new(), | 738 | None => return SmallVec::<[WhereClause; 1]>::new(), |
742 | Some(t) => t, | 739 | Some(t) => t, |
743 | }; | 740 | }; |
744 | let projection_ty = ProjectionTy { | 741 | let projection_ty = ProjectionTy { |
@@ -752,7 +749,7 @@ impl<'a> TyLoweringContext<'a> { | |||
752 | let ty = self.lower_ty(type_ref); | 749 | let ty = self.lower_ty(type_ref); |
753 | let alias_eq = | 750 | let alias_eq = |
754 | AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; | 751 | AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; |
755 | preds.push(GenericPredicate::AliasEq(alias_eq)); | 752 | preds.push(WhereClause::AliasEq(alias_eq)); |
756 | } | 753 | } |
757 | for bound in &binding.bounds { | 754 | for bound in &binding.bounds { |
758 | preds.extend(self.lower_type_bound( | 755 | preds.extend(self.lower_type_bound( |
@@ -809,7 +806,7 @@ pub fn associated_type_shorthand_candidates<R>( | |||
809 | let mut traits_: Vec<_> = predicates | 806 | let mut traits_: Vec<_> = predicates |
810 | .iter() | 807 | .iter() |
811 | .filter_map(|pred| match &pred.value { | 808 | .filter_map(|pred| match &pred.value { |
812 | GenericPredicate::Implemented(tr) => Some(tr.clone()), | 809 | WhereClause::Implemented(tr) => Some(tr.clone()), |
813 | _ => None, | 810 | _ => None, |
814 | }) | 811 | }) |
815 | .collect(); | 812 | .collect(); |
@@ -881,7 +878,7 @@ pub(crate) fn field_types_query( | |||
881 | pub(crate) fn generic_predicates_for_param_query( | 878 | pub(crate) fn generic_predicates_for_param_query( |
882 | db: &dyn HirDatabase, | 879 | db: &dyn HirDatabase, |
883 | param_id: TypeParamId, | 880 | param_id: TypeParamId, |
884 | ) -> Arc<[Binders<GenericPredicate>]> { | 881 | ) -> Arc<[Binders<WhereClause>]> { |
885 | let resolver = param_id.parent.resolver(db.upcast()); | 882 | let resolver = param_id.parent.resolver(db.upcast()); |
886 | let ctx = | 883 | let ctx = |
887 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 884 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
@@ -907,7 +904,7 @@ pub(crate) fn generic_predicates_for_param_recover( | |||
907 | _db: &dyn HirDatabase, | 904 | _db: &dyn HirDatabase, |
908 | _cycle: &[String], | 905 | _cycle: &[String], |
909 | _param_id: &TypeParamId, | 906 | _param_id: &TypeParamId, |
910 | ) -> Arc<[Binders<GenericPredicate>]> { | 907 | ) -> Arc<[Binders<WhereClause>]> { |
911 | Arc::new([]) | 908 | Arc::new([]) |
912 | } | 909 | } |
913 | 910 | ||
@@ -922,10 +919,7 @@ pub(crate) fn trait_environment_query( | |||
922 | let mut clauses = Vec::new(); | 919 | let mut clauses = Vec::new(); |
923 | for pred in resolver.where_predicates_in_scope() { | 920 | for pred in resolver.where_predicates_in_scope() { |
924 | for pred in ctx.lower_where_predicate(pred) { | 921 | for pred in ctx.lower_where_predicate(pred) { |
925 | if pred.is_error() { | 922 | if let WhereClause::Implemented(tr) = &pred { |
926 | continue; | ||
927 | } | ||
928 | if let GenericPredicate::Implemented(tr) = &pred { | ||
929 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); | 923 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); |
930 | } | 924 | } |
931 | let program_clause: chalk_ir::ProgramClause<Interner> = | 925 | let program_clause: chalk_ir::ProgramClause<Interner> = |
@@ -951,7 +945,7 @@ pub(crate) fn trait_environment_query( | |||
951 | cov_mark::hit!(trait_self_implements_self); | 945 | cov_mark::hit!(trait_self_implements_self); |
952 | let substs = Substitution::type_params(db, trait_id); | 946 | let substs = Substitution::type_params(db, trait_id); |
953 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; | 947 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; |
954 | let pred = GenericPredicate::Implemented(trait_ref); | 948 | let pred = WhereClause::Implemented(trait_ref); |
955 | let program_clause: chalk_ir::ProgramClause<Interner> = | 949 | let program_clause: chalk_ir::ProgramClause<Interner> = |
956 | pred.clone().to_chalk(db).cast(&Interner); | 950 | pred.clone().to_chalk(db).cast(&Interner); |
957 | clauses.push(program_clause.into_from_env_clause(&Interner)); | 951 | clauses.push(program_clause.into_from_env_clause(&Interner)); |
@@ -966,7 +960,7 @@ pub(crate) fn trait_environment_query( | |||
966 | pub(crate) fn generic_predicates_query( | 960 | pub(crate) fn generic_predicates_query( |
967 | db: &dyn HirDatabase, | 961 | db: &dyn HirDatabase, |
968 | def: GenericDefId, | 962 | def: GenericDefId, |
969 | ) -> Arc<[Binders<GenericPredicate>]> { | 963 | ) -> Arc<[Binders<WhereClause>]> { |
970 | let resolver = def.resolver(db.upcast()); | 964 | let resolver = def.resolver(db.upcast()); |
971 | let ctx = | 965 | let ctx = |
972 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 966 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 01b78fb44..da6bc2a4a 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -6,7 +6,7 @@ use std::{iter, sync::Arc}; | |||
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
9 | use chalk_ir::Mutability; | 9 | use chalk_ir::{cast::Cast, Mutability}; |
10 | use hir_def::{ | 10 | use hir_def::{ |
11 | lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, | 11 | lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, |
12 | ImplId, Lookup, ModuleId, TraitId, | 12 | ImplId, Lookup, ModuleId, TraitId, |
@@ -767,7 +767,7 @@ fn generic_implements_goal( | |||
767 | env: Arc<TraitEnvironment>, | 767 | env: Arc<TraitEnvironment>, |
768 | trait_: TraitId, | 768 | trait_: TraitId, |
769 | self_ty: Canonical<Ty>, | 769 | self_ty: Canonical<Ty>, |
770 | ) -> Canonical<InEnvironment<super::Obligation>> { | 770 | ) -> Canonical<InEnvironment<super::DomainGoal>> { |
771 | let mut kinds = self_ty.kinds.to_vec(); | 771 | let mut kinds = self_ty.kinds.to_vec(); |
772 | let substs = super::Substitution::build_for_def(db, trait_) | 772 | let substs = super::Substitution::build_for_def(db, trait_) |
773 | .push(self_ty.value) | 773 | .push(self_ty.value) |
@@ -775,7 +775,7 @@ fn generic_implements_goal( | |||
775 | .build(); | 775 | .build(); |
776 | kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1)); | 776 | kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1)); |
777 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; | 777 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; |
778 | let obligation = super::Obligation::Trait(trait_ref); | 778 | let obligation = trait_ref.cast(&Interner); |
779 | Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } | 779 | Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } |
780 | } | 780 | } |
781 | 781 | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 8270fa219..8f2bdffc0 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -1412,8 +1412,8 @@ fn weird_bounds() { | |||
1412 | 50..51 'b': impl | 1412 | 50..51 'b': impl |
1413 | 69..70 'c': impl Trait | 1413 | 69..70 'c': impl Trait |
1414 | 86..87 'd': impl | 1414 | 86..87 'd': impl |
1415 | 107..108 'e': impl {error} | 1415 | 107..108 'e': impl |
1416 | 123..124 'f': impl Trait + {error} | 1416 | 123..124 'f': impl Trait |
1417 | 147..149 '{}': () | 1417 | 147..149 '{}': () |
1418 | "#]], | 1418 | "#]], |
1419 | ); | 1419 | ); |
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index ac7de7605..7dadd1ffb 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -9,8 +9,8 @@ use hir_def::{lang_item::LangItemTarget, TraitId}; | |||
9 | use stdx::panic_context; | 9 | use stdx::panic_context; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | db::HirDatabase, AliasTy, Canonical, DebruijnIndex, GenericPredicate, HirDisplay, Substitution, | 12 | db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind, |
13 | TraitRef, Ty, TyKind, TypeWalk, | 13 | TypeWalk, WhereClause, |
14 | }; | 14 | }; |
15 | 15 | ||
16 | use self::chalk::{from_chalk, Interner, ToChalk}; | 16 | use self::chalk::{from_chalk, Interner, ToChalk}; |
@@ -88,21 +88,8 @@ impl<T> InEnvironment<T> { | |||
88 | /// a certain type implements a certain trait. Proving the Obligation might | 88 | /// a certain type implements a certain trait. Proving the Obligation might |
89 | /// result in additional information about inference variables. | 89 | /// result in additional information about inference variables. |
90 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 90 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
91 | pub enum Obligation { | 91 | pub enum DomainGoal { |
92 | /// Prove that a certain type implements a trait (the type is the `Self` type | 92 | Holds(WhereClause), |
93 | /// parameter to the `TraitRef`). | ||
94 | Trait(TraitRef), | ||
95 | AliasEq(AliasEq), | ||
96 | } | ||
97 | |||
98 | impl Obligation { | ||
99 | pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> { | ||
100 | match predicate { | ||
101 | GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)), | ||
102 | GenericPredicate::AliasEq(alias_eq) => Some(Obligation::AliasEq(alias_eq)), | ||
103 | GenericPredicate::Error => None, | ||
104 | } | ||
105 | } | ||
106 | } | 93 | } |
107 | 94 | ||
108 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 95 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
@@ -137,16 +124,20 @@ impl TypeWalk for AliasEq { | |||
137 | pub(crate) fn trait_solve_query( | 124 | pub(crate) fn trait_solve_query( |
138 | db: &dyn HirDatabase, | 125 | db: &dyn HirDatabase, |
139 | krate: CrateId, | 126 | krate: CrateId, |
140 | goal: Canonical<InEnvironment<Obligation>>, | 127 | goal: Canonical<InEnvironment<DomainGoal>>, |
141 | ) -> Option<Solution> { | 128 | ) -> Option<Solution> { |
142 | let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { | 129 | let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { |
143 | Obligation::Trait(it) => db.trait_data(it.hir_trait_id()).name.to_string(), | 130 | DomainGoal::Holds(WhereClause::Implemented(it)) => { |
144 | Obligation::AliasEq(_) => "alias_eq".to_string(), | 131 | db.trait_data(it.hir_trait_id()).name.to_string() |
132 | } | ||
133 | DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(), | ||
145 | }); | 134 | }); |
146 | log::info!("trait_solve_query({})", goal.value.value.display(db)); | 135 | log::info!("trait_solve_query({})", goal.value.value.display(db)); |
147 | 136 | ||
148 | if let Obligation::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), .. }) = | 137 | if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq { |
149 | &goal.value.value | 138 | alias: AliasTy::Projection(projection_ty), |
139 | .. | ||
140 | })) = &goal.value.value | ||
150 | { | 141 | { |
151 | if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { | 142 | if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { |
152 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible | 143 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 080764e76..734679414 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -21,8 +21,8 @@ use crate::{ | |||
21 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, | 21 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, |
22 | to_assoc_type_id, to_chalk_trait_id, | 22 | to_assoc_type_id, to_chalk_trait_id, |
23 | utils::generics, | 23 | utils::generics, |
24 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, | 24 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, ProjectionTy, |
25 | GenericPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind, | 25 | Substitution, TraitRef, Ty, TyKind, WhereClause, |
26 | }; | 26 | }; |
27 | use mapping::{ | 27 | use mapping::{ |
28 | convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, | 28 | convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, |
@@ -187,13 +187,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
187 | let data = &datas.value.impl_traits[idx as usize]; | 187 | let data = &datas.value.impl_traits[idx as usize]; |
188 | let bound = OpaqueTyDatumBound { | 188 | let bound = OpaqueTyDatumBound { |
189 | bounds: make_binders( | 189 | bounds: make_binders( |
190 | data.bounds | 190 | data.bounds.value.iter().cloned().map(|b| b.to_chalk(self.db)).collect(), |
191 | .value | ||
192 | .iter() | ||
193 | .cloned() | ||
194 | .filter(|b| !b.is_error()) | ||
195 | .map(|b| b.to_chalk(self.db)) | ||
196 | .collect(), | ||
197 | 1, | 191 | 1, |
198 | ), | 192 | ), |
199 | where_clauses: make_binders(vec![], 0), | 193 | where_clauses: make_binders(vec![], 0), |
@@ -218,7 +212,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
218 | // |-------------OpaqueTyDatumBound--------------| | 212 | // |-------------OpaqueTyDatumBound--------------| |
219 | // for<T> <Self> [Future<Self>, Future::Output<Self> = T] | 213 | // for<T> <Self> [Future<Self>, Future::Output<Self> = T] |
220 | // ^1 ^0 ^0 ^0 ^1 | 214 | // ^1 ^0 ^0 ^0 ^1 |
221 | let impl_bound = GenericPredicate::Implemented(TraitRef { | 215 | let impl_bound = WhereClause::Implemented(TraitRef { |
222 | trait_id: to_chalk_trait_id(future_trait), | 216 | trait_id: to_chalk_trait_id(future_trait), |
223 | // Self type as the first parameter. | 217 | // Self type as the first parameter. |
224 | substitution: Substitution::single( | 218 | substitution: Substitution::single( |
@@ -229,7 +223,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
229 | .intern(&Interner), | 223 | .intern(&Interner), |
230 | ), | 224 | ), |
231 | }); | 225 | }); |
232 | let proj_bound = GenericPredicate::AliasEq(AliasEq { | 226 | let proj_bound = WhereClause::AliasEq(AliasEq { |
233 | alias: AliasTy::Projection(ProjectionTy { | 227 | alias: AliasTy::Projection(ProjectionTy { |
234 | associated_ty_id: to_assoc_type_id(future_output), | 228 | associated_ty_id: to_assoc_type_id(future_output), |
235 | // Self type as the first parameter. | 229 | // Self type as the first parameter. |
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 62b779008..65feb82e5 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -13,9 +13,9 @@ use crate::{ | |||
13 | db::HirDatabase, | 13 | db::HirDatabase, |
14 | from_assoc_type_id, | 14 | from_assoc_type_id, |
15 | primitive::UintTy, | 15 | primitive::UintTy, |
16 | traits::{Canonical, Obligation}, | 16 | traits::{Canonical, DomainGoal}, |
17 | AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy, ProjectionTy, | 17 | AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution, |
18 | Scalar, Substitution, TraitRef, Ty, | 18 | TraitRef, Ty, WhereClause, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | use super::interner::*; | 21 | use super::interner::*; |
@@ -98,7 +98,7 @@ impl ToChalk for Ty { | |||
98 | TyKind::Dyn(predicates) => { | 98 | TyKind::Dyn(predicates) => { |
99 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( | 99 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( |
100 | &Interner, | 100 | &Interner, |
101 | predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), | 101 | predicates.iter().cloned().map(|p| p.to_chalk(db)), |
102 | ); | 102 | ); |
103 | let bounded_ty = chalk_ir::DynTy { | 103 | let bounded_ty = chalk_ir::DynTy { |
104 | bounds: make_binders(where_clauses, 1), | 104 | bounds: make_binders(where_clauses, 1), |
@@ -304,28 +304,27 @@ impl ToChalk for TypeAliasAsValue { | |||
304 | } | 304 | } |
305 | } | 305 | } |
306 | 306 | ||
307 | impl ToChalk for GenericPredicate { | 307 | impl ToChalk for WhereClause { |
308 | type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; | 308 | type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; |
309 | 309 | ||
310 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { | 310 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { |
311 | match self { | 311 | match self { |
312 | GenericPredicate::Implemented(trait_ref) => { | 312 | WhereClause::Implemented(trait_ref) => { |
313 | let chalk_trait_ref = trait_ref.to_chalk(db); | 313 | let chalk_trait_ref = trait_ref.to_chalk(db); |
314 | let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); | 314 | let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); |
315 | make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) | 315 | make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) |
316 | } | 316 | } |
317 | GenericPredicate::AliasEq(alias_eq) => make_binders( | 317 | WhereClause::AliasEq(alias_eq) => make_binders( |
318 | chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)), | 318 | chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)), |
319 | 0, | 319 | 0, |
320 | ), | 320 | ), |
321 | GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), | ||
322 | } | 321 | } |
323 | } | 322 | } |
324 | 323 | ||
325 | fn from_chalk( | 324 | fn from_chalk( |
326 | db: &dyn HirDatabase, | 325 | db: &dyn HirDatabase, |
327 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, | 326 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, |
328 | ) -> GenericPredicate { | 327 | ) -> WhereClause { |
329 | // we don't produce any where clauses with binders and can't currently deal with them | 328 | // we don't produce any where clauses with binders and can't currently deal with them |
330 | match where_clause | 329 | match where_clause |
331 | .skip_binders() | 330 | .skip_binders() |
@@ -333,11 +332,9 @@ impl ToChalk for GenericPredicate { | |||
333 | .shifted_out(&Interner) | 332 | .shifted_out(&Interner) |
334 | .expect("unexpected bound vars in where clause") | 333 | .expect("unexpected bound vars in where clause") |
335 | { | 334 | { |
336 | chalk_ir::WhereClause::Implemented(tr) => { | 335 | chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), |
337 | GenericPredicate::Implemented(from_chalk(db, tr)) | ||
338 | } | ||
339 | chalk_ir::WhereClause::AliasEq(alias_eq) => { | 336 | chalk_ir::WhereClause::AliasEq(alias_eq) => { |
340 | GenericPredicate::AliasEq(from_chalk(db, alias_eq)) | 337 | WhereClause::AliasEq(from_chalk(db, alias_eq)) |
341 | } | 338 | } |
342 | 339 | ||
343 | chalk_ir::WhereClause::LifetimeOutlives(_) => { | 340 | chalk_ir::WhereClause::LifetimeOutlives(_) => { |
@@ -425,13 +422,15 @@ impl ToChalk for AliasEq { | |||
425 | } | 422 | } |
426 | } | 423 | } |
427 | 424 | ||
428 | impl ToChalk for Obligation { | 425 | impl ToChalk for DomainGoal { |
429 | type Chalk = chalk_ir::DomainGoal<Interner>; | 426 | type Chalk = chalk_ir::DomainGoal<Interner>; |
430 | 427 | ||
431 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { | 428 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { |
432 | match self { | 429 | match self { |
433 | Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), | 430 | DomainGoal::Holds(WhereClause::Implemented(tr)) => tr.to_chalk(db).cast(&Interner), |
434 | Obligation::AliasEq(alias_eq) => alias_eq.to_chalk(db).cast(&Interner), | 431 | DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => { |
432 | alias_eq.to_chalk(db).cast(&Interner) | ||
433 | } | ||
435 | } | 434 | } |
436 | } | 435 | } |
437 | 436 | ||
@@ -523,10 +522,6 @@ pub(super) fn convert_where_clauses( | |||
523 | let generic_predicates = db.generic_predicates(def); | 522 | let generic_predicates = db.generic_predicates(def); |
524 | let mut result = Vec::with_capacity(generic_predicates.len()); | 523 | let mut result = Vec::with_capacity(generic_predicates.len()); |
525 | for pred in generic_predicates.iter() { | 524 | for pred in generic_predicates.iter() { |
526 | if pred.value.is_error() { | ||
527 | // skip errored predicates completely | ||
528 | continue; | ||
529 | } | ||
530 | result.push(pred.clone().subst(substs).to_chalk(db)); | 525 | result.push(pred.clone().subst(substs).to_chalk(db)); |
531 | } | 526 | } |
532 | result | 527 | result |
@@ -534,13 +529,13 @@ pub(super) fn convert_where_clauses( | |||
534 | 529 | ||
535 | pub(super) fn generic_predicate_to_inline_bound( | 530 | pub(super) fn generic_predicate_to_inline_bound( |
536 | db: &dyn HirDatabase, | 531 | db: &dyn HirDatabase, |
537 | pred: &GenericPredicate, | 532 | pred: &WhereClause, |
538 | self_ty: &Ty, | 533 | self_ty: &Ty, |
539 | ) -> Option<rust_ir::InlineBound<Interner>> { | 534 | ) -> Option<rust_ir::InlineBound<Interner>> { |
540 | // An InlineBound is like a GenericPredicate, except the self type is left out. | 535 | // An InlineBound is like a GenericPredicate, except the self type is left out. |
541 | // We don't have a special type for this, but Chalk does. | 536 | // We don't have a special type for this, but Chalk does. |
542 | match pred { | 537 | match pred { |
543 | GenericPredicate::Implemented(trait_ref) => { | 538 | WhereClause::Implemented(trait_ref) => { |
544 | if &trait_ref.substitution[0] != self_ty { | 539 | if &trait_ref.substitution[0] != self_ty { |
545 | // we can only convert predicates back to type bounds if they | 540 | // we can only convert predicates back to type bounds if they |
546 | // have the expected self type | 541 | // have the expected self type |
@@ -553,7 +548,7 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
553 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; | 548 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; |
554 | Some(rust_ir::InlineBound::TraitBound(trait_bound)) | 549 | Some(rust_ir::InlineBound::TraitBound(trait_bound)) |
555 | } | 550 | } |
556 | GenericPredicate::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { | 551 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { |
557 | if &projection_ty.substitution[0] != self_ty { | 552 | if &projection_ty.substitution[0] != self_ty { |
558 | return None; | 553 | return None; |
559 | } | 554 | } |
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index b66243d48..1ec1ecd43 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs | |||
@@ -15,7 +15,7 @@ use hir_def::{ | |||
15 | }; | 15 | }; |
16 | use hir_expand::name::{name, Name}; | 16 | use hir_expand::name::{name, Name}; |
17 | 17 | ||
18 | use crate::{db::HirDatabase, GenericPredicate, TraitRef}; | 18 | use crate::{db::HirDatabase, TraitRef, WhereClause}; |
19 | 19 | ||
20 | fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | 20 | fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { |
21 | let resolver = trait_.resolver(db); | 21 | let resolver = trait_.resolver(db); |
@@ -64,7 +64,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr | |||
64 | .iter() | 64 | .iter() |
65 | .filter_map(|pred| { | 65 | .filter_map(|pred| { |
66 | pred.as_ref().filter_map(|pred| match pred { | 66 | pred.as_ref().filter_map(|pred| match pred { |
67 | GenericPredicate::Implemented(tr) => Some(tr.clone()), | 67 | WhereClause::Implemented(tr) => Some(tr.clone()), |
68 | _ => None, | 68 | _ => None, |
69 | }) | 69 | }) |
70 | }) | 70 | }) |
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs index 5722dea3a..00493a6b5 100644 --- a/crates/ide/src/syntax_highlighting/inject.rs +++ b/crates/ide/src/syntax_highlighting/inject.rs | |||
@@ -6,7 +6,7 @@ use either::Either; | |||
6 | use hir::{HasAttrs, InFile, Semantics}; | 6 | use hir::{HasAttrs, InFile, Semantics}; |
7 | use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind}; | 7 | use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind}; |
8 | use syntax::{ | 8 | use syntax::{ |
9 | ast::{self, AstNode, AttrsOwner, DocCommentsOwner}, | 9 | ast::{self, AstNode}, |
10 | match_ast, AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, | 10 | match_ast, AstToken, NodeOrToken, SyntaxNode, SyntaxToken, TextRange, TextSize, |
11 | }; | 11 | }; |
12 | 12 | ||
@@ -89,57 +89,27 @@ const RUSTDOC_FENCE_TOKENS: &[&'static str] = &[ | |||
89 | "edition2021", | 89 | "edition2021", |
90 | ]; | 90 | ]; |
91 | 91 | ||
92 | // Basically an owned dyn AttrsOwner without extra Boxing | ||
93 | struct AttrsOwnerNode { | ||
94 | node: SyntaxNode, | ||
95 | } | ||
96 | |||
97 | impl AttrsOwnerNode { | ||
98 | fn new<N: DocCommentsOwner>(node: N) -> Self { | ||
99 | AttrsOwnerNode { node: node.syntax().clone() } | ||
100 | } | ||
101 | } | ||
102 | |||
103 | impl AttrsOwner for AttrsOwnerNode {} | ||
104 | impl AstNode for AttrsOwnerNode { | ||
105 | fn can_cast(_: syntax::SyntaxKind) -> bool | ||
106 | where | ||
107 | Self: Sized, | ||
108 | { | ||
109 | false | ||
110 | } | ||
111 | fn cast(_: SyntaxNode) -> Option<Self> | ||
112 | where | ||
113 | Self: Sized, | ||
114 | { | ||
115 | None | ||
116 | } | ||
117 | fn syntax(&self) -> &SyntaxNode { | ||
118 | &self.node | ||
119 | } | ||
120 | } | ||
121 | |||
122 | fn doc_attributes<'node>( | 92 | fn doc_attributes<'node>( |
123 | sema: &Semantics<RootDatabase>, | 93 | sema: &Semantics<RootDatabase>, |
124 | node: &'node SyntaxNode, | 94 | node: &'node SyntaxNode, |
125 | ) -> Option<(AttrsOwnerNode, hir::Attrs, Definition)> { | 95 | ) -> Option<(hir::AttrsWithOwner, Definition)> { |
126 | match_ast! { | 96 | match_ast! { |
127 | match node { | 97 | match node { |
128 | ast::SourceFile(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))), | 98 | ast::SourceFile(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))), |
129 | ast::Module(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))), | 99 | ast::Module(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Module(def)))), |
130 | ast::Fn(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Function(def)))), | 100 | ast::Fn(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Function(def)))), |
131 | ast::Struct(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(def))))), | 101 | ast::Struct(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Struct(def))))), |
132 | ast::Union(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Union(def))))), | 102 | ast::Union(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Union(def))))), |
133 | ast::Enum(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(def))))), | 103 | ast::Enum(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(def))))), |
134 | ast::Variant(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Variant(def)))), | 104 | ast::Variant(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Variant(def)))), |
135 | ast::Trait(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Trait(def)))), | 105 | ast::Trait(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Trait(def)))), |
136 | ast::Static(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Static(def)))), | 106 | ast::Static(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Static(def)))), |
137 | ast::Const(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Const(def)))), | 107 | ast::Const(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::Const(def)))), |
138 | ast::TypeAlias(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::TypeAlias(def)))), | 108 | ast::TypeAlias(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::ModuleDef(hir::ModuleDef::TypeAlias(def)))), |
139 | ast::Impl(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::SelfType(def))), | 109 | ast::Impl(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::SelfType(def))), |
140 | ast::RecordField(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::Field(def))), | 110 | ast::RecordField(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Field(def))), |
141 | ast::TupleField(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::Field(def))), | 111 | ast::TupleField(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Field(def))), |
142 | ast::MacroRules(it) => sema.to_def(&it).map(|def| (AttrsOwnerNode::new(it), def.attrs(sema.db), Definition::Macro(def))), | 112 | ast::MacroRules(it) => sema.to_def(&it).map(|def| (def.attrs(sema.db), Definition::Macro(def))), |
143 | // ast::MacroDef(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))), | 113 | // ast::MacroDef(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))), |
144 | // ast::Use(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))), | 114 | // ast::Use(it) => sema.to_def(&it).map(|def| (Box::new(it) as _, def.attrs(sema.db))), |
145 | _ => return None | 115 | _ => return None |
@@ -153,7 +123,7 @@ pub(super) fn doc_comment( | |||
153 | sema: &Semantics<RootDatabase>, | 123 | sema: &Semantics<RootDatabase>, |
154 | node: InFile<&SyntaxNode>, | 124 | node: InFile<&SyntaxNode>, |
155 | ) { | 125 | ) { |
156 | let (owner, attributes, def) = match doc_attributes(sema, node.value) { | 126 | let (attributes, def) = match doc_attributes(sema, node.value) { |
157 | Some(it) => it, | 127 | Some(it) => it, |
158 | None => return, | 128 | None => return, |
159 | }; | 129 | }; |
@@ -161,12 +131,7 @@ pub(super) fn doc_comment( | |||
161 | let mut inj = Injector::default(); | 131 | let mut inj = Injector::default(); |
162 | inj.add_unmapped("fn doctest() {\n"); | 132 | inj.add_unmapped("fn doctest() {\n"); |
163 | 133 | ||
164 | let attrs_source_map = match def { | 134 | let attrs_source_map = attributes.source_map(sema.db); |
165 | Definition::ModuleDef(hir::ModuleDef::Module(module)) => { | ||
166 | attributes.source_map_for_module(sema.db, module.into()) | ||
167 | } | ||
168 | _ => attributes.source_map(node.with_value(&owner)), | ||
169 | }; | ||
170 | 135 | ||
171 | let mut is_codeblock = false; | 136 | let mut is_codeblock = false; |
172 | let mut is_doctest = false; | 137 | let mut is_doctest = false; |
diff --git a/crates/ide_assists/src/handlers/move_bounds.rs b/crates/ide_assists/src/handlers/move_bounds.rs index 9ad0c9816..b5dec8014 100644 --- a/crates/ide_assists/src/handlers/move_bounds.rs +++ b/crates/ide_assists/src/handlers/move_bounds.rs | |||
@@ -50,8 +50,8 @@ pub(crate) fn move_bounds_to_where_clause(acc: &mut Assists, ctx: &AssistContext | |||
50 | 50 | ||
51 | for type_param in type_param_list.type_params() { | 51 | for type_param in type_param_list.type_params() { |
52 | if let Some(tbl) = type_param.type_bound_list() { | 52 | if let Some(tbl) = type_param.type_bound_list() { |
53 | if let Some(predicate) = build_predicate(type_param.clone()) { | 53 | if let Some(predicate) = build_predicate(type_param) { |
54 | where_clause.add_predicate(predicate.clone_for_update()) | 54 | where_clause.add_predicate(predicate) |
55 | } | 55 | } |
56 | tbl.remove() | 56 | tbl.remove() |
57 | } | 57 | } |
@@ -69,7 +69,7 @@ fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> { | |||
69 | make::path_unqualified(segment) | 69 | make::path_unqualified(segment) |
70 | }; | 70 | }; |
71 | let predicate = make::where_pred(path, param.type_bound_list()?.bounds()); | 71 | let predicate = make::where_pred(path, param.type_bound_list()?.bounds()); |
72 | Some(predicate) | 72 | Some(predicate.clone_for_update()) |
73 | } | 73 | } |
74 | 74 | ||
75 | #[cfg(test)] | 75 | #[cfg(test)] |
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs index 38e0b04ef..7f472d4db 100644 --- a/crates/syntax/src/ast.rs +++ b/crates/syntax/src/ast.rs | |||
@@ -20,8 +20,8 @@ pub use self::{ | |||
20 | expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp}, | 20 | expr_ext::{ArrayExprKind, BinOp, Effect, ElseBranch, LiteralKind, PrefixOp, RangeOp}, |
21 | generated::{nodes::*, tokens::*}, | 21 | generated::{nodes::*, tokens::*}, |
22 | node_ext::{ | 22 | node_ext::{ |
23 | AttrKind, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, SelfParamKind, | 23 | AttrKind, AttrsOwnerNode, FieldKind, Macro, NameLike, NameOrNameRef, PathSegmentKind, |
24 | SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind, | 24 | SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind, VisibilityKind, |
25 | }, | 25 | }, |
26 | token_ext::*, | 26 | token_ext::*, |
27 | traits::*, | 27 | traits::*, |
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs index 449b058fb..b1eed0a2c 100644 --- a/crates/syntax/src/ast/edit_in_place.rs +++ b/crates/syntax/src/ast/edit_in_place.rs | |||
@@ -8,7 +8,7 @@ use parser::T; | |||
8 | use crate::{ | 8 | use crate::{ |
9 | ast, | 9 | ast, |
10 | ted::{self, Position}, | 10 | ted::{self, Position}, |
11 | AstNode, Direction, SyntaxElement, | 11 | AstNode, Direction, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | use super::NameOwner; | 14 | use super::NameOwner; |
@@ -21,11 +21,11 @@ impl GenericParamsOwnerEdit for ast::Fn { | |||
21 | fn get_or_create_where_clause(&self) -> WhereClause { | 21 | fn get_or_create_where_clause(&self) -> WhereClause { |
22 | if self.where_clause().is_none() { | 22 | if self.where_clause().is_none() { |
23 | let position = if let Some(ty) = self.ret_type() { | 23 | let position = if let Some(ty) = self.ret_type() { |
24 | Position::after(ty.syntax().clone()) | 24 | Position::after(ty.syntax()) |
25 | } else if let Some(param_list) = self.param_list() { | 25 | } else if let Some(param_list) = self.param_list() { |
26 | Position::after(param_list.syntax().clone()) | 26 | Position::after(param_list.syntax()) |
27 | } else { | 27 | } else { |
28 | Position::last_child_of(self.syntax().clone()) | 28 | Position::last_child_of(self.syntax()) |
29 | }; | 29 | }; |
30 | create_where_clause(position) | 30 | create_where_clause(position) |
31 | } | 31 | } |
@@ -37,9 +37,9 @@ impl GenericParamsOwnerEdit for ast::Impl { | |||
37 | fn get_or_create_where_clause(&self) -> WhereClause { | 37 | fn get_or_create_where_clause(&self) -> WhereClause { |
38 | if self.where_clause().is_none() { | 38 | if self.where_clause().is_none() { |
39 | let position = if let Some(items) = self.assoc_item_list() { | 39 | let position = if let Some(items) = self.assoc_item_list() { |
40 | Position::before(items.syntax().clone()) | 40 | Position::before(items.syntax()) |
41 | } else { | 41 | } else { |
42 | Position::last_child_of(self.syntax().clone()) | 42 | Position::last_child_of(self.syntax()) |
43 | }; | 43 | }; |
44 | create_where_clause(position) | 44 | create_where_clause(position) |
45 | } | 45 | } |
@@ -51,9 +51,9 @@ impl GenericParamsOwnerEdit for ast::Trait { | |||
51 | fn get_or_create_where_clause(&self) -> WhereClause { | 51 | fn get_or_create_where_clause(&self) -> WhereClause { |
52 | if self.where_clause().is_none() { | 52 | if self.where_clause().is_none() { |
53 | let position = if let Some(items) = self.assoc_item_list() { | 53 | let position = if let Some(items) = self.assoc_item_list() { |
54 | Position::before(items.syntax().clone()) | 54 | Position::before(items.syntax()) |
55 | } else { | 55 | } else { |
56 | Position::last_child_of(self.syntax().clone()) | 56 | Position::last_child_of(self.syntax()) |
57 | }; | 57 | }; |
58 | create_where_clause(position) | 58 | create_where_clause(position) |
59 | } | 59 | } |
@@ -69,13 +69,13 @@ impl GenericParamsOwnerEdit for ast::Struct { | |||
69 | ast::FieldList::TupleFieldList(it) => Some(it), | 69 | ast::FieldList::TupleFieldList(it) => Some(it), |
70 | }); | 70 | }); |
71 | let position = if let Some(tfl) = tfl { | 71 | let position = if let Some(tfl) = tfl { |
72 | Position::after(tfl.syntax().clone()) | 72 | Position::after(tfl.syntax()) |
73 | } else if let Some(gpl) = self.generic_param_list() { | 73 | } else if let Some(gpl) = self.generic_param_list() { |
74 | Position::after(gpl.syntax().clone()) | 74 | Position::after(gpl.syntax()) |
75 | } else if let Some(name) = self.name() { | 75 | } else if let Some(name) = self.name() { |
76 | Position::after(name.syntax().clone()) | 76 | Position::after(name.syntax()) |
77 | } else { | 77 | } else { |
78 | Position::last_child_of(self.syntax().clone()) | 78 | Position::last_child_of(self.syntax()) |
79 | }; | 79 | }; |
80 | create_where_clause(position) | 80 | create_where_clause(position) |
81 | } | 81 | } |
@@ -87,11 +87,11 @@ impl GenericParamsOwnerEdit for ast::Enum { | |||
87 | fn get_or_create_where_clause(&self) -> WhereClause { | 87 | fn get_or_create_where_clause(&self) -> WhereClause { |
88 | if self.where_clause().is_none() { | 88 | if self.where_clause().is_none() { |
89 | let position = if let Some(gpl) = self.generic_param_list() { | 89 | let position = if let Some(gpl) = self.generic_param_list() { |
90 | Position::after(gpl.syntax().clone()) | 90 | Position::after(gpl.syntax()) |
91 | } else if let Some(name) = self.name() { | 91 | } else if let Some(name) = self.name() { |
92 | Position::after(name.syntax().clone()) | 92 | Position::after(name.syntax()) |
93 | } else { | 93 | } else { |
94 | Position::last_child_of(self.syntax().clone()) | 94 | Position::last_child_of(self.syntax()) |
95 | }; | 95 | }; |
96 | create_where_clause(position) | 96 | create_where_clause(position) |
97 | } | 97 | } |
@@ -100,19 +100,18 @@ impl GenericParamsOwnerEdit for ast::Enum { | |||
100 | } | 100 | } |
101 | 101 | ||
102 | fn create_where_clause(position: Position) { | 102 | fn create_where_clause(position: Position) { |
103 | let where_clause: SyntaxElement = | 103 | let where_clause = make::where_clause(empty()).clone_for_update(); |
104 | make::where_clause(empty()).clone_for_update().syntax().clone().into(); | 104 | ted::insert(position, where_clause.syntax()); |
105 | ted::insert(position, where_clause); | ||
106 | } | 105 | } |
107 | 106 | ||
108 | impl ast::WhereClause { | 107 | impl ast::WhereClause { |
109 | pub fn add_predicate(&self, predicate: ast::WherePred) { | 108 | pub fn add_predicate(&self, predicate: ast::WherePred) { |
110 | if let Some(pred) = self.predicates().last() { | 109 | if let Some(pred) = self.predicates().last() { |
111 | if !pred.syntax().siblings_with_tokens(Direction::Next).any(|it| it.kind() == T![,]) { | 110 | if !pred.syntax().siblings_with_tokens(Direction::Next).any(|it| it.kind() == T![,]) { |
112 | ted::append_child_raw(self.syntax().clone(), make::token(T![,])); | 111 | ted::append_child_raw(self.syntax(), make::token(T![,])); |
113 | } | 112 | } |
114 | } | 113 | } |
115 | ted::append_child(self.syntax().clone(), predicate.syntax().clone()) | 114 | ted::append_child(self.syntax(), predicate.syntax()) |
116 | } | 115 | } |
117 | } | 116 | } |
118 | 117 | ||
@@ -123,7 +122,7 @@ impl ast::TypeBoundList { | |||
123 | { | 122 | { |
124 | ted::remove_all(colon..=self.syntax().clone().into()) | 123 | ted::remove_all(colon..=self.syntax().clone().into()) |
125 | } else { | 124 | } else { |
126 | ted::remove(self.syntax().clone()) | 125 | ted::remove(self.syntax()) |
127 | } | 126 | } |
128 | } | 127 | } |
129 | } | 128 | } |
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs index 5a9834cbb..01f580a40 100644 --- a/crates/syntax/src/ast/node_ext.rs +++ b/crates/syntax/src/ast/node_ext.rs | |||
@@ -90,6 +90,36 @@ impl NameOwner for Macro { | |||
90 | 90 | ||
91 | impl AttrsOwner for Macro {} | 91 | impl AttrsOwner for Macro {} |
92 | 92 | ||
93 | /// Basically an owned `dyn AttrsOwner` without extra boxing. | ||
94 | pub struct AttrsOwnerNode { | ||
95 | node: SyntaxNode, | ||
96 | } | ||
97 | |||
98 | impl AttrsOwnerNode { | ||
99 | pub fn new<N: AttrsOwner>(node: N) -> Self { | ||
100 | AttrsOwnerNode { node: node.syntax().clone() } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | impl AttrsOwner for AttrsOwnerNode {} | ||
105 | impl AstNode for AttrsOwnerNode { | ||
106 | fn can_cast(_: SyntaxKind) -> bool | ||
107 | where | ||
108 | Self: Sized, | ||
109 | { | ||
110 | false | ||
111 | } | ||
112 | fn cast(_: SyntaxNode) -> Option<Self> | ||
113 | where | ||
114 | Self: Sized, | ||
115 | { | ||
116 | None | ||
117 | } | ||
118 | fn syntax(&self) -> &SyntaxNode { | ||
119 | &self.node | ||
120 | } | ||
121 | } | ||
122 | |||
93 | #[derive(Debug, Clone, PartialEq, Eq)] | 123 | #[derive(Debug, Clone, PartialEq, Eq)] |
94 | pub enum AttrKind { | 124 | pub enum AttrKind { |
95 | Inner, | 125 | Inner, |
diff --git a/crates/syntax/src/ted.rs b/crates/syntax/src/ted.rs index 442dfa14a..be2b846b1 100644 --- a/crates/syntax/src/ted.rs +++ b/crates/syntax/src/ted.rs | |||
@@ -8,6 +8,33 @@ use parser::T; | |||
8 | 8 | ||
9 | use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; | 9 | use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; |
10 | 10 | ||
11 | /// Utility trait to allow calling `ted` functions with references or owned | ||
12 | /// nodes. Do not use outside of this module. | ||
13 | pub trait Element { | ||
14 | fn syntax_element(self) -> SyntaxElement; | ||
15 | } | ||
16 | |||
17 | impl<E: Element + Clone> Element for &'_ E { | ||
18 | fn syntax_element(self) -> SyntaxElement { | ||
19 | self.clone().syntax_element() | ||
20 | } | ||
21 | } | ||
22 | impl Element for SyntaxElement { | ||
23 | fn syntax_element(self) -> SyntaxElement { | ||
24 | self | ||
25 | } | ||
26 | } | ||
27 | impl Element for SyntaxNode { | ||
28 | fn syntax_element(self) -> SyntaxElement { | ||
29 | self.into() | ||
30 | } | ||
31 | } | ||
32 | impl Element for SyntaxToken { | ||
33 | fn syntax_element(self) -> SyntaxElement { | ||
34 | self.into() | ||
35 | } | ||
36 | } | ||
37 | |||
11 | #[derive(Debug)] | 38 | #[derive(Debug)] |
12 | pub struct Position { | 39 | pub struct Position { |
13 | repr: PositionRepr, | 40 | repr: PositionRepr, |
@@ -20,24 +47,24 @@ enum PositionRepr { | |||
20 | } | 47 | } |
21 | 48 | ||
22 | impl Position { | 49 | impl Position { |
23 | pub fn after(elem: impl Into<SyntaxElement>) -> Position { | 50 | pub fn after(elem: impl Element) -> Position { |
24 | let repr = PositionRepr::After(elem.into()); | 51 | let repr = PositionRepr::After(elem.syntax_element()); |
25 | Position { repr } | 52 | Position { repr } |
26 | } | 53 | } |
27 | pub fn before(elem: impl Into<SyntaxElement>) -> Position { | 54 | pub fn before(elem: impl Element) -> Position { |
28 | let elem = elem.into(); | 55 | let elem = elem.syntax_element(); |
29 | let repr = match elem.prev_sibling_or_token() { | 56 | let repr = match elem.prev_sibling_or_token() { |
30 | Some(it) => PositionRepr::After(it), | 57 | Some(it) => PositionRepr::After(it), |
31 | None => PositionRepr::FirstChild(elem.parent().unwrap()), | 58 | None => PositionRepr::FirstChild(elem.parent().unwrap()), |
32 | }; | 59 | }; |
33 | Position { repr } | 60 | Position { repr } |
34 | } | 61 | } |
35 | pub fn first_child_of(node: impl Into<SyntaxNode>) -> Position { | 62 | pub fn first_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position { |
36 | let repr = PositionRepr::FirstChild(node.into()); | 63 | let repr = PositionRepr::FirstChild(node.clone().into()); |
37 | Position { repr } | 64 | Position { repr } |
38 | } | 65 | } |
39 | pub fn last_child_of(node: impl Into<SyntaxNode>) -> Position { | 66 | pub fn last_child_of(node: &(impl Into<SyntaxNode> + Clone)) -> Position { |
40 | let node = node.into(); | 67 | let node = node.clone().into(); |
41 | let repr = match node.last_child_or_token() { | 68 | let repr = match node.last_child_or_token() { |
42 | Some(it) => PositionRepr::After(it), | 69 | Some(it) => PositionRepr::After(it), |
43 | None => PositionRepr::FirstChild(node), | 70 | None => PositionRepr::FirstChild(node), |
@@ -46,11 +73,11 @@ impl Position { | |||
46 | } | 73 | } |
47 | } | 74 | } |
48 | 75 | ||
49 | pub fn insert(position: Position, elem: impl Into<SyntaxElement>) { | 76 | pub fn insert(position: Position, elem: impl Element) { |
50 | insert_all(position, vec![elem.into()]) | 77 | insert_all(position, vec![elem.syntax_element()]) |
51 | } | 78 | } |
52 | pub fn insert_raw(position: Position, elem: impl Into<SyntaxElement>) { | 79 | pub fn insert_raw(position: Position, elem: impl Element) { |
53 | insert_all_raw(position, vec![elem.into()]) | 80 | insert_all_raw(position, vec![elem.syntax_element()]) |
54 | } | 81 | } |
55 | pub fn insert_all(position: Position, mut elements: Vec<SyntaxElement>) { | 82 | pub fn insert_all(position: Position, mut elements: Vec<SyntaxElement>) { |
56 | if let Some(first) = elements.first() { | 83 | if let Some(first) = elements.first() { |
@@ -73,17 +100,17 @@ pub fn insert_all_raw(position: Position, elements: Vec<SyntaxElement>) { | |||
73 | parent.splice_children(index..index, elements); | 100 | parent.splice_children(index..index, elements); |
74 | } | 101 | } |
75 | 102 | ||
76 | pub fn remove(elem: impl Into<SyntaxElement>) { | 103 | pub fn remove(elem: impl Element) { |
77 | let elem = elem.into(); | 104 | let elem = elem.syntax_element(); |
78 | remove_all(elem.clone()..=elem) | 105 | remove_all(elem.clone()..=elem) |
79 | } | 106 | } |
80 | pub fn remove_all(range: RangeInclusive<SyntaxElement>) { | 107 | pub fn remove_all(range: RangeInclusive<SyntaxElement>) { |
81 | replace_all(range, Vec::new()) | 108 | replace_all(range, Vec::new()) |
82 | } | 109 | } |
83 | 110 | ||
84 | pub fn replace(old: impl Into<SyntaxElement>, new: impl Into<SyntaxElement>) { | 111 | pub fn replace(old: impl Element, new: impl Element) { |
85 | let old = old.into(); | 112 | let old = old.syntax_element(); |
86 | replace_all(old.clone()..=old, vec![new.into()]) | 113 | replace_all(old.clone()..=old, vec![new.syntax_element()]) |
87 | } | 114 | } |
88 | pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) { | 115 | pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) { |
89 | let start = range.start().index(); | 116 | let start = range.start().index(); |
@@ -92,11 +119,11 @@ pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement> | |||
92 | parent.splice_children(start..end + 1, new) | 119 | parent.splice_children(start..end + 1, new) |
93 | } | 120 | } |
94 | 121 | ||
95 | pub fn append_child(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) { | 122 | pub fn append_child(node: &(impl Into<SyntaxNode> + Clone), child: impl Element) { |
96 | let position = Position::last_child_of(node); | 123 | let position = Position::last_child_of(node); |
97 | insert(position, child) | 124 | insert(position, child) |
98 | } | 125 | } |
99 | pub fn append_child_raw(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) { | 126 | pub fn append_child_raw(node: &(impl Into<SyntaxNode> + Clone), child: impl Element) { |
100 | let position = Position::last_child_of(node); | 127 | let position = Position::last_child_of(node); |
101 | insert_raw(position, child) | 128 | insert_raw(position, child) |
102 | } | 129 | } |