aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/attrs.rs8
-rw-r--r--crates/hir/src/has_source.rs15
-rw-r--r--crates/hir/src/lib.rs23
-rw-r--r--crates/hir_def/src/attr.rs311
-rw-r--r--crates/hir_def/src/db.rs6
-rw-r--r--crates/hir_def/src/nameres/collector.rs50
-rw-r--r--crates/hir_def/src/nameres/tests/mod_resolution.rs19
-rw-r--r--crates/hir_expand/src/hygiene.rs2
-rw-r--r--crates/hir_expand/src/lib.rs9
-rw-r--r--crates/hir_ty/src/autoderef.rs9
-rw-r--r--crates/hir_ty/src/chalk_cast.rs53
-rw-r--r--crates/hir_ty/src/db.rs13
-rw-r--r--crates/hir_ty/src/display.rs55
-rw-r--r--crates/hir_ty/src/infer.rs12
-rw-r--r--crates/hir_ty/src/infer/coerce.rs7
-rw-r--r--crates/hir_ty/src/infer/expr.rs25
-rw-r--r--crates/hir_ty/src/infer/path.rs12
-rw-r--r--crates/hir_ty/src/infer/unify.rs30
-rw-r--r--crates/hir_ty/src/lib.rs48
-rw-r--r--crates/hir_ty/src/lower.rs40
-rw-r--r--crates/hir_ty/src/method_resolution.rs6
-rw-r--r--crates/hir_ty/src/tests/traits.rs4
-rw-r--r--crates/hir_ty/src/traits.rs35
-rw-r--r--crates/hir_ty/src/traits/chalk.rs16
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs41
-rw-r--r--crates/hir_ty/src/utils.rs4
-rw-r--r--crates/ide/src/syntax_highlighting/inject.rs73
-rw-r--r--crates/ide_assists/src/handlers/move_bounds.rs6
-rw-r--r--crates/syntax/src/ast.rs4
-rw-r--r--crates/syntax/src/ast/edit_in_place.rs41
-rw-r--r--crates/syntax/src/ast/node_ext.rs30
-rw-r--r--crates/syntax/src/ted.rs65
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.
2use hir_def::{ 2use 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
18pub trait HasAttrs { 18pub 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 {
36macro_rules! impl_has_attrs { 36macro_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![
70macro_rules! impl_has_attrs_enum { 70macro_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};
9use hir_expand::{InFile, MacroDefKind}; 9use hir_expand::InFile;
10use syntax::ast; 10use syntax::ast;
11 11
12use crate::{ 12use crate::{
@@ -113,15 +113,10 @@ impl HasSource for TypeAlias {
113impl HasSource for MacroDef { 113impl 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}
127impl HasSource for Impl { 122impl 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};
63use itertools::Itertools; 63use itertools::Itertools;
64use rustc_hash::FxHashSet; 64use rustc_hash::FxHashSet;
@@ -89,7 +89,7 @@ pub use crate::{
89pub use { 89pub 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)]
52pub struct Attrs(RawAttrs); 52pub struct Attrs(RawAttrs);
53 53
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct AttrsWithOwner {
56 attrs: Attrs,
57 owner: AttrDefId,
58}
59
54impl ops::Deref for RawAttrs { 60impl 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
82impl ops::Deref for AttrsWithOwner {
83 type Target = Attrs;
84
85 fn deref(&self) -> &Attrs {
86 &self.attrs
87 }
88}
89
76impl RawAttrs { 90impl 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 {
169impl Attrs { 183impl 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
282impl 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
389fn inner_attributes( 456fn 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
9use crate::{ 9use 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]
824fn cfg_in_module_file() {
825 // Inner `#![cfg]` in a module file makes the whole module disappear.
826 check(
827 r#"
828//- /main.rs
829mod module;
830
831//- /module.rs
832#![cfg(NEVER)]
833
834struct 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;
15pub mod quote; 15pub mod quote;
16pub mod eager; 16pub mod eager;
17 17
18use either::Either;
18pub use mbe::{ExpandError, ExpandResult}; 19pub use mbe::{ExpandError, ExpandResult};
19 20
20use std::hash::Hash; 21use 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 @@
6use std::iter::successors; 6use std::iter::successors;
7 7
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::cast::Cast;
9use hir_def::lang_item::LangItemTarget; 10use hir_def::lang_item::LangItemTarget;
10use hir_expand::name::name; 11use hir_expand::name::name;
11use log::{info, warn}; 12use 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
22const AUTODEREF_RECURSION_LIMIT: usize = 10; 23const 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
3use chalk_ir::{
4 cast::{Cast, CastTo},
5 interner::HasInterner,
6};
7
8use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause};
9
10macro_rules! has_interner {
11 ($t:ty) => {
12 impl HasInterner for $t {
13 type Interner = crate::Interner;
14 }
15 };
16}
17
18has_interner!(WhereClause);
19has_interner!(DomainGoal);
20
21impl CastTo<WhereClause> for TraitRef {
22 fn cast_to(self, _interner: &Interner) -> WhereClause {
23 WhereClause::Implemented(self)
24 }
25}
26
27impl CastTo<WhereClause> for AliasEq {
28 fn cast_to(self, _interner: &Interner) -> WhereClause {
29 WhereClause::AliasEq(self)
30 }
31}
32
33impl CastTo<DomainGoal> for WhereClause {
34 fn cast_to(self, _interner: &Interner) -> DomainGoal {
35 DomainGoal::Holds(self)
36 }
37}
38
39macro_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
52transitive_impl!(TraitRef, WhereClause, DomainGoal);
53transitive_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;
12use crate::{ 12use 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};
18use hir_expand::name::Name; 18use 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;
19use crate::{ 19use 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
26pub struct HirFormatter<'a> { 26pub 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
653pub fn write_bounds_like_dyn_trait_with_prefix( 653pub 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
667fn write_bounds_like_dyn_trait( 667fn 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
781impl HirDisplay for GenericPredicate { 771impl 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
821impl HirDisplay for Obligation { 808impl 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;
18use std::ops::Index; 18use std::ops::Index;
19use std::sync::Arc; 19use std::sync::Arc;
20 20
21use chalk_ir::Mutability; 21use chalk_ir::{cast::Cast, Mutability};
22use hir_def::{ 22use 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;
37use syntax::SmolStr; 37use syntax::SmolStr;
38 38
39use super::{ 39use 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};
43use crate::{ 43use 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
7use chalk_ir::{Mutability, TyVariableKind}; 7use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9 9
10use crate::{ 10use 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
15use super::{InEnvironment, InferenceContext}; 14use 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 @@
3use std::iter::{repeat, repeat_with}; 3use std::iter::{repeat, repeat_with};
4use std::{mem, sync::Arc}; 4use std::{mem, sync::Arc};
5 5
6use chalk_ir::{Mutability, TyVariableKind}; 6use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
7use hir_def::{ 7use 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
3use std::iter; 3use std::iter;
4 4
5use chalk_ir::cast::Cast;
5use hir_def::{ 6use 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;
5use chalk_ir::{FloatTy, IntTy, TyVariableKind}; 5use chalk_ir::{FloatTy, IntTy, TyVariableKind};
6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 7
8use super::{InferenceContext, Obligation}; 8use super::{DomainGoal, InferenceContext};
9use crate::{ 9use 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
14impl<'a> InferenceContext<'a> { 14impl<'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;
13mod lower; 13mod lower;
14pub(crate) mod infer; 14pub(crate) mod infer;
15pub(crate) mod utils; 15pub(crate) mod utils;
16mod chalk_cast;
16 17
17pub mod display; 18pub mod display;
18pub mod db; 19pub 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};
48pub use traits::{AliasEq, InEnvironment, Obligation, TraitEnvironment}; 49pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment};
49 50
50pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind}; 51pub use chalk_ir::{
52 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
53};
51 54
52pub use crate::traits::chalk::Interner; 55pub 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)]
567pub enum GenericPredicate { 570pub 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
577impl GenericPredicate { 577impl 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
597impl TypeWalk for GenericPredicate { 593impl 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)]
1168pub(crate) struct ReturnTypeImplTrait { 1162pub(crate) struct ReturnTypeImplTrait {
1169 pub(crate) bounds: Binders<Vec<GenericPredicate>>, 1163 pub(crate) bounds: Binders<Vec<WhereClause>>,
1170} 1164}
1171 1165
1172pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { 1166pub 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(
881pub(crate) fn generic_predicates_for_param_query( 878pub(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(
966pub(crate) fn generic_predicates_query( 960pub(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
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::Mutability; 9use chalk_ir::{cast::Cast, Mutability};
10use hir_def::{ 10use 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};
9use stdx::panic_context; 9use stdx::panic_context;
10 10
11use crate::{ 11use 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
16use self::chalk::{from_chalk, Interner, ToChalk}; 16use 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)]
91pub enum Obligation { 91pub 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
98impl 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 {
137pub(crate) fn trait_solve_query( 124pub(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};
27use mapping::{ 27use 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
21use super::interner::*; 21use 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
307impl ToChalk for GenericPredicate { 307impl 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
428impl ToChalk for Obligation { 425impl 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
535pub(super) fn generic_predicate_to_inline_bound( 530pub(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};
16use hir_expand::name::{name, Name}; 16use hir_expand::name::{name, Name};
17 17
18use crate::{db::HirDatabase, GenericPredicate, TraitRef}; 18use crate::{db::HirDatabase, TraitRef, WhereClause};
19 19
20fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 20fn 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;
6use hir::{HasAttrs, InFile, Semantics}; 6use hir::{HasAttrs, InFile, Semantics};
7use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind}; 7use ide_db::{call_info::ActiveParameter, defs::Definition, SymbolKind};
8use syntax::{ 8use 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
93struct AttrsOwnerNode {
94 node: SyntaxNode,
95}
96
97impl AttrsOwnerNode {
98 fn new<N: DocCommentsOwner>(node: N) -> Self {
99 AttrsOwnerNode { node: node.syntax().clone() }
100 }
101}
102
103impl AttrsOwner for AttrsOwnerNode {}
104impl 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
122fn doc_attributes<'node>( 92fn 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;
8use crate::{ 8use crate::{
9 ast, 9 ast,
10 ted::{self, Position}, 10 ted::{self, Position},
11 AstNode, Direction, SyntaxElement, 11 AstNode, Direction,
12}; 12};
13 13
14use super::NameOwner; 14use 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
102fn create_where_clause(position: Position) { 102fn 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
108impl ast::WhereClause { 107impl 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
91impl AttrsOwner for Macro {} 91impl AttrsOwner for Macro {}
92 92
93/// Basically an owned `dyn AttrsOwner` without extra boxing.
94pub struct AttrsOwnerNode {
95 node: SyntaxNode,
96}
97
98impl AttrsOwnerNode {
99 pub fn new<N: AttrsOwner>(node: N) -> Self {
100 AttrsOwnerNode { node: node.syntax().clone() }
101 }
102}
103
104impl AttrsOwner for AttrsOwnerNode {}
105impl 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)]
94pub enum AttrKind { 124pub 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
9use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; 9use 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.
13pub trait Element {
14 fn syntax_element(self) -> SyntaxElement;
15}
16
17impl<E: Element + Clone> Element for &'_ E {
18 fn syntax_element(self) -> SyntaxElement {
19 self.clone().syntax_element()
20 }
21}
22impl Element for SyntaxElement {
23 fn syntax_element(self) -> SyntaxElement {
24 self
25 }
26}
27impl Element for SyntaxNode {
28 fn syntax_element(self) -> SyntaxElement {
29 self.into()
30 }
31}
32impl Element for SyntaxToken {
33 fn syntax_element(self) -> SyntaxElement {
34 self.into()
35 }
36}
37
11#[derive(Debug)] 38#[derive(Debug)]
12pub struct Position { 39pub struct Position {
13 repr: PositionRepr, 40 repr: PositionRepr,
@@ -20,24 +47,24 @@ enum PositionRepr {
20} 47}
21 48
22impl Position { 49impl 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
49pub fn insert(position: Position, elem: impl Into<SyntaxElement>) { 76pub fn insert(position: Position, elem: impl Element) {
50 insert_all(position, vec![elem.into()]) 77 insert_all(position, vec![elem.syntax_element()])
51} 78}
52pub fn insert_raw(position: Position, elem: impl Into<SyntaxElement>) { 79pub 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}
55pub fn insert_all(position: Position, mut elements: Vec<SyntaxElement>) { 82pub 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
76pub fn remove(elem: impl Into<SyntaxElement>) { 103pub 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}
80pub fn remove_all(range: RangeInclusive<SyntaxElement>) { 107pub fn remove_all(range: RangeInclusive<SyntaxElement>) {
81 replace_all(range, Vec::new()) 108 replace_all(range, Vec::new())
82} 109}
83 110
84pub fn replace(old: impl Into<SyntaxElement>, new: impl Into<SyntaxElement>) { 111pub 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}
88pub fn replace_all(range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) { 115pub 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
95pub fn append_child(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) { 122pub 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}
99pub fn append_child_raw(node: impl Into<SyntaxNode>, child: impl Into<SyntaxElement>) { 126pub 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}